1 /* vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Contains C functions for JavaVM Instructions that cannot be
32 translated to machine language directly. Consequently, the
33 generated machine code for these instructions contains function
34 calls instead of machine instructions, using the C calling
37 $Id: builtin.c 1774 2004-12-20 20:16:57Z jowenn $
47 #include "mm/memory.h"
48 #include "native/native.h"
49 #include "native/include/java_lang_Cloneable.h"
50 #include "native/include/java_lang_VMObject.h"
52 #if defined(USE_THREADS)
53 # if defined(NATIVE_THREADS)
54 # include "threads/native/threads.h"
56 # include "threads/green/threads.h"
57 # include "threads/green/locks.h"
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/exceptions.h"
64 #include "vm/global.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/tables.h"
68 #include "vm/jit/asmpart.h"
71 #undef DEBUG /*define DEBUG 1*/
73 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
74 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
76 /*****************************************************************************
78 *****************************************************************************/
82 /*************** internal function: builtin_isanysubclass *********************
84 Checks a subclass relation between two classes. Implemented interfaces
85 are interpreted as super classes.
86 Return value: 1 ... sub is subclass of super
89 *****************************************************************************/
90 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
96 if (super->flags & ACC_INTERFACE)
97 return (sub->vftbl->interfacetablelength > super->index) &&
98 (sub->vftbl->interfacetable[-super->index] != NULL);
100 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
102 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
103 (unsigned) classvalues.super_diffval;
108 s4 builtin_isanysubclass_vftbl(vftbl_t *sub,vftbl_t *super)
112 castinfo classvalues;
114 asm_getclassvalues_atomic(super, sub, &classvalues);
116 if ((base = classvalues.super_baseval) <= 0)
117 /* super is an interface */
118 res = (sub->interfacetablelength > -base) &&
119 (sub->interfacetable[base] != NULL);
121 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
122 <= (unsigned) classvalues.super_diffval;
128 /****************** function: builtin_instanceof *****************************
130 Checks if an object is an instance of some given class (or subclass of
131 that class). If class is an interface, checks if the interface is
133 Return value: 1 ... obj is an instance of class or implements the interface
134 0 ... otherwise or if obj == NULL
136 *****************************************************************************/
138 /* XXX should use vftbl */
139 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
142 log_text ("builtin_instanceof called");
145 return builtin_isanysubclass (obj->vftbl->class, class);
150 /**************** function: builtin_checkcast *******************************
152 The same as builtin_instanceof except that 1 is returned when
155 ****************************************************************************/
157 /* XXX should use vftbl */
158 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
161 log_text("builtin_checkcast called");
166 if (builtin_isanysubclass(obj->vftbl->class, class))
170 printf("#### checkcast failed ");
171 utf_display(obj->vftbl->class->name);
173 utf_display(class->name);
181 /*********** internal function: builtin_descriptorscompatible ******************
183 Checks if two array type descriptors are assignment compatible
184 Return value: 1 ... target = desc is possible
187 ******************************************************************************/
189 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
191 if (desc==target) return 1;
192 if (desc->arraytype != target->arraytype) return 0;
193 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
195 /* {both arrays are arrays of references} */
196 if (desc->dimension == target->dimension) {
197 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
198 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
199 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
201 if (desc->dimension < target->dimension) return 0;
203 /* {desc has higher dimension than target} */
204 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
208 /******************** function: builtin_checkarraycast ***********************
210 Checks if an object is really a subtype of the requested array type.
211 The object has to be an array to begin with. For simple arrays (int, short,
212 double, etc.) the types have to match exactly.
213 For arrays of objects, the type of elements in the array has to be a
214 subtype (or the same type) of the requested element type. For arrays of
215 arrays (which in turn can again be arrays of arrays), the types at the
216 lowest level have to satisfy the corresponding sub class relation.
218 Return value: 1 ... cast is possible
221 ATTENTION: a cast with a NULL pointer is always possible.
223 *****************************************************************************/
225 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
227 arraydescriptor *desc;
230 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
232 return builtin_descriptorscompatible(desc, target->arraydesc);
236 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
239 return builtin_checkarraycast(obj, target);
243 /************************** exception functions *******************************
245 ******************************************************************************/
247 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
250 char logtext[MAXLOGTEXT];
251 sprintf(logtext, "Builtin exception thrown: ");
253 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
255 utf_sprint_classname(logtext + strlen(logtext),
256 xptr->vftbl->class->name);
258 if (t->detailMessage) {
259 sprintf(logtext + strlen(logtext), ": %s",
260 javastring_tochar((java_objectheader *) t->detailMessage));
264 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
269 *exceptionptr = xptr;
276 /******************* function: builtin_canstore *******************************
278 Checks, if an object can be stored in an array.
279 Return value: 1 ... possible
282 ******************************************************************************/
284 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
286 arraydescriptor *desc;
287 arraydescriptor *valuedesc;
288 vftbl_t *componentvftbl;
292 castinfo classvalues;
296 /* The following is guaranteed (by verifier checks):
298 * *) a->...vftbl->arraydesc != NULL
299 * *) a->...vftbl->arraydesc->componentvftbl != NULL
300 * *) o->vftbl is not an interface vftbl
303 desc = a->header.objheader.vftbl->arraydesc;
304 componentvftbl = desc->componentvftbl;
305 valuevftbl = o->vftbl;
307 if ((dim_m1 = desc->dimension - 1) == 0) {
310 /* {a is a one-dimensional array} */
311 /* {a is an array of references} */
313 if (valuevftbl == componentvftbl)
316 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
318 if ((base = classvalues.super_baseval) <= 0)
319 /* an array of interface references */
320 return (valuevftbl->interfacetablelength > -base &&
321 valuevftbl->interfacetable[base] != NULL);
323 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
324 <= (unsigned) classvalues.super_diffval;
328 /* {a has dimension > 1} */
329 /* {componentvftbl->arraydesc != NULL} */
331 /* check if o is an array */
332 if ((valuedesc = valuevftbl->arraydesc) == NULL)
334 /* {o is an array} */
336 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
340 /* This is an optimized version where a is guaranteed to be one-dimensional */
341 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
343 arraydescriptor *desc;
344 vftbl_t *elementvftbl;
348 castinfo classvalues;
352 /* The following is guaranteed (by verifier checks):
354 * *) a->...vftbl->arraydesc != NULL
355 * *) a->...vftbl->arraydesc->elementvftbl != NULL
356 * *) a->...vftbl->arraydesc->dimension == 1
357 * *) o->vftbl is not an interface vftbl
360 desc = a->header.objheader.vftbl->arraydesc;
361 elementvftbl = desc->elementvftbl;
362 valuevftbl = o->vftbl;
364 /* {a is a one-dimensional array} */
366 if (valuevftbl == elementvftbl)
369 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
371 if ((base = classvalues.super_baseval) <= 0)
372 /* an array of interface references */
373 return (valuevftbl->interfacetablelength > -base &&
374 valuevftbl->interfacetable[base] != NULL);
376 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
377 <= (unsigned) classvalues.super_diffval;
383 /* This is an optimized version where a is guaranteed to be a
384 * one-dimensional array of a class type */
385 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
387 vftbl_t *elementvftbl;
390 castinfo classvalues;
394 /* The following is guaranteed (by verifier checks):
396 * *) a->...vftbl->arraydesc != NULL
397 * *) a->...vftbl->arraydesc->elementvftbl != NULL
398 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
399 * *) a->...vftbl->arraydesc->dimension == 1
400 * *) o->vftbl is not an interface vftbl
403 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
404 valuevftbl = o->vftbl;
406 /* {a is a one-dimensional array} */
408 if (valuevftbl == elementvftbl)
411 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
413 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
414 <= (unsigned) classvalues.super_diffval;
420 /******************** Function: builtin_new **********************************
422 Creates a new instance of class c on the heap.
423 Return value: pointer to the object or NULL if no memory is
426 *****************************************************************************/
429 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
431 java_objectheader *builtin_new(classinfo *c)
433 java_objectheader *o;
435 /* is the class loaded */
440 /* is the class linked */
445 if (!c->initialized) {
447 log_message_class("Initialize class (from builtin_new): ", c);
453 #ifdef SIZE_FROM_CLASSINFO
454 c->alignedsize = align_size(c->instancesize);
455 o = heap_allocate(c->alignedsize, true, c->finalizer);
457 o = heap_allocate(c->instancesize, true, c->finalizer);
463 memset(o, 0, c->instancesize);
466 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
474 /********************** Function: builtin_newarray **************************
476 Creates an array with the given vftbl on the heap.
478 Return value: pointer to the array or NULL if no memory is available
480 CAUTION: The given vftbl must be the vftbl of the *array* class,
481 not of the element class.
483 *****************************************************************************/
485 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
488 arraydescriptor *desc;
493 desc = arrayvftbl->arraydesc;
494 dataoffset = desc->dataoffset;
495 componentsize = desc->componentsize;
499 new_exception(string_java_lang_NegativeArraySizeException);
503 #ifdef SIZE_FROM_CLASSINFO
504 actualsize = align_size(dataoffset + size * componentsize);
505 actualsize = dataoffset + size * componentsize;
510 if (((u4) actualsize) < ((u4) size)) { /* overflow */
511 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
515 a = heap_allocate(actualsize,
516 (desc->arraytype == ARRAYTYPE_OBJECT),
522 memset(a, 0, actualsize);
524 a->objheader.vftbl = arrayvftbl;
525 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
526 initObjectLock(&a->objheader);
529 #ifdef SIZE_FROM_CLASSINFO
530 a->alignedsize = actualsize;
537 /********************** Function: builtin_anewarray *************************
539 Creates an array of references to the given class type on the heap.
541 Return value: pointer to the array or NULL if no memory is available
543 XXX This function does not do The Right Thing, because it uses a
544 classinfo pointer at runtime. builtin_newarray should be used
547 *****************************************************************************/
549 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
551 /* is class loaded */
552 if (!component->loaded)
553 if (!class_load(component))
556 /* is class linked */
557 if (!component->linked)
558 if (!class_link(component))
561 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
565 /******************** Function: builtin_newarray_int ***********************
567 Creates an array of 32 bit Integers on the heap.
569 Return value: pointer to the array or NULL if no memory is available
571 *****************************************************************************/
573 java_intarray *builtin_newarray_int(s4 size)
575 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
579 /******************** Function: builtin_newarray_long ***********************
581 Creates an array of 64 bit Integers on the heap.
583 Return value: pointer to the array or NULL if no memory is available
585 *****************************************************************************/
587 java_longarray *builtin_newarray_long(s4 size)
589 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
593 /******************** function: builtin_newarray_float ***********************
595 Creates an array of 32 bit IEEE floats on the heap.
597 Return value: pointer to the array or NULL if no memory is available
599 *****************************************************************************/
601 java_floatarray *builtin_newarray_float(s4 size)
603 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
607 /******************** function: builtin_newarray_double ***********************
609 Creates an array of 64 bit IEEE floats on the heap.
611 Return value: pointer to the array or NULL if no memory is available
613 *****************************************************************************/
615 java_doublearray *builtin_newarray_double(s4 size)
617 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
621 /******************** function: builtin_newarray_byte ***********************
623 Creates an array of 8 bit Integers on the heap.
625 Return value: pointer to the array or NULL if no memory is available
627 *****************************************************************************/
629 java_bytearray *builtin_newarray_byte(s4 size)
631 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
635 /******************** function: builtin_newarray_char ************************
637 Creates an array of characters on the heap.
639 Return value: pointer to the array or NULL if no memory is available
641 *****************************************************************************/
643 java_chararray *builtin_newarray_char(s4 size)
645 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
649 /******************** function: builtin_newarray_short ***********************
651 Creates an array of 16 bit Integers on the heap.
653 Return value: pointer to the array or NULL if no memory is available
655 *****************************************************************************/
657 java_shortarray *builtin_newarray_short(s4 size)
659 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
663 /******************** function: builtin_newarray_boolean ************************
665 Creates an array of bytes on the heap. The array is designated as an array
666 of booleans (important for casts)
668 Return value: pointer to the array or NULL if no memory is available
670 *****************************************************************************/
672 java_booleanarray *builtin_newarray_boolean(s4 size)
674 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
678 /**************** function: builtin_nmultianewarray ***************************
680 Creates a multi-dimensional array on the heap. The dimensions are passed in
684 n............number of dimensions to create
685 arrayvftbl...vftbl of the array class
686 dims.........array containing the size of each dimension to create
688 Return value: pointer to the array or NULL if no memory is available
690 ******************************************************************************/
692 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
693 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
697 vftbl_t *componentvftbl;
699 /* utf_display(arrayclass->name); */
701 /* class_load(arrayclass); */
702 /* class_link(arrayclass); */
704 /* create this dimension */
706 a = builtin_newarray(size, arrayvftbl);
707 /* a = builtin_newarray(size, arrayclass->vftbl); */
712 /* if this is the last dimension return */
716 /* get the vftbl of the components to create */
717 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
718 /* component = arrayclass->vftbl->arraydesc; */
720 /* The verifier guarantees this. */
721 /* if (!componentvftbl) */
722 /* panic ("multianewarray with too many dimensions"); */
724 /* create the component arrays */
725 for (i = 0; i < size; i++) {
726 java_arrayheader *ea =
727 builtin_nmultianewarray(n, componentvftbl, dims + 1);
732 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
739 /*****************************************************************************
742 Various functions for printing a message at method entry or exit (for
745 *****************************************************************************/
749 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
759 log_text("WARNING: unmatched methodindent--");
761 if (opt_verbose || runverbose || verboseexception) {
763 printf("Exception ");
764 utf_display_classname(xptr->vftbl->class->name);
767 printf("Some Throwable");
769 printf(" thrown in ");
772 utf_display_classname(m->class->name);
774 utf_display(m->name);
775 if (m->flags & ACC_SYNCHRONIZED) {
782 if (m->flags & ACC_NATIVE) {
785 printf(")(0x%016lx) at position %p\n", (s8) m->entrypoint, pos);
787 printf(")(0x%08lx) at position %p\n", (s4) m->entrypoint, pos);
792 printf(")(0x%016lx) at position %p (", (s8) m->entrypoint, pos);
794 printf(")(0x%08lx) at position %p (", (s4) m->entrypoint, pos);
796 if (m->class->sourcefile == NULL) {
797 printf("<NO CLASSFILE INFORMATION>");
800 utf_display(m->class->sourcefile);
802 printf(":%d)\n", line);
806 printf("call_java_method\n");
814 #ifdef TRACE_ARGS_NUM
815 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
816 #if TRACE_ARGS_NUM > 6
822 char logtext[MAXLOGTEXT];
823 for (i = 0; i < methodindent; i++)
826 sprintf(logtext + methodindent, "called: ");
827 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
828 sprintf(logtext + strlen(logtext), ".");
829 utf_sprint(logtext + strlen(logtext), m->name);
830 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
832 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
833 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
834 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
835 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
836 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
837 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
838 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
839 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
840 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
841 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
842 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
845 sprintf(logtext + strlen(logtext), "(");
847 switch (m->paramcount) {
851 #if defined(__I386__) || defined(__POWERPC__)
853 sprintf(logtext+strlen(logtext), "%llx", a0);
857 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
861 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
865 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
870 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
875 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
876 a0, a1, a2, a3, a4, a5);
879 #if TRACE_ARGS_NUM > 6
881 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
882 a0, a1, a2, a3, a4, a5, a6);
886 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
887 a0, a1, a2, a3, a4, a5, a6, a7);
891 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
892 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
896 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
897 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
902 sprintf(logtext+strlen(logtext), "%lx", a0);
906 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
910 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
914 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
919 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
924 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
925 a0, a1, a2, a3, a4, a5);
928 #if TRACE_ARGS_NUM > 6
930 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
931 a0, a1, a2, a3, a4, a5, a6);
935 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
936 a0, a1, a2, a3, a4, a5, a6, a7);
940 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
941 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
945 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
946 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
952 sprintf(logtext + strlen(logtext), ")");
960 void builtin_displaymethodstart(methodinfo *m)
962 char logtext[MAXLOGTEXT];
963 sprintf(logtext, " ");
964 sprintf(logtext + methodindent, "called: ");
965 utf_sprint(logtext + strlen(logtext), m->class->name);
966 sprintf(logtext + strlen(logtext), ".");
967 utf_sprint(logtext + strlen(logtext), m->name);
968 utf_sprint(logtext + strlen(logtext), m->descriptor);
970 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
971 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
972 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
973 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
974 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
975 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
976 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
977 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
978 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
979 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
980 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
987 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
990 char logtext[MAXLOGTEXT];
991 for (i = 0; i < methodindent; i++)
996 log_text("WARNING: unmatched methodindent--");
998 sprintf(logtext + methodindent, "finished: ");
999 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1000 sprintf(logtext + strlen(logtext), ".");
1001 utf_sprint(logtext + strlen(logtext), m->name);
1002 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1004 switch (m->returntype) {
1006 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1010 #if defined(__I386__) || defined(__POWERPC__)
1011 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1013 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1018 #if defined(__I386__) || defined(__POWERPC__)
1019 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1021 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1026 sprintf(logtext + strlen(logtext), "->%g", f);
1030 sprintf(logtext + strlen(logtext), "->%g", d);
1037 /****************************************************************************
1038 SYNCHRONIZATION FUNCTIONS
1039 *****************************************************************************/
1042 * Lock the mutex of an object.
1044 void internal_lock_mutex_for_object(java_objectheader *object)
1046 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1047 mutexHashEntry *entry;
1050 assert(object != 0);
1052 hashValue = MUTEX_HASH_VALUE(object);
1053 entry = &mutexHashTable[hashValue];
1055 if (entry->object != 0) {
1056 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1058 entry->mutex.holder = 0;
1059 entry->mutex.count = 0;
1060 entry->mutex.muxWaiters = 0;
1063 while (entry->next != 0 && entry->object != object)
1064 entry = entry->next;
1066 if (entry->object != object) {
1067 entry->next = firstFreeOverflowEntry;
1068 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1070 entry = entry->next;
1073 assert(entry->conditionCount == 0);
1078 entry->mutex.holder = 0;
1079 entry->mutex.count = 0;
1080 entry->mutex.muxWaiters = 0;
1083 if (entry->object == 0)
1084 entry->object = object;
1086 internal_lock_mutex(&entry->mutex);
1092 * Unlocks the mutex of an object.
1094 void internal_unlock_mutex_for_object (java_objectheader *object)
1096 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1098 mutexHashEntry *entry;
1100 hashValue = MUTEX_HASH_VALUE(object);
1101 entry = &mutexHashTable[hashValue];
1103 if (entry->object == object) {
1104 internal_unlock_mutex(&entry->mutex);
1107 while (entry->next != 0 && entry->next->object != object)
1108 entry = entry->next;
1110 assert(entry->next != 0);
1112 internal_unlock_mutex(&entry->next->mutex);
1114 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1115 mutexHashEntry *unlinked = entry->next;
1117 entry->next = unlinked->next;
1118 unlinked->next = firstFreeOverflowEntry;
1119 firstFreeOverflowEntry = unlinked;
1126 void builtin_monitorenter(java_objectheader *o)
1128 #if defined(USE_THREADS)
1129 #if !defined(NATIVE_THREADS)
1134 hashValue = MUTEX_HASH_VALUE(o);
1135 if (mutexHashTable[hashValue].object == o
1136 && mutexHashTable[hashValue].mutex.holder == currentThread)
1137 ++mutexHashTable[hashValue].mutex.count;
1139 internal_lock_mutex_for_object(o);
1143 monitorEnter((threadobject *) THREADOBJECT, o);
1150 * Locks the class object - needed for static synchronized methods.
1151 * The use_class_as_object call is needed in order to circumvent a
1152 * possible deadlock with builtin_monitorenter called by another
1153 * thread calling use_class_as_object.
1155 void builtin_staticmonitorenter(classinfo *c)
1157 use_class_as_object(c);
1158 builtin_monitorenter(&c->header);
1162 void *builtin_monitorexit(java_objectheader *o)
1164 #if defined(USE_THREADS)
1165 #if !defined(NATIVE_THREADS)
1170 hashValue = MUTEX_HASH_VALUE(o);
1171 if (mutexHashTable[hashValue].object == o) {
1172 if (mutexHashTable[hashValue].mutex.count == 1
1173 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1174 internal_unlock_mutex_for_object(o);
1176 --mutexHashTable[hashValue].mutex.count;
1179 internal_unlock_mutex_for_object(o);
1184 monitorExit((threadobject *) THREADOBJECT, o);
1191 /*****************************************************************************
1192 MISCELLANEOUS HELPER FUNCTIONS
1193 *****************************************************************************/
1197 /*********** Functions for integer divisions *****************************
1199 On some systems (eg. DEC ALPHA), integer division is not supported by the
1200 CPU. These helper functions implement the missing functionality.
1202 ******************************************************************************/
1204 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1205 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1208 /************** Functions for long arithmetics *******************************
1210 On systems where 64 bit Integers are not supported by the CPU, these
1211 functions are needed.
1213 ******************************************************************************/
1216 s8 builtin_ladd(s8 a, s8 b)
1221 return builtin_i2l(0);
1225 s8 builtin_lsub(s8 a, s8 b)
1230 return builtin_i2l(0);
1234 s8 builtin_lmul(s8 a, s8 b)
1239 return builtin_i2l(0);
1243 s8 builtin_ldiv(s8 a, s8 b)
1248 return builtin_i2l(0);
1252 s8 builtin_lrem(s8 a, s8 b)
1257 return builtin_i2l(0);
1261 s8 builtin_lshl(s8 a, s4 b)
1264 return a << (b & 63);
1266 return builtin_i2l(0);
1270 s8 builtin_lshr(s8 a, s4 b)
1273 return a >> (b & 63);
1275 return builtin_i2l(0);
1279 s8 builtin_lushr(s8 a, s4 b)
1282 return ((u8) a) >> (b & 63);
1284 return builtin_i2l(0);
1288 s8 builtin_land(s8 a, s8 b)
1293 return builtin_i2l(0);
1297 s8 builtin_lor(s8 a, s8 b)
1302 return builtin_i2l(0);
1306 s8 builtin_lxor(s8 a, s8 b)
1311 return builtin_i2l(0);
1315 s8 builtin_lneg(s8 a)
1320 return builtin_i2l(0);
1324 s4 builtin_lcmp(s8 a, s8 b)
1327 if (a < b) return -1;
1328 if (a > b) return 1;
1339 /*********** Functions for floating point operations *************************/
1341 float builtin_fadd(float a, float b)
1343 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1344 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1355 if (copysignf(1.0, a) == copysignf(1.0, b))
1358 return intBitsToFloat(FLT_NAN);
1364 float builtin_fsub(float a, float b)
1366 return builtin_fadd(a, builtin_fneg(b));
1370 float builtin_fmul(float a, float b)
1372 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1373 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1375 if (finitef(b)) return a * b;
1377 if (a == 0) return intBitsToFloat(FLT_NAN);
1378 else return copysignf(b, copysignf(1.0, b)*a);
1383 if (b == 0) return intBitsToFloat(FLT_NAN);
1384 else return copysignf(a, copysignf(1.0, a)*b);
1387 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1393 float builtin_fdiv(float a, float b)
1395 if (finitef(a) && finitef(b)) {
1400 return intBitsToFloat(FLT_POSINF);
1402 return intBitsToFloat(FLT_NEGINF);
1405 return intBitsToFloat(FLT_NAN);
1409 float builtin_frem(float a, float b)
1415 float builtin_fneg(float a)
1417 if (isnanf(a)) return a;
1419 if (finitef(a)) return -a;
1420 else return copysignf(a, -copysignf(1.0, a));
1425 s4 builtin_fcmpl(float a, float b)
1427 if (isnanf(a)) return -1;
1428 if (isnanf(b)) return -1;
1429 if (!finitef(a) || !finitef(b)) {
1430 a = finitef(a) ? 0 : copysignf(1.0, a);
1431 b = finitef(b) ? 0 : copysignf(1.0, b);
1433 if (a > b) return 1;
1434 if (a == b) return 0;
1439 s4 builtin_fcmpg(float a, float b)
1441 if (isnanf(a)) return 1;
1442 if (isnanf(b)) return 1;
1443 if (!finitef(a) || !finitef(b)) {
1444 a = finitef(a) ? 0 : copysignf(1.0, a);
1445 b = finitef(b) ? 0 : copysignf(1.0, b);
1447 if (a > b) return 1;
1448 if (a == b) return 0;
1454 /************************* Functions for doubles ****************************/
1456 double builtin_dadd(double a, double b)
1458 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1459 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1461 if (finite(b)) return a + b;
1465 if (finite(b)) return a;
1467 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1468 else return longBitsToDouble(DBL_NAN);
1474 double builtin_dsub(double a, double b)
1476 return builtin_dadd(a, builtin_dneg(b));
1480 double builtin_dmul(double a, double b)
1482 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1483 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1485 if (finite(b)) return a * b;
1487 if (a == 0) return longBitsToDouble(DBL_NAN);
1488 else return copysign(b, copysign(1.0, b) * a);
1493 if (b == 0) return longBitsToDouble(DBL_NAN);
1494 else return copysign(a, copysign(1.0, a) * b);
1497 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1503 double builtin_ddiv(double a, double b)
1511 return longBitsToDouble(DBL_NAN);
1513 return copysign(0.0, b);
1519 return longBitsToDouble(DBL_POSINF);
1521 return longBitsToDouble(DBL_NEGINF);
1524 return longBitsToDouble(DBL_NAN);
1527 /* if (finite(a) && finite(b)) { */
1532 /* return longBitsToDouble(DBL_POSINF); */
1533 /* else if (a < 0) */
1534 /* return longBitsToDouble(DBL_NEGINF); */
1538 /* keep compiler happy */
1543 double builtin_drem(double a, double b)
1549 double builtin_dneg(double a)
1551 if (isnan(a)) return a;
1553 if (finite(a)) return -a;
1554 else return copysign(a, -copysign(1.0, a));
1559 s4 builtin_dcmpl(double a, double b)
1561 if (isnan(a)) return -1;
1562 if (isnan(b)) return -1;
1563 if (!finite(a) || !finite(b)) {
1564 a = finite(a) ? 0 : copysign(1.0, a);
1565 b = finite(b) ? 0 : copysign(1.0, b);
1567 if (a > b) return 1;
1568 if (a == b) return 0;
1573 s4 builtin_dcmpg(double a, double b)
1575 if (isnan(a)) return 1;
1576 if (isnan(b)) return 1;
1577 if (!finite(a) || !finite(b)) {
1578 a = finite(a) ? 0 : copysign(1.0, a);
1579 b = finite(b) ? 0 : copysign(1.0, b);
1581 if (a > b) return 1;
1582 if (a == b) return 0;
1587 /*********************** Conversion operations ****************************/
1589 s8 builtin_i2l(s4 i)
1602 float builtin_i2f(s4 a)
1604 float f = (float) a;
1609 double builtin_i2d(s4 a)
1611 double d = (double) a;
1616 s4 builtin_l2i(s8 l)
1626 float builtin_l2f(s8 a)
1629 float f = (float) a;
1637 double builtin_l2d(s8 a)
1640 double d = (double) a;
1648 s4 builtin_f2i(float a)
1651 return builtin_d2i((double) a);
1660 if (a < (-2147483648))
1661 return (-2147483648);
1664 f = copysignf((float) 1.0, a);
1667 return (-2147483648); */
1671 s8 builtin_f2l(float a)
1674 return builtin_d2l((double) a);
1679 if (a > 9223372036854775807L)
1680 return 9223372036854775807L;
1681 if (a < (-9223372036854775808L))
1682 return (-9223372036854775808L);
1687 f = copysignf((float) 1.0, a);
1689 return 9223372036854775807L;
1690 return (-9223372036854775808L); */
1694 double builtin_f2d(float a)
1696 if (finitef(a)) return (double) a;
1699 return longBitsToDouble(DBL_NAN);
1701 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1706 s4 builtin_d2i(double a)
1711 if (a >= 2147483647)
1713 if (a <= (-2147483647-1))
1714 return (-2147483647-1);
1719 d = copysign(1.0, a);
1722 return (-2147483647-1);
1726 s8 builtin_d2l(double a)
1731 if (a >= 9223372036854775807LL)
1732 return 9223372036854775807LL;
1733 if (a <= (-9223372036854775807LL-1))
1734 return (-9223372036854775807LL-1);
1739 d = copysign(1.0, a);
1741 return 9223372036854775807LL;
1742 return (-9223372036854775807LL-1);
1746 float builtin_d2f(double a)
1752 return intBitsToFloat(FLT_NAN);
1754 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1759 /* used to convert FLT_xxx defines into float values */
1761 inline float intBitsToFloat(s4 i)
1770 /* used to convert DBL_xxx defines into double values */
1772 inline float longBitsToDouble(s8 l)
1781 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1783 return (java_arrayheader *)
1784 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1790 panic("Internal error: builtin_dummy called (native function is missing)");
1791 return 0; /* for the compiler */
1795 /* builtin_asm_get_exceptionptrptr *********************************************
1797 this is a wrapper for calls from asmpart
1799 *******************************************************************************/
1801 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1802 java_objectheader **builtin_asm_get_exceptionptrptr()
1804 return builtin_get_exceptionptrptr();
1809 methodinfo *builtin_asm_get_threadrootmethod()
1811 return *threadrootmethod;
1815 inline void* builtin_asm_get_stackframeinfo()
1817 /*log_text("builtin_asm_get_stackframeinfo()");*/
1818 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1819 return &THREADINFO->_stackframeinfo;
1821 #if defined(__GNUC__)
1822 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1824 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1828 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1829 /* stacktraceelement *el;*/
1832 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1833 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1835 *el=MNEW(stacktraceelement,s+1); /*GC*/
1837 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1839 #if defined(__GNUC__)
1840 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1842 (*el)[s].linenumber=-1; /* -1 can never be reched otherwise, since line numbers are only u2, so it is save to use that as flag */
1847 * These are local overrides for various environment variables in Emacs.
1848 * Please do not remove this and leave it at the end of the file, where
1849 * Emacs will automagically detect them.
1850 * ---------------------------------------------------------------------
1853 * indent-tabs-mode: t