1 /* src/native/localref.cpp - Management of local reference tables
3 Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
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 hwm=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used, dlrt->hwm); \
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;
156 /* add given local references table to this thread */
160 /*DEBUGLOCALREF("table add", -1);*/
164 /* localref_table_remove *******************************************************
166 Removes the topmost local references table from the current thread.
168 *******************************************************************************/
170 void localref_table_remove()
175 /* check for uncleared local references */
177 localref_check_uncleared();
180 /* get current local reference table from thread */
184 assert(lrt->localframes == 1);
186 /*DEBUGLOCALREF("table remove", -1);*/
194 /* localref_frame_push *********************************************************
196 Creates a new local reference frame, in which at least a given
197 number of local references can be created.
199 *******************************************************************************/
201 bool localref_frame_push(int32_t capacity)
204 localref_table *nlrt;
205 int32_t additionalrefs;
207 /* get current local reference table from thread */
211 assert(capacity > 0);
213 /* Allocate new local reference table on Java heap. Calculate the
214 additional memory we have to allocate. */
216 if (capacity > LOCALREFTABLE_CAPACITY)
217 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
221 #if !defined(ENABLE_GC_BOEHM)
222 nlrt = (localref_table *)
223 MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
225 nlrt = (localref_table *)
226 GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
232 /* Set up the new local reference table and add it to the local
235 nlrt->capacity = capacity;
237 nlrt->localframes = lrt->localframes + 1;
240 /* store new local reference table in thread */
242 LOCALREFTABLE = nlrt;
244 DEBUGLOCALREF("frame push", -1);
250 /* localref_frame_pop_all ******************************************************
252 Pops off all the local reference frames of the current table.
254 *******************************************************************************/
256 void localref_frame_pop_all(void)
259 localref_table *plrt;
261 #if !defined(ENABLE_GC_BOEHM)
262 int32_t additionalrefs;
265 /* get current local reference table from thread */
270 localframes = lrt->localframes;
272 /* Don't delete the top local frame, as this one is allocated in
273 the native stub on the stack and is freed automagically on
276 if (localframes == 1)
279 /* release all current local frames */
281 for (; localframes > 1; localframes--) {
282 /* get previous frame */
286 DEBUGLOCALREF("frame pop", -1);
290 #if !defined(ENABLE_GC_BOEHM)
291 /* for the exact GC local reference tables are not on the heap,
292 so we need to free them explicitly here. */
294 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
295 additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
299 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
302 /* set new local references table */
307 /* store new local reference table in thread */
313 /* localref_add ****************************************************************
315 Adds a new entry into the local reference table and returns the
318 *******************************************************************************/
320 java_handle_t *localref_add(java_object_t *o)
326 /* get current local reference table from thread */
331 /* XXX: assert that we are in a GC critical section! */
333 /* Check if we have space for the requested reference? No,
334 allocate a new frame. This is actually not what the spec says,
335 but for compatibility reasons... */
337 if (lrt->used == lrt->capacity) {
338 if (!localref_frame_push(64))
341 /* get the new local reference table */
346 /* insert the reference into the local reference table */
349 if (i == lrt->capacity) {
350 if (lrt->firstfree >= 0) {
352 lrt->firstfree = lrt->refs[i].nextfree;
355 /* this should not happen */
357 log_println("localref_add: WARNING: unable to add localref for %p", o);
364 lrt->refs[i].ptr = o;
367 #if defined(ENABLE_HANDLES)
368 h = (java_handle_t *) &(lrt->refs[i].ptr);
370 h = (java_handle_t *) o;
373 /*DEBUGLOCALREF("entry add", i);*/
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->hwm; i++) {
408 #if defined(ENABLE_HANDLES)
409 h = (java_handle_t *) &(lrt->refs[i].ptr);
411 h = (java_handle_t *) lrt->refs[i].ptr;
415 DEBUGLOCALREF("entry delete", i);
417 lrt->refs[i].nextfree = lrt->firstfree;
428 /* this should not happen */
430 log_println("localref_del: WARNING: unable to find localref %p", localref);
434 /* localref_native_enter *******************************************************
436 Insert arguments to a native method into the local reference table.
437 This is done by the native stub through codegen_start_native_call.
439 *******************************************************************************/
441 void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
449 /* get local reference table from thread */
457 /* walk through all parameters to the method */
459 for (i = 0; i < md->paramcount; ++i) {
460 /* load TYPE_ADR parameters ... */
462 if (md->paramtypes[i].type == TYPE_ADR) {
463 arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
468 /* ... and insert them into the table */
470 h = localref_add((java_object_t *) arg.a);
472 #if defined(ENABLE_HANDLES)
473 /* update the modified parameter if necesarry */
476 argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
483 /* localref_native_exit ********************************************************
485 Undo the wrapping of the return value of a native method. This is
486 done by the native stub through codegen_finish_native_call.
488 NOTE: This function is only useful if handles are enabled.
490 *******************************************************************************/
492 #if defined(ENABLE_HANDLES)
493 void localref_native_exit(methodinfo *m, uint64_t *return_regs)
500 /* get local reference table from thread */
508 /* load TYPE_ADR return values ... */
510 if (md->returntype.type == TYPE_ADR) {
511 ret = argument_jitreturn_load(md, return_regs);
516 h = (java_handle_t *) ret.a;
518 /* update the modified return valie */
520 ret.a = (void *) h->heap_object;
521 argument_jitreturn_store(md, return_regs, ret);
523 #if !defined(NDEBUG) && 0
524 /* removing the entry from the local reference table is not really
525 necesarry, but gives us warnings if the entry does not exist. */
531 #endif /* defined(ENABLE_HANDLES) */
534 /* localref_dump ***************************************************************
536 Dumps all local reference tables, including all frames.
538 *******************************************************************************/
541 # define LOCALREF_DUMP_REFS_PER_LINE 4
544 localref_table *lrt, dlrt;
547 /* get current local reference table from thread */
551 log_println("--------- Local Reference Tables Dump ---------");
553 while (lrt != NULL) {
554 log_println("Frame #%d, Used=%d, Capacity=%d, Hwm=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, lrt->hwm, (void *) lrt);
556 if (lrt->used != 0) {
558 dlrt = *lrt; // copy it for dumping
559 for (i = dlrt.firstfree; i >= 0; i = j) {
560 j = dlrt.refs[i].nextfree;
561 dlrt.refs[i].ptr = NULL;
567 for (i = 0; i < dlrt.hwm; i++) {
568 if (dlrt.refs[i].ptr != NULL) {
569 if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
574 log_print("\t0x%016lx ", (intptr_t) dlrt.refs[i].ptr);
584 #endif /* !defined(NDEBUG) */
587 /* localref_check_uncleared ****************************************************
589 Checks the topmost local reference table for uncleared references.
591 *******************************************************************************/
594 static bool localref_check_uncleared()
598 int32_t lrt_uncleared;
602 /* get current local reference table from thread */
606 assert(lrt->localframes > 0);
608 localframes = lrt->localframes;
612 for (; localframes > 0; localframes--) {
613 lrt_used += lrt->used;
615 lrt_uncleared += lrt->hwm;
616 for (i = lrt->firstfree; i >= 0; i = lrt->refs[i].nextfree)
622 if (lrt_uncleared != lrt_used) {
624 vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
627 if (lrt_uncleared <= 1)
630 /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
638 * These are local overrides for various environment variables in Emacs.
639 * Please do not remove this and leave it at the end of the file, where
640 * Emacs will automagically detect them.
641 * ---------------------------------------------------------------------
644 * indent-tabs-mode: t
648 * vim:noexpandtab:sw=4:ts=4: