1 /* src/native/localref.cpp - 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.hpp"
33 #include "native/localref.hpp"
35 #include "threads/thread.hpp"
37 #include "toolbox/logging.hpp"
39 #include "vm/options.h"
42 #include "vm/jit/argument.hpp"
45 /* debug **********************************************************************/
48 # define DEBUGLOCALREF(message, index) \
50 if (opt_DebugLocalReferences) { \
51 localref_table *dlrt = LOCALREFTABLE; \
53 log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
55 log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
61 # define DEBUGLOCALREF(message, index)
65 /* global variables ***********************************************************/
67 #if !defined(ENABLE_THREADS)
68 localref_table *_no_threads_localref_table;
72 /* some forward declarations **************************************************/
75 static bool localref_check_uncleared();
79 /* localref_table_init *********************************************************
81 Initializes the local references table of the current thread.
83 *******************************************************************************/
85 bool localref_table_init(void)
89 TRACESUBSYSTEMINITIALIZATION("localref_table_init");
91 assert(LOCALREFTABLE == NULL);
93 #if !defined(ENABLE_GC_BOEHM)
94 /* this is freed by localref_table_destroy */
95 lrt = (localref_table*) NEW(localref_table);
97 /* this does not need to be freed again */
98 lrt = (localref_table*) GCNEW(localref_table);
104 localref_table_add(lrt);
106 DEBUGLOCALREF("table init", -1);
112 /* localref_table_destroy ******************************************************
114 Destroys the complete local references table of the current thread.
116 *******************************************************************************/
118 bool localref_table_destroy(void)
124 assert(lrt->prev == NULL);
126 DEBUGLOCALREF("table destroy", -1);
128 #if !defined(ENABLE_GC_BOEHM)
129 FREE(lrt, localref_table);
132 LOCALREFTABLE = NULL;
138 /* localref_table_add **********************************************************
140 Adds a new local references table to the current thread.
142 *******************************************************************************/
144 void localref_table_add(localref_table *lrt)
146 /* initialize the local reference table */
148 lrt->capacity = LOCALREFTABLE_CAPACITY;
150 lrt->localframes = 1;
151 lrt->prev = LOCALREFTABLE;
153 /* clear the references array (memset is faster the a for-loop) */
155 MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
157 /* add given local references table to this thread */
161 /*DEBUGLOCALREF("table add", -1);*/
165 /* localref_table_remove *******************************************************
167 Removes the topmost local references table from the current thread.
169 *******************************************************************************/
171 void localref_table_remove()
176 /* check for uncleared local references */
178 localref_check_uncleared();
181 /* get current local reference table from thread */
185 assert(lrt->localframes == 1);
187 /*DEBUGLOCALREF("table remove", -1);*/
195 /* localref_frame_push *********************************************************
197 Creates a new local reference frame, in which at least a given
198 number of local references can be created.
200 *******************************************************************************/
202 bool localref_frame_push(int32_t capacity)
205 localref_table *nlrt;
206 int32_t additionalrefs;
208 /* get current local reference table from thread */
212 assert(capacity > 0);
214 /* Allocate new local reference table on Java heap. Calculate the
215 additional memory we have to allocate. */
217 if (capacity > LOCALREFTABLE_CAPACITY)
218 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
222 #if !defined(ENABLE_GC_BOEHM)
223 nlrt = (localref_table *)
224 MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
226 nlrt = (localref_table *)
227 GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
233 /* Set up the new local reference table and add it to the local
236 nlrt->capacity = capacity;
238 nlrt->localframes = lrt->localframes + 1;
241 /* store new local reference table in thread */
243 LOCALREFTABLE = nlrt;
245 DEBUGLOCALREF("frame push", -1);
251 /* localref_frame_pop_all ******************************************************
253 Pops off all the local reference frames of the current table.
255 *******************************************************************************/
257 void localref_frame_pop_all(void)
260 localref_table *plrt;
262 #if !defined(ENABLE_GC_BOEHM)
263 int32_t additionalrefs;
266 /* get current local reference table from thread */
271 localframes = lrt->localframes;
273 /* Don't delete the top local frame, as this one is allocated in
274 the native stub on the stack and is freed automagically on
277 if (localframes == 1)
280 /* release all current local frames */
282 for (; localframes > 1; localframes--) {
283 /* get previous frame */
287 DEBUGLOCALREF("frame pop", -1);
289 /* clear all reference entries */
291 MSET(lrt->refs, 0, void*, lrt->capacity);
295 #if !defined(ENABLE_GC_BOEHM)
296 /* for the exact GC local reference tables are not on the heap,
297 so we need to free them explicitly here. */
299 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
300 additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
304 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
307 /* set new local references table */
312 /* store new local reference table in thread */
318 /* localref_add ****************************************************************
320 Adds a new entry into the local reference table and returns the
323 *******************************************************************************/
325 java_handle_t *localref_add(java_object_t *o)
331 /* get current local reference table from thread */
336 /* XXX: assert that we are in a GC critical section! */
338 /* Check if we have space for the requested reference? No,
339 allocate a new frame. This is actually not what the spec says,
340 but for compatibility reasons... */
342 if (lrt->used == lrt->capacity) {
343 if (!localref_frame_push(64))
346 /* get the new local reference table */
351 /* insert the reference into the local reference table */
353 for (i = 0; i < lrt->capacity; i++) {
354 if (lrt->refs[i] == NULL) {
358 #if defined(ENABLE_HANDLES)
359 h = (java_handle_t *) &(lrt->refs[i]);
361 h = (java_handle_t *) o;
364 /*DEBUGLOCALREF("entry add", i);*/
370 /* this should not happen */
372 log_println("localref_add: WARNING: unable to add localref for %p", o);
378 /* localref_del ****************************************************************
380 Deletes an entry from the local reference table.
382 *******************************************************************************/
384 void localref_del(java_handle_t *localref)
391 /* get local reference table from thread */
395 assert(localref != NULL);
397 localframes = lrt->localframes;
399 /* go through all local frames of the current table */
400 /* XXX: this is propably not what the spec wants! */
402 for (; localframes > 0; localframes--) {
404 /* and try to remove the reference */
406 for (i = 0; i < lrt->capacity; i++) {
407 #if defined(ENABLE_HANDLES)
408 h = (java_handle_t *) &(lrt->refs[i]);
410 h = (java_handle_t *) lrt->refs[i];
414 DEBUGLOCALREF("entry delete", i);
426 /* this should not happen */
428 log_println("localref_del: WARNING: unable to find localref %p", localref);
432 /* localref_native_enter *******************************************************
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.
437 *******************************************************************************/
439 void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
447 /* get local reference table from thread */
455 /* walk through all parameters to the method */
457 for (i = 0; i < md->paramcount; ++i) {
458 /* load TYPE_ADR parameters ... */
460 if (md->paramtypes[i].type == TYPE_ADR) {
461 arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
466 /* ... and insert them into the table */
468 h = localref_add((java_object_t *) arg.a);
470 #if defined(ENABLE_HANDLES)
471 /* update the modified parameter if necesarry */
474 argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
481 /* localref_native_exit ********************************************************
483 Undo the wrapping of the return value of a native method. This is
484 done by the native stub through codegen_finish_native_call.
486 NOTE: This function is only useful if handles are enabled.
488 *******************************************************************************/
490 #if defined(ENABLE_HANDLES)
491 void localref_native_exit(methodinfo *m, uint64_t *return_regs)
498 /* get local reference table from thread */
506 /* load TYPE_ADR return values ... */
508 if (md->returntype.type == TYPE_ADR) {
509 ret = argument_jitreturn_load(md, return_regs);
514 h = (java_handle_t *) ret.a;
516 /* update the modified return valie */
518 ret.a = (void *) h->heap_object;
519 argument_jitreturn_store(md, return_regs, ret);
521 #if !defined(NDEBUG) && 0
522 /* removing the entry from the local reference table is not really
523 necesarry, but gives us warnings if the entry does not exist. */
529 #endif /* defined(ENABLE_HANDLES) */
532 /* localref_dump ***************************************************************
534 Dumps all local reference tables, including all frames.
536 *******************************************************************************/
539 # define LOCALREF_DUMP_REFS_PER_LINE 4
545 /* get current local reference table from thread */
549 log_println("--------- Local Reference Tables Dump ---------");
551 while (lrt != NULL) {
552 log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
554 if (lrt->used != 0) {
559 for (i = 0; i < lrt->capacity; i++) {
560 if (lrt->refs[i] != NULL) {
561 if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
566 log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
576 #endif /* !defined(NDEBUG) */
579 /* localref_check_uncleared ****************************************************
581 Checks the topmost local reference table for uncleared references.
583 *******************************************************************************/
586 static bool localref_check_uncleared()
590 int32_t lrt_uncleared;
594 /* get current local reference table from thread */
598 assert(lrt->localframes > 0);
600 localframes = lrt->localframes;
604 for (; localframes > 0; localframes--) {
605 lrt_used += lrt->used;
607 for (i = 0; i < lrt->capacity; i++) {
608 if (lrt->refs[i] != NULL)
615 if (lrt_uncleared != lrt_used) {
617 vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
620 if (lrt_uncleared <= 1)
623 /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
631 * These are local overrides for various environment variables in Emacs.
632 * Please do not remove this and leave it at the end of the file, where
633 * Emacs will automagically detect them.
634 * ---------------------------------------------------------------------
637 * indent-tabs-mode: t
641 * vim:noexpandtab:sw=4:ts=4: