1 /* src/native/localref.c - Management of local reference tables
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #include "mm/memory.h"
35 #include "native/localref.h"
37 #include "threads/threads-common.h"
39 #include "toolbox/logging.h"
43 #include "vm/jit/argument.h"
46 /* debug **********************************************************************/
48 #if !defined(NDEBUG) && 0
49 # define TRACELOCALREF(message) log_println("%s", message)
51 # define TRACELOCALREF(message)
55 /* global variables ***********************************************************/
57 #if !defined(ENABLE_THREADS)
58 localref_table *_no_threads_localref_table;
62 /* localref_table_init *********************************************************
64 Initializes the local references table of the current thread.
66 *******************************************************************************/
68 bool localref_table_init(void)
72 TRACELOCALREF("table init");
74 assert(LOCALREFTABLE == NULL);
76 #if defined(ENABLE_GC_CACAO)
77 /* this is freed by localref_table_destroy */
78 lrt = NEW(localref_table);
80 /* this does not need to be freed again */
81 lrt = GCNEW(localref_table);
87 localref_table_add(lrt);
93 /* localref_table_destroy ******************************************************
95 Destroys the complete local references table of the current thread.
97 *******************************************************************************/
99 bool localref_table_destroy(void)
103 TRACELOCALREF("table destroy");
108 assert(lrt->prev == NULL);
110 #if defined(ENABLE_GC_CACAO)
111 FREE(lrt, localref_table);
114 LOCALREFTABLE = NULL;
120 /* localref_table_add **********************************************************
122 Adds a new local references table to the current thread.
124 *******************************************************************************/
126 void localref_table_add(localref_table *lrt)
128 /* initialize the local reference table */
130 lrt->capacity = LOCALREFTABLE_CAPACITY;
132 lrt->localframes = 1;
133 lrt->prev = LOCALREFTABLE;
135 /* clear the references array (memset is faster the a for-loop) */
137 MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
139 /* add given local references table to this thread */
145 /* localref_table_remove *******************************************************
147 Removes the topmost local references table from the current thread.
149 *******************************************************************************/
151 void localref_table_remove()
155 /* get current local reference table from thread */
160 assert(lrt->localframes == 1);
168 /* localref_frame_push *********************************************************
170 Creates a new local reference frame, in which at least a given
171 number of local references can be created.
173 *******************************************************************************/
175 bool localref_frame_push(int32_t capacity)
178 localref_table *nlrt;
179 int32_t additionalrefs;
181 TRACELOCALREF("frame push");
183 /* get current local reference table from thread */
188 assert(capacity > 0);
190 /* Allocate new local reference table on Java heap. Calculate the
191 additional memory we have to allocate. */
193 if (capacity > LOCALREFTABLE_CAPACITY)
194 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
198 #if defined(ENABLE_GC_CACAO)
199 nlrt = (localref_table *)
200 MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
202 nlrt = (localref_table *)
203 GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
209 /* Set up the new local reference table and add it to the local
212 nlrt->capacity = capacity;
214 nlrt->localframes = lrt->localframes + 1;
217 /* store new local reference table in thread */
219 LOCALREFTABLE = nlrt;
225 /* localref_frame_pop_all ******************************************************
227 Pops off all the local reference frames of the current table.
229 *******************************************************************************/
231 void localref_frame_pop_all(void)
234 localref_table *plrt;
236 #if defined(ENABLE_GC_CACAO)
237 int32_t additionalrefs;
240 TRACELOCALREF("frame pop all");
242 /* get current local reference table from thread */
248 localframes = lrt->localframes;
250 /* Don't delete the top local frame, as this one is allocated in
251 the native stub on the stack and is freed automagically on
254 if (localframes == 1)
257 /* release all current local frames */
259 for (; localframes > 1; localframes--) {
260 /* get previous frame */
264 /* clear all reference entries */
266 MSET(lrt->refs, 0, void*, lrt->capacity);
270 #if defined(ENABLE_GC_CACAO)
271 /* for the exact GC local reference tables are not on the heap,
272 so we need to free them explicitly here. */
274 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
275 additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
279 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
282 /* set new local references table */
287 /* store new local reference table in thread */
293 /* localref_add ****************************************************************
295 Adds a new entry into the local reference table and returns the
298 *******************************************************************************/
300 java_handle_t *localref_add(java_object_t *o)
308 log_println("localref_add: WARNING: trying to add localref for (NIL)!");
313 /* XXX: assert that we are in a GC critical section! */
315 /* XXX: this is only an ugly hack */
316 #if defined(ENABLE_HANDLES)
317 if (LOCALREFTABLE == NULL) {
318 h = NEW(java_handle_t);
320 log_println("localref_add: WARNING: added preliminary localref %p for %p", h, o);
325 /* get current local reference table from thread */
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... */
335 if (lrt->used == lrt->capacity) {
336 if (!localref_frame_push(16))
339 /* get the new local reference table */
344 /* insert the reference into the local reference table */
346 for (i = 0; i < lrt->capacity; i++) {
347 if (lrt->refs[i] == NULL) {
351 #if defined(ENABLE_HANDLES)
352 h = (java_handle_t *) &(lrt->refs[i]);
354 h = (java_handle_t *) o;
360 for (lrt = LOCALREFTABLE; lrt != NULL; lrt = lrt->prev)
362 log_println("added localref %p for %p (total count %d)", h, o, count);
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 */
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];
425 /* this should not happen */
427 log_println("localref_del: WARNING: unable to find localref %p", localref);
431 /* localref_native_enter *******************************************************
433 Insert arguments to a native method into the local reference table.
434 This is done by the native stub through codegen_start_native_call.
436 *******************************************************************************/
438 void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
446 /* 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 */
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);
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) */
581 * These are local overrides for various environment variables in Emacs.
582 * Please do not remove this and leave it at the end of the file, where
583 * Emacs will automagically detect them.
584 * ---------------------------------------------------------------------
587 * indent-tabs-mode: t
591 * vim:noexpandtab:sw=4:ts=4: