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"
44 /* debug **********************************************************************/
46 #if !defined(NDEBUG) && 0
47 # define TRACELOCALREF(message) log_println("%s", message)
49 # define TRACELOCALREF(message)
53 /* global variables ***********************************************************/
55 #if !defined(ENABLE_THREADS)
56 localref_table *_no_threads_localref_table;
60 /* localref_table_init *********************************************************
62 Initializes the local references table of the current thread.
64 *******************************************************************************/
66 bool localref_table_init(void)
70 TRACELOCALREF("table init");
72 assert(LOCALREFTABLE == NULL);
74 #if defined(ENABLE_GC_CACAO)
75 /* this is freed by localref_table_destroy */
76 lrt = NEW(localref_table);
78 /* this does not need to be freed again */
79 lrt = GCNEW(localref_table);
85 localref_table_add(lrt);
91 /* localref_table_destroy ******************************************************
93 Destroys the complete local references table of the current thread.
95 *******************************************************************************/
97 bool localref_table_destroy(void)
101 TRACELOCALREF("table destroy");
106 assert(lrt->prev == NULL);
108 #if defined(ENABLE_GC_CACAO)
109 FREE(lrt, localref_table);
112 LOCALREFTABLE = NULL;
118 /* localref_table_add **********************************************************
120 Adds a new local references table to the current thread.
122 *******************************************************************************/
124 void localref_table_add(localref_table *lrt)
126 /* initialize the local reference table */
128 lrt->capacity = LOCALREFTABLE_CAPACITY;
130 lrt->localframes = 1;
131 lrt->prev = LOCALREFTABLE;
133 /* clear the references array (memset is faster the a for-loop) */
135 MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
137 /* add given local references table to this thread */
143 /* localref_table_remove *******************************************************
145 Removes the topmost local references table from the current thread.
147 *******************************************************************************/
149 void localref_table_remove()
153 /* get current local reference table from thread */
158 assert(lrt->localframes == 1);
166 /* localref_frame_push *********************************************************
168 Creates a new local reference frame, in which at least a given
169 number of local references can be created.
171 *******************************************************************************/
173 bool localref_frame_push(int32_t capacity)
176 localref_table *nlrt;
177 int32_t additionalrefs;
179 TRACELOCALREF("frame push");
181 /* get current local reference table from thread */
186 assert(capacity > 0);
188 /* Allocate new local reference table on Java heap. Calculate the
189 additional memory we have to allocate. */
191 if (capacity > LOCALREFTABLE_CAPACITY)
192 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
196 #if defined(ENABLE_GC_CACAO)
197 nlrt = (localref_table *)
198 MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
200 nlrt = (localref_table *)
201 GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
207 /* Set up the new local reference table and add it to the local
210 nlrt->capacity = capacity;
212 nlrt->localframes = lrt->localframes + 1;
215 /* store new local reference table in thread */
217 LOCALREFTABLE = nlrt;
223 /* localref_frame_pop_all ******************************************************
225 Pops off all the local reference frames of the current table.
227 *******************************************************************************/
229 void localref_frame_pop_all(void)
232 localref_table *plrt;
234 #if defined(ENABLE_GC_CACAO)
235 int32_t additionalrefs;
238 TRACELOCALREF("frame pop all");
240 /* get current local reference table from thread */
246 localframes = lrt->localframes;
248 /* Don't delete the top local frame, as this one is allocated in
249 the native stub on the stack and is freed automagically on
252 if (localframes == 1)
255 /* release all current local frames */
257 for (; localframes > 1; localframes--) {
258 /* get previous frame */
262 /* clear all reference entries */
264 MSET(lrt->refs, 0, void*, lrt->capacity);
268 #if defined(ENABLE_GC_CACAO)
269 /* for the exact GC local reference tables are not on the heap,
270 so we need to free them explicitly here. */
272 if (lrt->capacity > LOCALREFTABLE_CAPACITY)
273 additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
277 MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
280 /* set new local references table */
285 /* store new local reference table in thread */
291 /* localref_add ****************************************************************
293 Adds a new entry into the local reference table and returns the
296 *******************************************************************************/
298 java_handle_t *localref_add(java_object_t *o)
306 log_println("localref_add: WARNING: trying to add localref for (NIL)!");
311 /* XXX: assert that we are in a GC critical section! */
313 /* XXX: this is only an ugly hack */
314 #if defined(ENABLE_HANDLES)
315 if (LOCALREFTABLE == NULL) {
316 h = NEW(java_handle_t);
318 log_println("localref_add: WARNING: added preliminary localref %p for %p", h, o);
323 /* get current local reference table from thread */
329 /* Check if we have space for the requested reference? No,
330 allocate a new frame. This is actually not what the spec says,
331 but for compatibility reasons... */
333 if (lrt->used == lrt->capacity) {
334 if (!localref_frame_push(16))
337 /* get the new local reference table */
342 /* insert the reference into the local reference table */
344 for (i = 0; i < lrt->capacity; i++) {
345 if (lrt->refs[i] == NULL) {
349 #if defined(ENABLE_HANDLES)
350 h = (java_handle_t *) &(lrt->refs[i]);
352 h = (java_handle_t *) o;
358 for (lrt = LOCALREFTABLE; lrt != NULL; lrt = lrt->prev)
360 log_println("added localref %p for %p (total count %d)", h, o, count);
369 /* this should not happen */
371 log_println("localref_add: WARNING: unable to add localref for %p", o);
377 /* localref_del ****************************************************************
379 Deletes an entry from the local reference table.
381 *******************************************************************************/
383 void localref_del(java_handle_t *localref)
390 /* get local reference table from thread */
396 localframes = lrt->localframes;
398 /* go through all local frames of the current table */
399 /* XXX: this is propably not what the spec wants! */
401 for (; localframes > 0; localframes--) {
403 /* and try to remove the reference */
405 for (i = 0; i < lrt->capacity; i++) {
406 #if defined(ENABLE_HANDLES)
407 h = (java_handle_t *) &(lrt->refs[i]);
409 h = (java_handle_t *) lrt->refs[i];
423 /* this should not happen */
425 log_println("localref_del: WARNING: unable to find localref %p", localref);
429 void _array_store_param(paramdesc *pd, typedesc *td, uint64_t *arg_regs, uint64_t *stack, imm_union param)
434 #if (SIZEOF_VOID_P == 8)
435 stack[pd->index] = param.l;
440 arg_regs[pd->index] = param.l;
444 vm_abort("_array_store_param: type not implemented");
450 /* localref_fill ***************************************************************
452 Insert arguments to a native method into the local reference table.
453 This is done by the native stub through codegen_start_native_call.
455 *******************************************************************************/
457 /* XXX these two function are in trace.c and above ...
458 * move them somewhere else!!! */
459 imm_union _array_load_param(paramdesc *pd, typedesc *td, uint64_t *arg_regs, uint64_t *stack);
460 void _array_store_param(paramdesc *pd, typedesc *td, uint64_t *arg_regs, uint64_t *stack, imm_union param);
462 void localref_fill(methodinfo *m, uint64_t *args_regs, uint64_t *args_stack)
472 /* get local reference table from thread */
481 /* walk through all parameters to the method */
483 for (i = 0; i < md->paramcount; ++i) {
485 td = &md->paramtypes[i];
487 /* load TYPE_ADR parameters ... */
489 if (td->type == TYPE_ADR) {
490 arg = _array_load_param(pd, td, args_regs, args_stack);
495 /* ... and insert them into the table */
497 h = localref_add((java_object_t *) arg.a);
499 /* update the parameter */
502 _array_store_param(pd, td, args_regs, args_stack, arg);
508 /* localref_dump ***************************************************************
510 Dumps all local reference tables, including all frames.
512 *******************************************************************************/
515 # define LOCALREF_DUMP_REFS_PER_LINE 4
521 /* get current local reference table from thread */
525 log_println("--------- Local Reference Tables Dump ---------");
527 while (lrt != NULL) {
528 log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
530 if (lrt->used != 0) {
535 for (i = 0; i < lrt->capacity; i++) {
536 if (lrt->refs[i] != NULL) {
537 if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
542 log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
552 #endif /* !defined(NDEBUG) */
556 * These are local overrides for various environment variables in Emacs.
557 * Please do not remove this and leave it at the end of the file, where
558 * Emacs will automagically detect them.
559 * ---------------------------------------------------------------------
562 * indent-tabs-mode: t
566 * vim:noexpandtab:sw=4:ts=4: