1 /* src/native/localref.c - Management of local reference tables
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
31 #include "mm/memory.h"
33 #include "native/localref.h"
35 #include "threads/thread.h"
37 #include "toolbox/logging.h"
41 #include "vm/jit/argument.h"
43 #include "vmcore/options.h"
46 /* debug **********************************************************************/
49 # define DEBUGLOCALREF(message, index) \
51 if (opt_DebugLocalReferences) { \
52 localref_table *dlrt = LOCALREFTABLE; \
54 log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
56 log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
62 # define DEBUGLOCALREF(message, index)
66 /* global variables ***********************************************************/
68 #if !defined(ENABLE_THREADS)
69 localref_table *_no_threads_localref_table;
73 /* some forward declarations **************************************************/
76 static bool localref_check_uncleared();
80 /* localref_table_init *********************************************************
82 Initializes the local references table of the current thread.
84 *******************************************************************************/
86 bool localref_table_init(void)
90 TRACESUBSYSTEMINITIALIZATION("localref_table_init");
92 assert(LOCALREFTABLE == NULL);
94 #if !defined(ENABLE_GC_BOEHM)
95 /* this is freed by localref_table_destroy */
96 lrt = NEW(localref_table);
98 /* this does not need to be freed again */
99 lrt = GCNEW(localref_table);
105 localref_table_add(lrt);
107 DEBUGLOCALREF("table init", -1);
113 /* localref_table_destroy ******************************************************
115 Destroys the complete local references table of the current thread.
117 *******************************************************************************/
119 bool localref_table_destroy(void)
125 assert(lrt->prev == NULL);
127 DEBUGLOCALREF("table destroy", -1);
129 #if !defined(ENABLE_GC_BOEHM)
130 FREE(lrt, localref_table);
133 LOCALREFTABLE = NULL;
139 /* localref_table_add **********************************************************
141 Adds a new local references table to the current thread.
143 *******************************************************************************/
145 void localref_table_add(localref_table *lrt)
147 /* initialize the local reference table */
149 lrt->capacity = LOCALREFTABLE_CAPACITY;
151 lrt->localframes = 1;
152 lrt->prev = LOCALREFTABLE;
154 /* clear the references array (memset is faster the a for-loop) */
156 MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
158 /* add given local references table to this thread */
162 /*DEBUGLOCALREF("table add", -1);*/
166 /* localref_table_remove *******************************************************
168 Removes the topmost local references table from the current thread.
170 *******************************************************************************/
172 void localref_table_remove()
177 /* check for uncleared local references */
179 localref_check_uncleared();
182 /* get current local reference table from thread */
186 assert(lrt->localframes == 1);
188 /*DEBUGLOCALREF("table remove", -1);*/
196 /* localref_frame_push *********************************************************
198 Creates a new local reference frame, in which at least a given
199 number of local references can be created.
201 *******************************************************************************/
203 bool localref_frame_push(int32_t capacity)
206 localref_table *nlrt;
207 int32_t additionalrefs;
209 /* get current local reference table from thread */
213 assert(capacity > 0);
215 /* Allocate new local reference table on Java heap. Calculate the
216 additional memory we have to allocate. */
218 if (capacity > LOCALREFTABLE_CAPACITY)
219 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
223 #if !defined(ENABLE_GC_BOEHM)
224 nlrt = (localref_table *)
225 MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
227 nlrt = (localref_table *)
228 GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
234 /* Set up the new local reference table and add it to the local
237 nlrt->capacity = capacity;
239 nlrt->localframes = lrt->localframes + 1;
242 /* store new local reference table in thread */
244 LOCALREFTABLE = nlrt;
246 DEBUGLOCALREF("frame push", -1);
252 /* localref_frame_pop_all ******************************************************
254 Pops off all the local reference frames of the current table.
256 *******************************************************************************/
258 void localref_frame_pop_all(void)
261 localref_table *plrt;
263 #if !defined(ENABLE_GC_BOEHM)
264 int32_t additionalrefs;
267 /* get current local reference table from thread */
272 localframes = lrt->localframes;
274 /* Don't delete the top local frame, as this one is allocated in
275 the native stub on the stack and is freed automagically on
278 if (localframes == 1)
281 /* release all current local frames */
283 for (; localframes > 1; localframes--) {
284 /* get previous frame */
288 DEBUGLOCALREF("frame pop", -1);
290 /* clear all reference entries */
292 MSET(lrt->refs, 0, void*, lrt->capacity);
296 #if !defined(ENABLE_GC_BOEHM)
297 /* for the exact GC local reference tables are not on the heap,
298 so we need to free them explicitly here. */
300 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
301 additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
305 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
308 /* set new local references table */
313 /* store new local reference table in thread */
319 /* localref_add ****************************************************************
321 Adds a new entry into the local reference table and returns the
324 *******************************************************************************/
326 java_handle_t *localref_add(java_object_t *o)
332 /* get current local reference table from thread */
337 /* XXX: assert that we are in a GC critical section! */
339 /* Check if we have space for the requested reference? No,
340 allocate a new frame. This is actually not what the spec says,
341 but for compatibility reasons... */
343 if (lrt->used == lrt->capacity) {
344 if (!localref_frame_push(64))
347 /* get the new local reference table */
352 /* insert the reference into the local reference table */
354 for (i = 0; i < lrt->capacity; i++) {
355 if (lrt->refs[i] == NULL) {
359 #if defined(ENABLE_HANDLES)
360 h = (java_handle_t *) &(lrt->refs[i]);
362 h = (java_handle_t *) o;
365 /*DEBUGLOCALREF("entry add", i);*/
371 /* this should not happen */
373 log_println("localref_add: WARNING: unable to add localref for %p", o);
379 /* localref_del ****************************************************************
381 Deletes an entry from the local reference table.
383 *******************************************************************************/
385 void localref_del(java_handle_t *localref)
392 /* get local reference table from thread */
396 assert(localref != NULL);
398 localframes = lrt->localframes;
400 /* go through all local frames of the current table */
401 /* XXX: this is propably not what the spec wants! */
403 for (; localframes > 0; localframes--) {
405 /* and try to remove the reference */
407 for (i = 0; i < lrt->capacity; i++) {
408 #if defined(ENABLE_HANDLES)
409 h = (java_handle_t *) &(lrt->refs[i]);
411 h = (java_handle_t *) lrt->refs[i];
415 DEBUGLOCALREF("entry delete", i);
427 /* this should not happen */
429 log_println("localref_del: WARNING: unable to find localref %p", localref);
433 /* localref_native_enter *******************************************************
435 Insert arguments to a native method into the local reference table.
436 This is done by the native stub through codegen_start_native_call.
438 *******************************************************************************/
440 void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
448 /* get local reference table from thread */
456 /* walk through all parameters to the method */
458 for (i = 0; i < md->paramcount; ++i) {
459 /* load TYPE_ADR parameters ... */
461 if (md->paramtypes[i].type == TYPE_ADR) {
462 arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
467 /* ... and insert them into the table */
469 h = localref_add((java_object_t *) arg.a);
471 #if defined(ENABLE_HANDLES)
472 /* update the modified parameter if necesarry */
475 argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
482 /* localref_native_exit ********************************************************
484 Undo the wrapping of the return value of a native method. This is
485 done by the native stub through codegen_finish_native_call.
487 NOTE: This function is only useful if handles are enabled.
489 *******************************************************************************/
491 #if defined(ENABLE_HANDLES)
492 void localref_native_exit(methodinfo *m, uint64_t *return_regs)
499 /* get local reference table from thread */
507 /* load TYPE_ADR return values ... */
509 if (md->returntype.type == TYPE_ADR) {
510 ret = argument_jitreturn_load(md, return_regs);
515 h = (java_handle_t *) ret.a;
517 /* update the modified return valie */
519 ret.a = (void *) h->heap_object;
520 argument_jitreturn_store(md, return_regs, ret);
522 #if !defined(NDEBUG) && 0
523 /* removing the entry from the local reference table is not really
524 necesarry, but gives us warnings if the entry does not exist. */
530 #endif /* defined(ENABLE_HANDLES) */
533 /* localref_dump ***************************************************************
535 Dumps all local reference tables, including all frames.
537 *******************************************************************************/
540 # define LOCALREF_DUMP_REFS_PER_LINE 4
546 /* get current local reference table from thread */
550 log_println("--------- Local Reference Tables Dump ---------");
552 while (lrt != NULL) {
553 log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
555 if (lrt->used != 0) {
560 for (i = 0; i < lrt->capacity; i++) {
561 if (lrt->refs[i] != NULL) {
562 if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
567 log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
577 #endif /* !defined(NDEBUG) */
580 /* localref_check_uncleared ****************************************************
582 Checks the topmost local reference table for uncleared references.
584 *******************************************************************************/
587 static bool localref_check_uncleared()
591 int32_t lrt_uncleared;
595 /* get current local reference table from thread */
599 assert(lrt->localframes > 0);
601 localframes = lrt->localframes;
605 for (; localframes > 0; localframes--) {
606 lrt_used += lrt->used;
608 for (i = 0; i < lrt->capacity; i++) {
609 if (lrt->refs[i] != NULL)
616 if (lrt_uncleared != lrt_used) {
618 vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
621 if (lrt_uncleared <= 1)
624 /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
632 * These are local overrides for various environment variables in Emacs.
633 * Please do not remove this and leave it at the end of the file, where
634 * Emacs will automagically detect them.
635 * ---------------------------------------------------------------------
638 * indent-tabs-mode: t
642 * vim:noexpandtab:sw=4:ts=4: