1 /* builtin.c - functions for unsupported operations
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
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 1533 2004-11-18 10:37:24Z twisti $
45 #include "exceptions.h"
54 #include "threads/thread.h"
55 #include "threads/locks.h"
56 #include "toolbox/logging.h"
57 #include "toolbox/memory.h"
58 #include "nat/java_lang_Cloneable.h"
61 #undef DEBUG /*define DEBUG 1*/
63 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
64 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
66 /*****************************************************************************
68 *****************************************************************************/
72 /*************** internal function: builtin_isanysubclass *********************
74 Checks a subclass relation between two classes. Implemented interfaces
75 are interpreted as super classes.
76 Return value: 1 ... sub is subclass of super
79 *****************************************************************************/
80 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
86 if (super->flags & ACC_INTERFACE)
87 return (sub->vftbl->interfacetablelength > super->index) &&
88 (sub->vftbl->interfacetable[-super->index] != NULL);
101 for (tmp=sub;tmp!=0;tmp=tmp->super) {
103 utf_display(tmp->name);
107 for (tmp=super;tmp!=0;tmp=tmp->super) {
109 utf_display(tmp->name);
114 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
115 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
116 super->vftbl->diffval); */
118 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
120 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
121 (unsigned) classvalues.super_diffval;
126 s4 builtin_isanysubclass_vftbl(vftbl_t *sub,vftbl_t *super)
130 castinfo classvalues;
132 asm_getclassvalues_atomic(super, sub, &classvalues);
134 if ((base = classvalues.super_baseval) <= 0)
135 /* super is an interface */
136 res = (sub->interfacetablelength > -base) &&
137 (sub->interfacetable[base] != NULL);
139 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
140 <= (unsigned) classvalues.super_diffval;
146 /****************** function: builtin_instanceof *****************************
148 Checks if an object is an instance of some given class (or subclass of
149 that class). If class is an interface, checks if the interface is
151 Return value: 1 ... obj is an instance of class or implements the interface
152 0 ... otherwise or if obj == NULL
154 *****************************************************************************/
156 /* XXX should use vftbl */
157 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
160 log_text ("builtin_instanceof called");
163 return builtin_isanysubclass (obj->vftbl->class, class);
168 /**************** function: builtin_checkcast *******************************
170 The same as builtin_instanceof except that 1 is returned when
173 ****************************************************************************/
175 /* XXX should use vftbl */
176 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
179 log_text("builtin_checkcast called");
184 if (builtin_isanysubclass(obj->vftbl->class, class))
188 printf("#### checkcast failed ");
189 utf_display(obj->vftbl->class->name);
191 utf_display(class->name);
199 /*********** internal function: builtin_descriptorscompatible ******************
201 Checks if two array type descriptors are assignment compatible
202 Return value: 1 ... target = desc is possible
205 ******************************************************************************/
207 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
209 if (desc==target) return 1;
210 if (desc->arraytype != target->arraytype) return 0;
211 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
213 /* {both arrays are arrays of references} */
214 if (desc->dimension == target->dimension) {
215 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
216 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
217 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
219 if (desc->dimension < target->dimension) return 0;
221 /* {desc has higher dimension than target} */
222 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
226 /******************** function: builtin_checkarraycast ***********************
228 Checks if an object is really a subtype of the requested array type.
229 The object has to be an array to begin with. For simple arrays (int, short,
230 double, etc.) the types have to match exactly.
231 For arrays of objects, the type of elements in the array has to be a
232 subtype (or the same type) of the requested element type. For arrays of
233 arrays (which in turn can again be arrays of arrays), the types at the
234 lowest level have to satisfy the corresponding sub class relation.
236 Return value: 1 ... cast is possible
239 ATTENTION: a cast with a NULL pointer is always possible.
241 *****************************************************************************/
243 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
245 arraydescriptor *desc;
248 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
250 return builtin_descriptorscompatible(desc, target->arraydesc);
254 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
257 return builtin_checkarraycast(obj, target);
261 /************************** exception functions *******************************
263 ******************************************************************************/
265 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
268 char logtext[MAXLOGTEXT];
269 sprintf(logtext, "Builtin exception thrown: ");
271 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
273 utf_sprint_classname(logtext + strlen(logtext),
274 xptr->vftbl->class->name);
276 if (t->detailMessage) {
277 sprintf(logtext + strlen(logtext), ": %s",
278 javastring_tochar((java_objectheader *) t->detailMessage));
282 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
287 *exceptionptr = xptr;
294 /******************* function: builtin_canstore *******************************
296 Checks, if an object can be stored in an array.
297 Return value: 1 ... possible
300 ******************************************************************************/
302 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
304 arraydescriptor *desc;
305 arraydescriptor *valuedesc;
306 vftbl_t *componentvftbl;
310 castinfo classvalues;
314 /* The following is guaranteed (by verifier checks):
316 * *) a->...vftbl->arraydesc != NULL
317 * *) a->...vftbl->arraydesc->componentvftbl != NULL
318 * *) o->vftbl is not an interface vftbl
321 desc = a->header.objheader.vftbl->arraydesc;
322 componentvftbl = desc->componentvftbl;
323 valuevftbl = o->vftbl;
325 if ((dim_m1 = desc->dimension - 1) == 0) {
328 /* {a is a one-dimensional array} */
329 /* {a is an array of references} */
331 if (valuevftbl == componentvftbl)
334 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
336 if ((base = classvalues.super_baseval) <= 0)
337 /* an array of interface references */
338 return (valuevftbl->interfacetablelength > -base &&
339 valuevftbl->interfacetable[base] != NULL);
341 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
342 <= (unsigned) classvalues.super_diffval;
346 /* {a has dimension > 1} */
347 /* {componentvftbl->arraydesc != NULL} */
349 /* check if o is an array */
350 if ((valuedesc = valuevftbl->arraydesc) == NULL)
352 /* {o is an array} */
354 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
358 /* This is an optimized version where a is guaranteed to be one-dimensional */
359 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
361 arraydescriptor *desc;
362 vftbl_t *elementvftbl;
366 castinfo classvalues;
370 /* The following is guaranteed (by verifier checks):
372 * *) a->...vftbl->arraydesc != NULL
373 * *) a->...vftbl->arraydesc->elementvftbl != NULL
374 * *) a->...vftbl->arraydesc->dimension == 1
375 * *) o->vftbl is not an interface vftbl
378 desc = a->header.objheader.vftbl->arraydesc;
379 elementvftbl = desc->elementvftbl;
380 valuevftbl = o->vftbl;
382 /* {a is a one-dimensional array} */
384 if (valuevftbl == elementvftbl)
387 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
389 if ((base = classvalues.super_baseval) <= 0)
390 /* an array of interface references */
391 return (valuevftbl->interfacetablelength > -base &&
392 valuevftbl->interfacetable[base] != NULL);
394 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
395 <= (unsigned) classvalues.super_diffval;
401 /* This is an optimized version where a is guaranteed to be a
402 * one-dimensional array of a class type */
403 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
405 vftbl_t *elementvftbl;
408 castinfo classvalues;
412 /* The following is guaranteed (by verifier checks):
414 * *) a->...vftbl->arraydesc != NULL
415 * *) a->...vftbl->arraydesc->elementvftbl != NULL
416 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
417 * *) a->...vftbl->arraydesc->dimension == 1
418 * *) o->vftbl is not an interface vftbl
421 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
422 valuevftbl = o->vftbl;
424 /* {a is a one-dimensional array} */
426 if (valuevftbl == elementvftbl)
429 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
431 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
432 <= (unsigned) classvalues.super_diffval;
438 /******************** Function: builtin_new **********************************
440 Creates a new instance of class c on the heap.
441 Return value: pointer to the object or NULL if no memory is
444 *****************************************************************************/
447 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
449 java_objectheader *builtin_new(classinfo *c)
451 java_objectheader *o;
453 /* is the class loaded */
458 /* is the class linked */
463 if (!c->initialized) {
465 log_message_class("Initialize class (from builtin_new): ", c);
471 #ifdef SIZE_FROM_CLASSINFO
472 c->alignedsize = align_size(c->instancesize);
473 o = heap_allocate(c->alignedsize, true, c->finalizer);
475 o = heap_allocate(c->instancesize, true, c->finalizer);
481 memset(o, 0, c->instancesize);
484 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
492 /********************** Function: builtin_newarray **************************
494 Creates an array with the given vftbl on the heap.
496 Return value: pointer to the array or NULL if no memory is available
498 CAUTION: The given vftbl must be the vftbl of the *array* class,
499 not of the element class.
501 *****************************************************************************/
503 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
506 arraydescriptor *desc;
511 desc = arrayvftbl->arraydesc;
512 dataoffset = desc->dataoffset;
513 componentsize = desc->componentsize;
517 new_exception(string_java_lang_NegativeArraySizeException);
521 #ifdef SIZE_FROM_CLASSINFO
522 actualsize = align_size(dataoffset + size * componentsize);
523 actualsize = dataoffset + size * componentsize;
528 if (((u4) actualsize) < ((u4) size)) { /* overflow */
529 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
533 a = heap_allocate(actualsize,
534 (desc->arraytype == ARRAYTYPE_OBJECT),
540 memset(a, 0, actualsize);
542 a->objheader.vftbl = arrayvftbl;
543 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
544 initObjectLock(&a->objheader);
547 #ifdef SIZE_FROM_CLASSINFO
548 a->alignedsize = actualsize;
555 /********************** Function: builtin_anewarray *************************
557 Creates an array of references to the given class type on the heap.
559 Return value: pointer to the array or NULL if no memory is available
561 XXX This function does not do The Right Thing, because it uses a
562 classinfo pointer at runtime. builtin_newarray should be used
565 *****************************************************************************/
567 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
569 /* is class loaded */
570 if (!component->loaded)
571 if (!class_load(component))
574 /* is class linked */
575 if (!component->linked)
576 if (!class_link(component))
579 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
583 /******************** Function: builtin_newarray_int ***********************
585 Creates an array of 32 bit Integers on the heap.
587 Return value: pointer to the array or NULL if no memory is available
589 *****************************************************************************/
591 java_intarray *builtin_newarray_int(s4 size)
593 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
597 /******************** Function: builtin_newarray_long ***********************
599 Creates an array of 64 bit Integers on the heap.
601 Return value: pointer to the array or NULL if no memory is available
603 *****************************************************************************/
605 java_longarray *builtin_newarray_long(s4 size)
607 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
611 /******************** function: builtin_newarray_float ***********************
613 Creates an array of 32 bit IEEE floats on the heap.
615 Return value: pointer to the array or NULL if no memory is available
617 *****************************************************************************/
619 java_floatarray *builtin_newarray_float(s4 size)
621 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
625 /******************** function: builtin_newarray_double ***********************
627 Creates an array of 64 bit IEEE floats on the heap.
629 Return value: pointer to the array or NULL if no memory is available
631 *****************************************************************************/
633 java_doublearray *builtin_newarray_double(s4 size)
635 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
639 /******************** function: builtin_newarray_byte ***********************
641 Creates an array of 8 bit Integers on the heap.
643 Return value: pointer to the array or NULL if no memory is available
645 *****************************************************************************/
647 java_bytearray *builtin_newarray_byte(s4 size)
649 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
653 /******************** function: builtin_newarray_char ************************
655 Creates an array of characters on the heap.
657 Return value: pointer to the array or NULL if no memory is available
659 *****************************************************************************/
661 java_chararray *builtin_newarray_char(s4 size)
663 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
667 /******************** function: builtin_newarray_short ***********************
669 Creates an array of 16 bit Integers on the heap.
671 Return value: pointer to the array or NULL if no memory is available
673 *****************************************************************************/
675 java_shortarray *builtin_newarray_short(s4 size)
677 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
681 /******************** function: builtin_newarray_boolean ************************
683 Creates an array of bytes on the heap. The array is designated as an array
684 of booleans (important for casts)
686 Return value: pointer to the array or NULL if no memory is available
688 *****************************************************************************/
690 java_booleanarray *builtin_newarray_boolean(s4 size)
692 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
696 /**************** function: builtin_nmultianewarray ***************************
698 Creates a multi-dimensional array on the heap. The dimensions are passed in
702 n............number of dimensions to create
703 arrayvftbl...vftbl of the array class
704 dims.........array containing the size of each dimension to create
706 Return value: pointer to the array or NULL if no memory is available
708 ******************************************************************************/
710 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
711 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
715 vftbl_t *componentvftbl;
717 /* utf_display(arrayclass->name); */
719 /* class_load(arrayclass); */
720 /* class_link(arrayclass); */
722 /* create this dimension */
724 a = builtin_newarray(size, arrayvftbl);
725 /* a = builtin_newarray(size, arrayclass->vftbl); */
730 /* if this is the last dimension return */
734 /* get the vftbl of the components to create */
735 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
736 /* component = arrayclass->vftbl->arraydesc; */
738 /* The verifier guarantees this. */
739 /* if (!componentvftbl) */
740 /* panic ("multianewarray with too many dimensions"); */
742 /* create the component arrays */
743 for (i = 0; i < size; i++) {
744 java_arrayheader *ea =
745 builtin_nmultianewarray(n, componentvftbl, dims + 1);
750 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
757 /*****************************************************************************
760 Various functions for printing a message at method entry or exit (for
763 *****************************************************************************/
767 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
777 log_text("WARNING: unmatched methodindent--");
779 if (verbose || runverbose || verboseexception) {
781 printf("Exception ");
782 utf_display_classname(xptr->vftbl->class->name);
785 printf("Some Throwable");
787 printf(" thrown in ");
790 utf_display_classname(m->class->name);
792 utf_display(m->name);
793 if (m->flags & ACC_SYNCHRONIZED) {
800 if (m->flags & ACC_NATIVE) {
803 printf(")(0x%016lx) at position %p\n", (s8) m->entrypoint, pos);
805 printf(")(0x%08lx) at position %p\n", (s4) m->entrypoint, pos);
810 printf(")(0x%016lx) at position %p (", (s8) m->entrypoint, pos);
812 printf(")(0x%08lx) at position %p (", (s4) m->entrypoint, pos);
814 if (m->class->sourcefile == NULL) {
815 printf("<NO CLASSFILE INFORMATION>");
818 utf_display(m->class->sourcefile);
820 printf(":%d)\n", line);
824 printf("call_java_method\n");
832 #ifdef TRACE_ARGS_NUM
833 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
834 #if TRACE_ARGS_NUM > 6
840 char logtext[MAXLOGTEXT];
841 for (i = 0; i < methodindent; i++)
844 sprintf(logtext + methodindent, "called: ");
845 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
846 sprintf(logtext + strlen(logtext), ".");
847 utf_sprint(logtext + strlen(logtext), m->name);
848 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
850 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
851 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
852 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
853 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
854 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
855 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
856 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
857 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
858 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
859 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
860 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
863 sprintf(logtext + strlen(logtext), "(");
865 switch (m->paramcount) {
869 #if defined(__I386__) || defined(__POWERPC__)
871 sprintf(logtext+strlen(logtext), "%llx", a0);
875 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
879 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
883 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
888 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
893 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
894 a0, a1, a2, a3, a4, a5);
897 #if TRACE_ARGS_NUM > 6
899 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
900 a0, a1, a2, a3, a4, a5, a6);
904 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
905 a0, a1, a2, a3, a4, a5, a6, a7);
909 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
910 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
914 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
915 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
920 sprintf(logtext+strlen(logtext), "%lx", a0);
924 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
928 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
932 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
937 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
942 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
943 a0, a1, a2, a3, a4, a5);
946 #if TRACE_ARGS_NUM > 6
948 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
949 a0, a1, a2, a3, a4, a5, a6);
953 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
954 a0, a1, a2, a3, a4, a5, a6, a7);
958 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
959 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
963 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
964 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
970 sprintf(logtext + strlen(logtext), ")");
978 void builtin_displaymethodstart(methodinfo *m)
980 char logtext[MAXLOGTEXT];
981 sprintf(logtext, " ");
982 sprintf(logtext + methodindent, "called: ");
983 utf_sprint(logtext + strlen(logtext), m->class->name);
984 sprintf(logtext + strlen(logtext), ".");
985 utf_sprint(logtext + strlen(logtext), m->name);
986 utf_sprint(logtext + strlen(logtext), m->descriptor);
988 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
989 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
990 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
991 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
992 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
993 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
994 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
995 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
996 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
997 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
998 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1005 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1008 char logtext[MAXLOGTEXT];
1009 for (i = 0; i < methodindent; i++)
1014 log_text("WARNING: unmatched methodindent--");
1016 sprintf(logtext + methodindent, "finished: ");
1017 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1018 sprintf(logtext + strlen(logtext), ".");
1019 utf_sprint(logtext + strlen(logtext), m->name);
1020 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1022 switch (m->returntype) {
1024 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1028 #if defined(__I386__) || defined(__POWERPC__)
1029 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1031 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1036 #if defined(__I386__) || defined(__POWERPC__)
1037 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1039 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1044 sprintf(logtext + strlen(logtext), "->%g", f);
1048 sprintf(logtext + strlen(logtext), "->%g", d);
1055 /****************************************************************************
1056 SYNCHRONIZATION FUNCTIONS
1057 *****************************************************************************/
1060 * Lock the mutex of an object.
1062 void internal_lock_mutex_for_object(java_objectheader *object)
1064 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1065 mutexHashEntry *entry;
1068 assert(object != 0);
1070 hashValue = MUTEX_HASH_VALUE(object);
1071 entry = &mutexHashTable[hashValue];
1073 if (entry->object != 0) {
1074 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1076 entry->mutex.holder = 0;
1077 entry->mutex.count = 0;
1078 entry->mutex.muxWaiters = 0;
1081 while (entry->next != 0 && entry->object != object)
1082 entry = entry->next;
1084 if (entry->object != object) {
1085 entry->next = firstFreeOverflowEntry;
1086 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1088 entry = entry->next;
1091 assert(entry->conditionCount == 0);
1096 entry->mutex.holder = 0;
1097 entry->mutex.count = 0;
1098 entry->mutex.muxWaiters = 0;
1101 if (entry->object == 0)
1102 entry->object = object;
1104 internal_lock_mutex(&entry->mutex);
1110 * Unlocks the mutex of an object.
1112 void internal_unlock_mutex_for_object (java_objectheader *object)
1114 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1116 mutexHashEntry *entry;
1118 hashValue = MUTEX_HASH_VALUE(object);
1119 entry = &mutexHashTable[hashValue];
1121 if (entry->object == object) {
1122 internal_unlock_mutex(&entry->mutex);
1125 while (entry->next != 0 && entry->next->object != object)
1126 entry = entry->next;
1128 assert(entry->next != 0);
1130 internal_unlock_mutex(&entry->next->mutex);
1132 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1133 mutexHashEntry *unlinked = entry->next;
1135 entry->next = unlinked->next;
1136 unlinked->next = firstFreeOverflowEntry;
1137 firstFreeOverflowEntry = unlinked;
1144 void builtin_monitorenter(java_objectheader *o)
1146 #if defined(USE_THREADS)
1147 #if !defined(NATIVE_THREADS)
1152 hashValue = MUTEX_HASH_VALUE(o);
1153 if (mutexHashTable[hashValue].object == o
1154 && mutexHashTable[hashValue].mutex.holder == currentThread)
1155 ++mutexHashTable[hashValue].mutex.count;
1157 internal_lock_mutex_for_object(o);
1161 monitorEnter((threadobject *) THREADOBJECT, o);
1168 * Locks the class object - needed for static synchronized methods.
1169 * The use_class_as_object call is needed in order to circumvent a
1170 * possible deadlock with builtin_monitorenter called by another
1171 * thread calling use_class_as_object.
1173 void builtin_staticmonitorenter(classinfo *c)
1175 use_class_as_object(c);
1176 builtin_monitorenter(&c->header);
1180 void *builtin_monitorexit(java_objectheader *o)
1182 #if defined(USE_THREADS)
1183 #if !defined(NATIVE_THREADS)
1188 hashValue = MUTEX_HASH_VALUE(o);
1189 if (mutexHashTable[hashValue].object == o) {
1190 if (mutexHashTable[hashValue].mutex.count == 1
1191 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1192 internal_unlock_mutex_for_object(o);
1194 --mutexHashTable[hashValue].mutex.count;
1197 internal_unlock_mutex_for_object(o);
1202 monitorExit((threadobject *) THREADOBJECT, o);
1209 /*****************************************************************************
1210 MISCELLANEOUS HELPER FUNCTIONS
1211 *****************************************************************************/
1215 /*********** Functions for integer divisions *****************************
1217 On some systems (eg. DEC ALPHA), integer division is not supported by the
1218 CPU. These helper functions implement the missing functionality.
1220 ******************************************************************************/
1222 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1223 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1226 /************** Functions for long arithmetics *******************************
1228 On systems where 64 bit Integers are not supported by the CPU, these
1229 functions are needed.
1231 ******************************************************************************/
1234 s8 builtin_ladd(s8 a, s8 b)
1239 return builtin_i2l(0);
1243 s8 builtin_lsub(s8 a, s8 b)
1248 return builtin_i2l(0);
1252 s8 builtin_lmul(s8 a, s8 b)
1257 return builtin_i2l(0);
1261 s8 builtin_ldiv(s8 a, s8 b)
1266 return builtin_i2l(0);
1270 s8 builtin_lrem(s8 a, s8 b)
1275 return builtin_i2l(0);
1279 s8 builtin_lshl(s8 a, s4 b)
1282 return a << (b & 63);
1284 return builtin_i2l(0);
1288 s8 builtin_lshr(s8 a, s4 b)
1291 return a >> (b & 63);
1293 return builtin_i2l(0);
1297 s8 builtin_lushr(s8 a, s4 b)
1300 return ((u8) a) >> (b & 63);
1302 return builtin_i2l(0);
1306 s8 builtin_land(s8 a, s8 b)
1311 return builtin_i2l(0);
1315 s8 builtin_lor(s8 a, s8 b)
1320 return builtin_i2l(0);
1324 s8 builtin_lxor(s8 a, s8 b)
1329 return builtin_i2l(0);
1333 s8 builtin_lneg(s8 a)
1338 return builtin_i2l(0);
1342 s4 builtin_lcmp(s8 a, s8 b)
1345 if (a < b) return -1;
1346 if (a > b) return 1;
1357 /*********** Functions for floating point operations *************************/
1359 float builtin_fadd(float a, float b)
1361 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1362 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1373 if (copysignf(1.0, a) == copysignf(1.0, b))
1376 return intBitsToFloat(FLT_NAN);
1382 float builtin_fsub(float a, float b)
1384 return builtin_fadd(a, builtin_fneg(b));
1388 float builtin_fmul(float a, float b)
1390 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1391 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1393 if (finitef(b)) return a * b;
1395 if (a == 0) return intBitsToFloat(FLT_NAN);
1396 else return copysignf(b, copysignf(1.0, b)*a);
1401 if (b == 0) return intBitsToFloat(FLT_NAN);
1402 else return copysignf(a, copysignf(1.0, a)*b);
1405 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1411 float builtin_fdiv(float a, float b)
1413 if (finitef(a) && finitef(b)) {
1418 return intBitsToFloat(FLT_POSINF);
1420 return intBitsToFloat(FLT_NEGINF);
1423 return intBitsToFloat(FLT_NAN);
1427 float builtin_frem(float a, float b)
1433 float builtin_fneg(float a)
1435 if (isnanf(a)) return a;
1437 if (finitef(a)) return -a;
1438 else return copysignf(a, -copysignf(1.0, a));
1443 s4 builtin_fcmpl(float a, float b)
1445 if (isnanf(a)) return -1;
1446 if (isnanf(b)) return -1;
1447 if (!finitef(a) || !finitef(b)) {
1448 a = finitef(a) ? 0 : copysignf(1.0, a);
1449 b = finitef(b) ? 0 : copysignf(1.0, b);
1451 if (a > b) return 1;
1452 if (a == b) return 0;
1457 s4 builtin_fcmpg(float a, float b)
1459 if (isnanf(a)) return 1;
1460 if (isnanf(b)) return 1;
1461 if (!finitef(a) || !finitef(b)) {
1462 a = finitef(a) ? 0 : copysignf(1.0, a);
1463 b = finitef(b) ? 0 : copysignf(1.0, b);
1465 if (a > b) return 1;
1466 if (a == b) return 0;
1472 /************************* Functions for doubles ****************************/
1474 double builtin_dadd(double a, double b)
1476 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1477 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1479 if (finite(b)) return a + b;
1483 if (finite(b)) return a;
1485 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1486 else return longBitsToDouble(DBL_NAN);
1492 double builtin_dsub(double a, double b)
1494 return builtin_dadd(a, builtin_dneg(b));
1498 double builtin_dmul(double a, double b)
1500 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1501 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1503 if (finite(b)) return a * b;
1505 if (a == 0) return longBitsToDouble(DBL_NAN);
1506 else return copysign(b, copysign(1.0, b) * a);
1511 if (b == 0) return longBitsToDouble(DBL_NAN);
1512 else return copysign(a, copysign(1.0, a) * b);
1515 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1521 double builtin_ddiv(double a, double b)
1529 return longBitsToDouble(DBL_NAN);
1531 return copysign(0.0, b);
1537 return longBitsToDouble(DBL_POSINF);
1539 return longBitsToDouble(DBL_NEGINF);
1542 return longBitsToDouble(DBL_NAN);
1545 /* if (finite(a) && finite(b)) { */
1550 /* return longBitsToDouble(DBL_POSINF); */
1551 /* else if (a < 0) */
1552 /* return longBitsToDouble(DBL_NEGINF); */
1556 /* keep compiler happy */
1561 double builtin_drem(double a, double b)
1567 double builtin_dneg(double a)
1569 if (isnan(a)) return a;
1571 if (finite(a)) return -a;
1572 else return copysign(a, -copysign(1.0, a));
1577 s4 builtin_dcmpl(double a, double b)
1579 if (isnan(a)) return -1;
1580 if (isnan(b)) return -1;
1581 if (!finite(a) || !finite(b)) {
1582 a = finite(a) ? 0 : copysign(1.0, a);
1583 b = finite(b) ? 0 : copysign(1.0, b);
1585 if (a > b) return 1;
1586 if (a == b) return 0;
1591 s4 builtin_dcmpg(double a, double b)
1593 if (isnan(a)) return 1;
1594 if (isnan(b)) return 1;
1595 if (!finite(a) || !finite(b)) {
1596 a = finite(a) ? 0 : copysign(1.0, a);
1597 b = finite(b) ? 0 : copysign(1.0, b);
1599 if (a > b) return 1;
1600 if (a == b) return 0;
1605 /*********************** Conversion operations ****************************/
1607 s8 builtin_i2l(s4 i)
1620 float builtin_i2f(s4 a)
1622 float f = (float) a;
1627 double builtin_i2d(s4 a)
1629 double d = (double) a;
1634 s4 builtin_l2i(s8 l)
1644 float builtin_l2f(s8 a)
1647 float f = (float) a;
1655 double builtin_l2d(s8 a)
1658 double d = (double) a;
1666 s4 builtin_f2i(float a)
1669 return builtin_d2i((double) a);
1678 if (a < (-2147483648))
1679 return (-2147483648);
1682 f = copysignf((float) 1.0, a);
1685 return (-2147483648); */
1689 s8 builtin_f2l(float a)
1692 return builtin_d2l((double) a);
1697 if (a > 9223372036854775807L)
1698 return 9223372036854775807L;
1699 if (a < (-9223372036854775808L))
1700 return (-9223372036854775808L);
1705 f = copysignf((float) 1.0, a);
1707 return 9223372036854775807L;
1708 return (-9223372036854775808L); */
1712 double builtin_f2d(float a)
1714 if (finitef(a)) return (double) a;
1717 return longBitsToDouble(DBL_NAN);
1719 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1724 s4 builtin_d2i(double a)
1729 if (a >= 2147483647)
1731 if (a <= (-2147483647-1))
1732 return (-2147483647-1);
1737 d = copysign(1.0, a);
1740 return (-2147483647-1);
1744 s8 builtin_d2l(double a)
1749 if (a >= 9223372036854775807LL)
1750 return 9223372036854775807LL;
1751 if (a <= (-9223372036854775807LL-1))
1752 return (-9223372036854775807LL-1);
1757 d = copysign(1.0, a);
1759 return 9223372036854775807LL;
1760 return (-9223372036854775807LL-1);
1764 float builtin_d2f(double a)
1770 return intBitsToFloat(FLT_NAN);
1772 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1777 /* used to convert FLT_xxx defines into float values */
1779 inline float intBitsToFloat(s4 i)
1788 /* used to convert DBL_xxx defines into double values */
1790 inline float longBitsToDouble(s8 l)
1799 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1801 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1807 panic("Internal error: builtin_dummy called (native function is missing)");
1808 return 0; /* for the compiler */
1812 /* builtin_asm_get_exceptionptrptr *********************************************
1814 this is a wrapper for calls from asmpart
1816 *******************************************************************************/
1818 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1819 java_objectheader **builtin_asm_get_exceptionptrptr()
1821 return builtin_get_exceptionptrptr();
1826 methodinfo *builtin_asm_get_threadrootmethod()
1828 return *threadrootmethod;
1832 inline void* builtin_asm_get_stackframeinfo()
1834 /*log_text("builtin_asm_get_stackframeinfo()");*/
1835 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1836 return &THREADINFO->_stackframeinfo;
1838 #if defined(__GNUC__)
1839 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1841 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1845 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1846 /* stacktraceelement *el;*/
1849 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1850 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1852 *el=MNEW(stacktraceelement,s+1); /*GC*/
1854 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1856 #if defined(__GNUC__)
1857 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1859 (*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 */
1864 * These are local overrides for various environment variables in Emacs.
1865 * Please do not remove this and leave it at the end of the file, where
1866 * Emacs will automagically detect them.
1867 * ---------------------------------------------------------------------
1870 * indent-tabs-mode: t