LCOV - code coverage report
Current view: top level - native - localref.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 98 146 67.1 %
Date: 2017-07-14 10:03:36 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /* src/native/localref.cpp - Management of local reference tables
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : 
      26             : #include "config.h"
      27             : 
      28             : #include <assert.h>
      29             : #include <stdint.h>
      30             : 
      31             : #include "mm/gc.hpp"
      32             : #include "mm/memory.hpp"
      33             : 
      34             : #include "native/localref.hpp"
      35             : 
      36             : #include "threads/thread.hpp"
      37             : 
      38             : #include "toolbox/logging.hpp"
      39             : 
      40             : #include "vm/descriptor.hpp"
      41             : #include "vm/options.hpp"
      42             : #include "vm/vm.hpp"
      43             : 
      44             : #include "vm/jit/argument.hpp"
      45             : 
      46             : 
      47             : #define LOCALREFTABLE    (THREADOBJECT->_localref_table)
      48             : 
      49             : /* debug **********************************************************************/
      50             : 
      51             : #if !defined(NDEBUG)
      52             : # define DEBUGLOCALREF(message, index) \
      53             :         do { \
      54             :                 if (opt_DebugLocalReferences) { \
      55             :                         localref_table *dlrt = LOCALREFTABLE; \
      56             :                         log_start(); \
      57             :                         log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d hwm=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used, dlrt->hwm); \
      58             :                         if (index >= 0) \
      59             :                                 log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
      60             :                         log_print("]"); \
      61             :                         log_finish(); \
      62             :                 } \
      63             :         } while (0)
      64             : #else
      65             : # define DEBUGLOCALREF(message, index)
      66             : #endif
      67             : 
      68             : /* some forward declarations **************************************************/
      69             : 
      70             : #if !defined(NDEBUG)
      71             : static bool localref_check_uncleared();
      72             : #endif
      73             : 
      74             : 
      75             : /* localref_table_init *********************************************************
      76             : 
      77             :    Initializes the local references table of the current thread.
      78             : 
      79             : *******************************************************************************/
      80             : 
      81         163 : bool localref_table_init(void)
      82             : {
      83             :         localref_table *lrt;
      84             : 
      85         163 :         TRACESUBSYSTEMINITIALIZATION("localref_table_init");
      86             : 
      87         163 :         assert(LOCALREFTABLE == NULL);
      88             : 
      89             : #if !defined(ENABLE_GC_BOEHM)
      90             :         /* this is freed by localref_table_destroy */
      91             :         lrt = (localref_table*) NEW(localref_table);
      92             : #else
      93             :         /* this does not need to be freed again */
      94         163 :         lrt = (localref_table*) GCNEW(localref_table);
      95             : #endif
      96             : 
      97         163 :         if (lrt == NULL)
      98           0 :                 return false;
      99             : 
     100         163 :         localref_table_add(lrt);
     101             : 
     102         163 :         DEBUGLOCALREF("table init", -1);
     103             : 
     104         163 :         return true;
     105             : }
     106             : 
     107             : 
     108             : /* localref_table_destroy ******************************************************
     109             : 
     110             :    Destroys the complete local references table of the current thread.
     111             : 
     112             : *******************************************************************************/
     113             : 
     114           0 : bool localref_table_destroy(void)
     115             : {
     116             : #if !defined(ENABLE_GC_BOEHM)
     117             :         localref_table *lrt;
     118             : 
     119             :         lrt = LOCALREFTABLE;
     120             :         assert(lrt != NULL);
     121             :         assert(lrt->prev == NULL);
     122             : #endif
     123             : 
     124           0 :         DEBUGLOCALREF("table destroy", -1);
     125             : 
     126             : #if !defined(ENABLE_GC_BOEHM)
     127             :         FREE(lrt, localref_table);
     128             : #endif
     129             : 
     130           0 :         LOCALREFTABLE = NULL;
     131             : 
     132           0 :         return true;
     133             : }
     134             : 
     135             : 
     136             : /* localref_table_add **********************************************************
     137             : 
     138             :    Adds a new local references table to the current thread.
     139             : 
     140             : *******************************************************************************/
     141             : 
     142     3116701 : void localref_table_add(localref_table *lrt)
     143             : {
     144             :         /* initialize the local reference table */
     145             : 
     146     3116701 :         lrt->capacity    = LOCALREFTABLE_CAPACITY;
     147     3116701 :         lrt->used        = 0;
     148     3116701 :         lrt->localframes = 1;
     149     3116701 :         lrt->prev        = LOCALREFTABLE;
     150             : 
     151     3116701 :         lrt->hwm = 0;
     152     3116701 :         lrt->firstfree = -1;
     153             : 
     154             :         /* add given local references table to this thread */
     155             : 
     156     3116701 :         LOCALREFTABLE = lrt;
     157             : 
     158             :         /*DEBUGLOCALREF("table add", -1);*/
     159     3116701 : }
     160             : 
     161             : 
     162             : /* localref_table_remove *******************************************************
     163             : 
     164             :    Removes the topmost local references table from the current thread.
     165             : 
     166             : *******************************************************************************/
     167             : 
     168     3116369 : void localref_table_remove()
     169             : {
     170             :         localref_table *lrt;
     171             : 
     172             : #if !defined(NDEBUG)
     173             :         /* check for uncleared local references */
     174             : 
     175     3116369 :         localref_check_uncleared();
     176             : #endif
     177             : 
     178             :         /* get current local reference table from thread */
     179             : 
     180     3116545 :         lrt = LOCALREFTABLE;
     181     3116545 :         assert(lrt != NULL);
     182     3116545 :         assert(lrt->localframes == 1);
     183             : 
     184             :         /*DEBUGLOCALREF("table remove", -1);*/
     185             : 
     186     3116545 :         lrt = lrt->prev;
     187             : 
     188     3116545 :         LOCALREFTABLE = lrt;
     189     3116545 : }
     190             : 
     191             : 
     192             : /* localref_frame_push *********************************************************
     193             : 
     194             :    Creates a new local reference frame, in which at least a given
     195             :    number of local references can be created.
     196             : 
     197             : *******************************************************************************/
     198             : 
     199           1 : bool localref_frame_push(int32_t capacity)
     200             : {
     201             :         localref_table *lrt;
     202             :         localref_table *nlrt;
     203             :         int32_t         additionalrefs;
     204             : 
     205             :         /* get current local reference table from thread */
     206             : 
     207           1 :         lrt = LOCALREFTABLE;
     208           1 :         assert(lrt != NULL);
     209           1 :         assert(capacity > 0);
     210             : 
     211             :         /* Allocate new local reference table on Java heap.  Calculate the
     212             :            additional memory we have to allocate. */
     213             : 
     214           1 :         if (capacity > LOCALREFTABLE_CAPACITY)
     215           1 :                 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
     216             :         else
     217           0 :                 additionalrefs = 0;
     218             : 
     219             : #if !defined(ENABLE_GC_BOEHM)
     220             :         nlrt = (localref_table *)
     221             :                         MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
     222             : #else
     223             :         nlrt = (localref_table *)
     224           1 :                         GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
     225             : #endif
     226             : 
     227           1 :         if (nlrt == NULL)
     228           0 :                 return false;
     229             : 
     230             :         /* Set up the new local reference table and add it to the local
     231             :            frames chain. */
     232             : 
     233           1 :         nlrt->capacity    = capacity;
     234           1 :         nlrt->used        = 0;
     235           1 :         nlrt->localframes = lrt->localframes + 1;
     236           1 :         nlrt->prev        = lrt;
     237             : 
     238             :         /* store new local reference table in thread */
     239             : 
     240           1 :         LOCALREFTABLE = nlrt;
     241             : 
     242           1 :         DEBUGLOCALREF("frame push", -1);
     243             : 
     244           1 :         return true;
     245             : }
     246             : 
     247             : 
     248             : /* localref_frame_pop_all ******************************************************
     249             : 
     250             :    Pops off all the local reference frames of the current table.
     251             : 
     252             : *******************************************************************************/
     253             : 
     254     3116458 : void localref_frame_pop_all(void)
     255             : {
     256             :         localref_table *lrt;
     257             :         localref_table *plrt;
     258             :         int32_t         localframes;
     259             : #if !defined(ENABLE_GC_BOEHM)
     260             :         int32_t         additionalrefs;
     261             : #endif
     262             : 
     263             :         /* get current local reference table from thread */
     264             : 
     265     3116458 :         lrt = LOCALREFTABLE;
     266     3116458 :         assert(lrt != NULL);
     267             : 
     268     3116458 :         localframes = lrt->localframes;
     269             : 
     270             :         /* Don't delete the top local frame, as this one is allocated in
     271             :            the native stub on the stack and is freed automagically on
     272             :            return. */
     273             : 
     274     3116458 :         if (localframes == 1)
     275     3116457 :                 return;
     276             : 
     277             :         /* release all current local frames */
     278             : 
     279           2 :         for (; localframes > 1; localframes--) {
     280             :                 /* get previous frame */
     281             : 
     282           1 :                 plrt = lrt->prev;
     283             : 
     284           1 :                 DEBUGLOCALREF("frame pop", -1);
     285             : 
     286           1 :                 lrt->prev = NULL;
     287             : 
     288             : #if !defined(ENABLE_GC_BOEHM)
     289             :                 /* for the exact GC local reference tables are not on the heap,
     290             :                    so we need to free them explicitly here. */
     291             : 
     292             :                 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
     293             :                         additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
     294             :                 else
     295             :                         additionalrefs = 0;
     296             : 
     297             :                 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
     298             : #endif
     299             : 
     300             :                 /* set new local references table */
     301             : 
     302           1 :                 lrt = plrt;
     303             :         }
     304             : 
     305             :         /* store new local reference table in thread */
     306             : 
     307           1 :         LOCALREFTABLE = lrt;
     308             : }
     309             : 
     310             : 
     311             : /* localref_add ****************************************************************
     312             : 
     313             :    Adds a new entry into the local reference table and returns the
     314             :    new local reference.
     315             : 
     316             : *******************************************************************************/
     317             : 
     318      595686 : java_handle_t *localref_add(java_object_t *o)
     319             : {
     320             :         localref_table *lrt;
     321             :         java_handle_t  *h;
     322             :         int32_t         i;
     323             : 
     324             :         /* get current local reference table from thread */
     325             : 
     326      595686 :         lrt = LOCALREFTABLE;
     327      595686 :         assert(lrt != NULL);
     328      595686 :         assert(o != NULL);
     329             :         /* XXX: assert that we are in a GC critical section! */
     330             : 
     331             :         /* Check if we have space for the requested reference?  No,
     332             :            allocate a new frame.  This is actually not what the spec says,
     333             :            but for compatibility reasons... */
     334             : 
     335      595686 :     if (lrt->used == lrt->capacity) {
     336           0 :                 if (!localref_frame_push(64))
     337           0 :                         assert(0);
     338             : 
     339             :                 /* get the new local reference table */ 
     340             : 
     341           0 :                 lrt = LOCALREFTABLE;
     342             :         }
     343             : 
     344             :         /* insert the reference into the local reference table */
     345             : 
     346      595686 :         i = lrt->hwm;
     347      595686 :         if (i == lrt->capacity) {
     348           9 :                 if (lrt->firstfree >= 0) {
     349           9 :                         i = lrt->firstfree;
     350           9 :                         lrt->firstfree = lrt->refs[i].nextfree;
     351             :                 }
     352             :                 else {
     353             :                         /* this should not happen */
     354             : 
     355           0 :                         log_println("localref_add: WARNING: unable to add localref for %p", o);
     356             : 
     357           0 :                         return NULL;
     358             :                 }
     359             :         } else
     360      595677 :                 lrt->hwm++;
     361             : 
     362      595686 :         lrt->refs[i].ptr = o;
     363      595686 :         lrt->used++;
     364             : 
     365             : #if defined(ENABLE_HANDLES)
     366             :         h = (java_handle_t *) &(lrt->refs[i].ptr);
     367             : #else
     368      595686 :         h = (java_handle_t *) o;
     369             : #endif
     370             : 
     371             :         /*DEBUGLOCALREF("entry add", i);*/
     372             : 
     373      595686 :         return h;
     374             : }
     375             : 
     376             : 
     377             : /* localref_del ****************************************************************
     378             : 
     379             :    Deletes an entry from the local reference table.
     380             : 
     381             : *******************************************************************************/
     382             : 
     383      284644 : void localref_del(java_handle_t *localref)
     384             : {
     385             :         localref_table *lrt;
     386             :         java_handle_t  *h;
     387             :         int32_t         localframes;
     388             :         int32_t         i;
     389             : 
     390             :         /* get local reference table from thread */
     391             : 
     392      284644 :         lrt = LOCALREFTABLE;
     393      284644 :         assert(lrt != NULL);
     394      284644 :         assert(localref != NULL);
     395             : 
     396      284644 :         localframes = lrt->localframes;
     397             : 
     398             :         /* go through all local frames of the current table */
     399             :         /* XXX: this is propably not what the spec wants! */
     400             : 
     401      284644 :         for (; localframes > 0; localframes--) {
     402             : 
     403             :                 /* and try to remove the reference */
     404             :     
     405      569296 :                 for (i = 0; i < lrt->hwm; i++) {
     406             : #if defined(ENABLE_HANDLES)
     407             :                         h = (java_handle_t *) &(lrt->refs[i].ptr);
     408             : #else
     409      569296 :                         h = (java_handle_t *) lrt->refs[i].ptr;
     410             : #endif
     411             : 
     412      569296 :                         if (h == localref) {
     413      284644 :                                 DEBUGLOCALREF("entry delete", i);
     414             : 
     415      284644 :                                 lrt->refs[i].nextfree = lrt->firstfree;
     416      284644 :                                 lrt->firstfree = i;
     417      284644 :                                 lrt->used--;
     418             : 
     419      284644 :                                 return;
     420             :                         }
     421             :                 }
     422             : 
     423           0 :                 lrt = lrt->prev;
     424             :         }
     425             : 
     426             :         /* this should not happen */
     427             : 
     428           0 :         log_println("localref_del: WARNING: unable to find localref %p", localref);
     429             : }
     430             : 
     431             : 
     432             : /* localref_native_enter *******************************************************
     433             : 
     434             :    Insert arguments to a native method into the local reference table.
     435             :    This is done by the native stub through codegen_start_native_call.
     436             : 
     437             : *******************************************************************************/
     438             : 
     439           0 : void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
     440             : {
     441             :         methoddesc     *md;
     442             :         imm_union       arg;
     443             : #if defined(ENABLE_HANDLES)
     444             :         java_handle_t  *h;
     445             : #endif
     446             :         int i;
     447             : 
     448             :         /* get local reference table from thread */
     449             : 
     450             :         //localref_table *lrt = LOCALREFTABLE;
     451             :         //assert(lrt != NULL);
     452           0 :         assert(m != NULL);
     453             : 
     454           0 :         md = m->parseddesc;
     455             : 
     456             :         /* walk through all parameters to the method */
     457             : 
     458           0 :         for (i = 0; i < md->paramcount; ++i) {
     459             :                 /* load TYPE_ADR parameters ... */
     460             : 
     461           0 :                 if (md->paramtypes[i].type == TYPE_ADR) {
     462           0 :                         arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
     463             : 
     464           0 :                         if (arg.a == NULL)
     465           0 :                                 continue;
     466             : 
     467             : #if !defined(ENABLE_HANDLES)
     468             :                         /* ... and insert them into the table */
     469             : 
     470           0 :                         localref_add((java_object_t *) arg.a);
     471             : #else
     472             :                         /* ... and insert them into the table */
     473             : 
     474             :                         h = localref_add((java_object_t *) arg.a);
     475             : 
     476             :                         /* update the modified parameter if necesarry */
     477             : 
     478             :                         arg.a = (void *) h;
     479             :                         argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
     480             : #endif
     481             :                 }
     482             :         }
     483           0 : }
     484             : 
     485             : 
     486             : /* localref_native_exit ********************************************************
     487             : 
     488             :    Undo the wrapping of the return value of a native method. This is
     489             :    done by the native stub through codegen_finish_native_call.
     490             : 
     491             :    NOTE: This function is only useful if handles are enabled.
     492             : 
     493             : *******************************************************************************/
     494             : 
     495             : #if defined(ENABLE_HANDLES)
     496             : void localref_native_exit(methodinfo *m, uint64_t *return_regs)
     497             : {
     498             :         localref_table *lrt;
     499             :         methoddesc     *md;
     500             :         imm_union       ret;
     501             :         java_handle_t  *h;
     502             : 
     503             :         /* get local reference table from thread */
     504             : 
     505             :         lrt = LOCALREFTABLE;
     506             :         assert(lrt != NULL);
     507             :         assert(m != NULL);
     508             : 
     509             :         md = m->parseddesc;
     510             : 
     511             :         /* load TYPE_ADR return values ... */
     512             : 
     513             :         if (md->returntype.type == TYPE_ADR) {
     514             :                 ret = argument_jitreturn_load(md, return_regs);
     515             : 
     516             :                 if (ret.a == NULL)
     517             :                         return;
     518             : 
     519             :                 h = (java_handle_t *) ret.a;
     520             : 
     521             :                 /* update the modified return valie */
     522             : 
     523             :                 ret.a = (void *) h->heap_object;
     524             :                 argument_jitreturn_store(md, return_regs, ret);
     525             : 
     526             : #if !defined(NDEBUG) && 0
     527             :                 /* removing the entry from the local reference table is not really
     528             :                    necesarry, but gives us warnings if the entry does not exist. */
     529             : 
     530             :                 localref_del(h);
     531             : #endif
     532             :         }
     533             : }
     534             : #endif /* defined(ENABLE_HANDLES) */
     535             : 
     536             : 
     537             : /* localref_dump ***************************************************************
     538             : 
     539             :    Dumps all local reference tables, including all frames.
     540             : 
     541             : *******************************************************************************/
     542             : 
     543             : #if !defined(NDEBUG)
     544             : # define LOCALREF_DUMP_REFS_PER_LINE 4
     545           0 : void localref_dump()
     546             : {
     547             :         localref_table *lrt, dlrt;
     548             :         int i, j;
     549             : 
     550             :         /* get current local reference table from thread */
     551             : 
     552           0 :         lrt = LOCALREFTABLE;
     553             : 
     554           0 :         log_println("--------- Local Reference Tables Dump ---------");
     555             : 
     556           0 :         while (lrt != NULL) {
     557           0 :                 log_println("Frame #%d, Used=%d, Capacity=%d, Hwm=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, lrt->hwm, (void *) lrt);
     558             : 
     559           0 :                         if (lrt->used != 0) {
     560             : 
     561           0 :                                 dlrt = *lrt;                    // copy it for dumping
     562           0 :                                 for (i = dlrt.firstfree; i >= 0; i = j) {
     563           0 :                                         j = dlrt.refs[i].nextfree;
     564           0 :                                         dlrt.refs[i].ptr = NULL;
     565             :                                 }
     566             : 
     567           0 :                                 log_start();
     568             : 
     569           0 :                                 j = 0;
     570           0 :                                 for (i = 0; i < dlrt.hwm; i++) {
     571           0 :                                         if (dlrt.refs[i].ptr != NULL) {
     572           0 :                                                 if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
     573           0 :                                                         log_finish();
     574           0 :                                                         log_start();
     575             :                                                 }
     576           0 :                                                 j++;
     577           0 :                                                 log_print("\t0x%016lx ", (intptr_t) dlrt.refs[i].ptr);
     578             :                                         }
     579             :                                 }
     580             : 
     581           0 :                                 log_finish();
     582             :                         }
     583             : 
     584           0 :                 lrt = lrt->prev;
     585             :         }
     586           0 : }
     587             : #endif /* !defined(NDEBUG) */
     588             : 
     589             : 
     590             : /* localref_check_uncleared ****************************************************
     591             : 
     592             :    Checks the topmost local reference table for uncleared references.
     593             : 
     594             : *******************************************************************************/
     595             : 
     596             : #if !defined(NDEBUG)
     597     3116551 : static bool localref_check_uncleared()
     598             : {
     599             :         localref_table *lrt;
     600             :         int32_t         localframes;
     601             :         int32_t         lrt_uncleared;
     602             :         int32_t         lrt_used;
     603             :         int i;
     604             : 
     605             :         /* get current local reference table from thread */
     606             : 
     607     3116551 :         lrt = LOCALREFTABLE;
     608     3116551 :         assert(lrt != NULL);
     609     3116551 :         assert(lrt->localframes > 0);
     610             : 
     611     3116551 :         localframes   = lrt->localframes;
     612     3116551 :         lrt_uncleared = 0;
     613     3116551 :         lrt_used      = 0;
     614             : 
     615     6233087 :         for (; localframes > 0; localframes--) {
     616     3116536 :                 lrt_used += lrt->used;
     617             : 
     618     3116536 :                 lrt_uncleared += lrt->hwm;
     619     3401171 :                 for (i = lrt->firstfree; i >= 0; i = lrt->refs[i].nextfree)
     620      284635 :                         lrt_uncleared--;
     621             : 
     622     3116536 :                 lrt = lrt->prev;
     623             :         }
     624             : 
     625     3116551 :         if (lrt_uncleared != lrt_used) {
     626           0 :                 localref_dump();
     627           0 :                 vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
     628             :         }
     629             : 
     630     3116551 :         if (lrt_uncleared <= 1)
     631     3116406 :                 return true;
     632             :         else {
     633             :                 /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
     634         145 :                 return false;
     635             :         }
     636             : }
     637             : #endif
     638             : 
     639             : 
     640             : /*
     641             :  * These are local overrides for various environment variables in Emacs.
     642             :  * Please do not remove this and leave it at the end of the file, where
     643             :  * Emacs will automagically detect them.
     644             :  * ---------------------------------------------------------------------
     645             :  * Local variables:
     646             :  * mode: c++
     647             :  * indent-tabs-mode: t
     648             :  * c-basic-offset: 4
     649             :  * tab-width: 4
     650             :  * End:
     651             :  * vim:noexpandtab:sw=4:ts=4:
     652             :  */

Generated by: LCOV version 1.11