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 1296 2004-07-10 17:02:15Z stefan $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/logging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.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 *local_exceptionptr)
268 char logtext[MAXLOGTEXT];
269 sprintf(logtext, "Builtin exception thrown: ");
270 if (local_exceptionptr) {
271 java_lang_Throwable *t = (java_lang_Throwable *) local_exceptionptr;
273 utf_sprint_classname(logtext + strlen(logtext),
274 local_exceptionptr->vftbl->class->name);
276 if (t->detailMessage) {
277 sprintf(logtext + strlen(logtext), ": %s",
278 javastring_tochar(t->detailMessage));
282 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
287 *exceptionptr = local_exceptionptr;
289 return local_exceptionptr;
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);
489 /********************** Function: builtin_newarray **************************
491 Creates an array with the given vftbl on the heap.
493 Return value: pointer to the array or NULL if no memory is available
495 CAUTION: The given vftbl must be the vftbl of the *array* class,
496 not of the element class.
498 *****************************************************************************/
500 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
503 arraydescriptor *desc;
508 desc = arrayvftbl->arraydesc;
509 dataoffset = desc->dataoffset;
510 componentsize = desc->componentsize;
514 new_exception(string_java_lang_NegativeArraySizeException);
518 #ifdef SIZE_FROM_CLASSINFO
519 actualsize = align_size(dataoffset + size * componentsize);
520 actualsize = dataoffset + size * componentsize;
523 if (((u4) actualsize) < ((u4) size)) { /* overflow */
524 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
528 a = heap_allocate(actualsize,
529 (desc->arraytype == ARRAYTYPE_OBJECT),
535 memset(a, 0, actualsize);
537 a->objheader.vftbl = arrayvftbl;
539 #ifdef SIZE_FROM_CLASSINFO
540 a->alignedsize = actualsize;
547 /********************** Function: builtin_anewarray *************************
549 Creates an array of references to the given class type on the heap.
551 Return value: pointer to the array or NULL if no memory is available
553 XXX This function does not do The Right Thing, because it uses a
554 classinfo pointer at runtime. builtin_newarray should be used
557 *****************************************************************************/
559 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
561 /* is class loaded */
562 if (!component->loaded)
563 if (!class_load(component))
566 /* is class linked */
567 if (!component->linked)
568 if (!class_link(component))
571 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
575 /******************** Function: builtin_newarray_int ***********************
577 Creates an array of 32 bit Integers on the heap.
579 Return value: pointer to the array or NULL if no memory is available
581 *****************************************************************************/
583 java_intarray *builtin_newarray_int(s4 size)
585 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
589 /******************** Function: builtin_newarray_long ***********************
591 Creates an array of 64 bit Integers on the heap.
593 Return value: pointer to the array or NULL if no memory is available
595 *****************************************************************************/
597 java_longarray *builtin_newarray_long(s4 size)
599 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
603 /******************** function: builtin_newarray_float ***********************
605 Creates an array of 32 bit IEEE floats on the heap.
607 Return value: pointer to the array or NULL if no memory is available
609 *****************************************************************************/
611 java_floatarray *builtin_newarray_float(s4 size)
613 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
617 /******************** function: builtin_newarray_double ***********************
619 Creates an array of 64 bit IEEE floats on the heap.
621 Return value: pointer to the array or NULL if no memory is available
623 *****************************************************************************/
625 java_doublearray *builtin_newarray_double(s4 size)
627 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
631 /******************** function: builtin_newarray_byte ***********************
633 Creates an array of 8 bit Integers on the heap.
635 Return value: pointer to the array or NULL if no memory is available
637 *****************************************************************************/
639 java_bytearray *builtin_newarray_byte(s4 size)
641 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
645 /******************** function: builtin_newarray_char ************************
647 Creates an array of characters on the heap.
649 Return value: pointer to the array or NULL if no memory is available
651 *****************************************************************************/
653 java_chararray *builtin_newarray_char(s4 size)
655 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
659 /******************** function: builtin_newarray_short ***********************
661 Creates an array of 16 bit Integers on the heap.
663 Return value: pointer to the array or NULL if no memory is available
665 *****************************************************************************/
667 java_shortarray *builtin_newarray_short(s4 size)
669 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
673 /******************** function: builtin_newarray_boolean ************************
675 Creates an array of bytes on the heap. The array is designated as an array
676 of booleans (important for casts)
678 Return value: pointer to the array or NULL if no memory is available
680 *****************************************************************************/
682 java_booleanarray *builtin_newarray_boolean(s4 size)
684 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
688 /**************** function: builtin_nmultianewarray ***************************
690 Creates a multi-dimensional array on the heap. The dimensions are passed in
694 n............number of dimensions to create
695 arrayvftbl...vftbl of the array class
696 dims.........array containing the size of each dimension to create
698 Return value: pointer to the array or NULL if no memory is available
700 ******************************************************************************/
702 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
703 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
707 vftbl_t *componentvftbl;
709 /* utf_display(arrayclass->name); */
711 /* class_load(arrayclass); */
712 /* class_link(arrayclass); */
714 /* create this dimension */
716 a = builtin_newarray(size, arrayvftbl);
717 /* a = builtin_newarray(size, arrayclass->vftbl); */
722 /* if this is the last dimension return */
726 /* get the vftbl of the components to create */
727 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
728 /* component = arrayclass->vftbl->arraydesc; */
730 /* The verifier guarantees this. */
731 /* if (!componentvftbl) */
732 /* panic ("multianewarray with too many dimensions"); */
734 /* create the component arrays */
735 for (i = 0; i < size; i++) {
736 java_arrayheader *ea =
737 builtin_nmultianewarray(n, componentvftbl, dims + 1);
742 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
749 /*****************************************************************************
752 Various functions for printing a message at method entry or exit (for
755 *****************************************************************************/
759 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
769 log_text("WARNING: unmatched methodindent--");
771 if (verbose || runverbose || verboseexception) {
773 printf("Exception ");
774 utf_display_classname(_exceptionptr->vftbl->class->name);
777 printf("Some Throwable");
779 printf(" thrown in ");
782 utf_display_classname(method->class->name);
784 utf_display(method->name);
785 if (method->flags & ACC_SYNCHRONIZED)
789 if (method->flags & ACC_NATIVE) {
791 printf(")(%p) at position %p\n", method->entrypoint, pos);
793 printf(")(%p) at position %p (",method->entrypoint,pos);
794 if (method->class->sourcefile==NULL)
795 printf("<NO CLASSFILE INFORMATION>");
797 utf_display(method->class->sourcefile);
798 printf(":%d)\n",line);
802 printf("call_java_method\n");
806 return _exceptionptr;
810 #ifdef TRACE_ARGS_NUM
811 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
812 #if TRACE_ARGS_NUM > 6
818 char logtext[MAXLOGTEXT];
819 for (i = 0; i < methodindent; i++)
822 sprintf(logtext + methodindent, "called: ");
823 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
824 sprintf(logtext + strlen(logtext), ".");
825 utf_sprint(logtext + strlen(logtext), method->name);
826 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
828 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
829 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
830 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
831 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
832 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
833 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
834 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
835 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
836 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
837 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
838 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
841 sprintf(logtext + strlen(logtext), "(");
843 switch (method->paramcount) {
847 #if defined(__I386__) || defined(__POWERPC__)
849 sprintf(logtext+strlen(logtext), "%llx", a0);
853 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
857 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
861 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
866 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
871 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
872 a0, a1, a2, a3, a4, a5);
875 #if TRACE_ARGS_NUM > 6
877 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
878 a0, a1, a2, a3, a4, a5, a6);
882 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
883 a0, a1, a2, a3, a4, a5, a6, a7);
887 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
888 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
892 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
893 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
898 sprintf(logtext+strlen(logtext), "%lx", a0);
902 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
906 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
910 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
915 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
920 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
921 a0, a1, a2, a3, a4, a5);
924 #if TRACE_ARGS_NUM > 6
926 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
927 a0, a1, a2, a3, a4, a5, a6);
931 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
932 a0, a1, a2, a3, a4, a5, a6, a7);
936 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
937 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
941 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
942 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
948 sprintf(logtext + strlen(logtext), ")");
956 void builtin_displaymethodstart(methodinfo *method)
958 char logtext[MAXLOGTEXT];
959 sprintf(logtext, " ");
960 sprintf(logtext + methodindent, "called: ");
961 utf_sprint(logtext + strlen(logtext), method->class->name);
962 sprintf(logtext + strlen(logtext), ".");
963 utf_sprint(logtext + strlen(logtext), method->name);
964 utf_sprint(logtext + strlen(logtext), method->descriptor);
966 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
967 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
968 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
969 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
970 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
971 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
972 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
973 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
974 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
975 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
976 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
983 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
986 char logtext[MAXLOGTEXT];
987 for (i = 0; i < methodindent; i++)
992 log_text("WARNING: unmatched methodindent--");
994 sprintf(logtext + methodindent, "finished: ");
995 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
996 sprintf(logtext + strlen(logtext), ".");
997 utf_sprint(logtext + strlen(logtext), method->name);
998 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
1000 switch (method->returntype) {
1002 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1006 #if defined(__I386__) || defined(__POWERPC__)
1007 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1009 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1014 #if defined(__I386__) || defined(__POWERPC__)
1015 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1017 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1022 sprintf(logtext + strlen(logtext), "->%g", f);
1026 sprintf(logtext + strlen(logtext), "->%g", d);
1033 /****************************************************************************
1034 SYNCHRONIZATION FUNCTIONS
1035 *****************************************************************************/
1038 * Lock the mutex of an object.
1040 void internal_lock_mutex_for_object(java_objectheader *object)
1042 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1043 mutexHashEntry *entry;
1046 assert(object != 0);
1048 hashValue = MUTEX_HASH_VALUE(object);
1049 entry = &mutexHashTable[hashValue];
1051 if (entry->object != 0) {
1052 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1054 entry->mutex.holder = 0;
1055 entry->mutex.count = 0;
1056 entry->mutex.muxWaiters = 0;
1059 while (entry->next != 0 && entry->object != object)
1060 entry = entry->next;
1062 if (entry->object != object) {
1063 entry->next = firstFreeOverflowEntry;
1064 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1066 entry = entry->next;
1069 assert(entry->conditionCount == 0);
1074 entry->mutex.holder = 0;
1075 entry->mutex.count = 0;
1076 entry->mutex.muxWaiters = 0;
1079 if (entry->object == 0)
1080 entry->object = object;
1082 internal_lock_mutex(&entry->mutex);
1088 * Unlocks the mutex of an object.
1090 void internal_unlock_mutex_for_object (java_objectheader *object)
1092 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1094 mutexHashEntry *entry;
1096 hashValue = MUTEX_HASH_VALUE(object);
1097 entry = &mutexHashTable[hashValue];
1099 if (entry->object == object) {
1100 internal_unlock_mutex(&entry->mutex);
1103 while (entry->next != 0 && entry->next->object != object)
1104 entry = entry->next;
1106 assert(entry->next != 0);
1108 internal_unlock_mutex(&entry->next->mutex);
1110 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1111 mutexHashEntry *unlinked = entry->next;
1113 entry->next = unlinked->next;
1114 unlinked->next = firstFreeOverflowEntry;
1115 firstFreeOverflowEntry = unlinked;
1122 void builtin_monitorenter(java_objectheader *o)
1124 #if defined(USE_THREADS)
1125 #if !defined(NATIVE_THREADS)
1130 hashValue = MUTEX_HASH_VALUE(o);
1131 if (mutexHashTable[hashValue].object == o
1132 && mutexHashTable[hashValue].mutex.holder == currentThread)
1133 ++mutexHashTable[hashValue].mutex.count;
1135 internal_lock_mutex_for_object(o);
1139 monitorEnter((threadobject *) THREADOBJECT, o);
1145 * Locks the class object - needed for static synchronized methods.
1146 * The use_class_as_object call is needed in order to circumvent a
1147 * possible deadlock with builtin_monitorenter called by another
1148 * thread calling use_class_as_object.
1150 void builtin_staticmonitorenter(classinfo *c)
1152 use_class_as_object(c);
1153 builtin_monitorenter(&c->header);
1157 void builtin_monitorexit(java_objectheader *o)
1159 #if defined(USE_THREADS)
1160 #if !defined(NATIVE_THREADS)
1165 hashValue = MUTEX_HASH_VALUE(o);
1166 if (mutexHashTable[hashValue].object == o) {
1167 if (mutexHashTable[hashValue].mutex.count == 1
1168 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1169 internal_unlock_mutex_for_object(o);
1171 --mutexHashTable[hashValue].mutex.count;
1174 internal_unlock_mutex_for_object(o);
1178 monitorExit((threadobject *) THREADOBJECT, o);
1184 /*****************************************************************************
1185 MISCELLANEOUS HELPER FUNCTIONS
1186 *****************************************************************************/
1190 /*********** Functions for integer divisions *****************************
1192 On some systems (eg. DEC ALPHA), integer division is not supported by the
1193 CPU. These helper functions implement the missing functionality.
1195 ******************************************************************************/
1197 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1198 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1201 /************** Functions for long arithmetics *******************************
1203 On systems where 64 bit Integers are not supported by the CPU, these
1204 functions are needed.
1206 ******************************************************************************/
1209 s8 builtin_ladd(s8 a, s8 b)
1214 return builtin_i2l(0);
1218 s8 builtin_lsub(s8 a, s8 b)
1223 return builtin_i2l(0);
1227 s8 builtin_lmul(s8 a, s8 b)
1232 return builtin_i2l(0);
1236 s8 builtin_ldiv(s8 a, s8 b)
1241 return builtin_i2l(0);
1245 s8 builtin_lrem(s8 a, s8 b)
1250 return builtin_i2l(0);
1254 s8 builtin_lshl(s8 a, s4 b)
1257 return a << (b & 63);
1259 return builtin_i2l(0);
1263 s8 builtin_lshr(s8 a, s4 b)
1266 return a >> (b & 63);
1268 return builtin_i2l(0);
1272 s8 builtin_lushr(s8 a, s4 b)
1275 return ((u8) a) >> (b & 63);
1277 return builtin_i2l(0);
1281 s8 builtin_land(s8 a, s8 b)
1286 return builtin_i2l(0);
1290 s8 builtin_lor(s8 a, s8 b)
1295 return builtin_i2l(0);
1299 s8 builtin_lxor(s8 a, s8 b)
1304 return builtin_i2l(0);
1308 s8 builtin_lneg(s8 a)
1313 return builtin_i2l(0);
1317 s4 builtin_lcmp(s8 a, s8 b)
1320 if (a < b) return -1;
1321 if (a > b) return 1;
1332 /*********** Functions for floating point operations *************************/
1334 float builtin_fadd(float a, float b)
1336 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1337 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1348 if (copysignf(1.0, a) == copysignf(1.0, b))
1351 return intBitsToFloat(FLT_NAN);
1357 float builtin_fsub(float a, float b)
1359 return builtin_fadd(a, builtin_fneg(b));
1363 float builtin_fmul(float a, float b)
1365 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1366 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1368 if (finitef(b)) return a * b;
1370 if (a == 0) return intBitsToFloat(FLT_NAN);
1371 else return copysignf(b, copysignf(1.0, b)*a);
1376 if (b == 0) return intBitsToFloat(FLT_NAN);
1377 else return copysignf(a, copysignf(1.0, a)*b);
1380 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1386 float builtin_fdiv(float a, float b)
1388 if (finitef(a) && finitef(b)) {
1393 return intBitsToFloat(FLT_POSINF);
1395 return intBitsToFloat(FLT_NEGINF);
1398 return intBitsToFloat(FLT_NAN);
1402 float builtin_frem(float a, float b)
1408 float builtin_fneg(float a)
1410 if (isnanf(a)) return a;
1412 if (finitef(a)) return -a;
1413 else return copysignf(a, -copysignf(1.0, a));
1418 s4 builtin_fcmpl(float a, float b)
1420 if (isnanf(a)) return -1;
1421 if (isnanf(b)) return -1;
1422 if (!finitef(a) || !finitef(b)) {
1423 a = finitef(a) ? 0 : copysignf(1.0, a);
1424 b = finitef(b) ? 0 : copysignf(1.0, b);
1426 if (a > b) return 1;
1427 if (a == b) return 0;
1432 s4 builtin_fcmpg(float a, float b)
1434 if (isnanf(a)) return 1;
1435 if (isnanf(b)) return 1;
1436 if (!finitef(a) || !finitef(b)) {
1437 a = finitef(a) ? 0 : copysignf(1.0, a);
1438 b = finitef(b) ? 0 : copysignf(1.0, b);
1440 if (a > b) return 1;
1441 if (a == b) return 0;
1447 /************************* Functions for doubles ****************************/
1449 double builtin_dadd(double a, double b)
1451 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1452 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1454 if (finite(b)) return a + b;
1458 if (finite(b)) return a;
1460 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1461 else return longBitsToDouble(DBL_NAN);
1467 double builtin_dsub(double a, double b)
1469 return builtin_dadd(a, builtin_dneg(b));
1473 double builtin_dmul(double a, double b)
1475 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1476 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1478 if (finite(b)) return a * b;
1480 if (a == 0) return longBitsToDouble(DBL_NAN);
1481 else return copysign(b, copysign(1.0, b) * a);
1486 if (b == 0) return longBitsToDouble(DBL_NAN);
1487 else return copysign(a, copysign(1.0, a) * b);
1490 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1496 double builtin_ddiv(double a, double b)
1504 return longBitsToDouble(DBL_NAN);
1506 return copysign(0.0, b);
1512 return longBitsToDouble(DBL_POSINF);
1514 return longBitsToDouble(DBL_NEGINF);
1517 return longBitsToDouble(DBL_NAN);
1520 /* if (finite(a) && finite(b)) { */
1525 /* return longBitsToDouble(DBL_POSINF); */
1526 /* else if (a < 0) */
1527 /* return longBitsToDouble(DBL_NEGINF); */
1531 /* keep compiler happy */
1536 double builtin_drem(double a, double b)
1542 double builtin_dneg(double a)
1544 if (isnan(a)) return a;
1546 if (finite(a)) return -a;
1547 else return copysign(a, -copysign(1.0, a));
1552 s4 builtin_dcmpl(double a, double b)
1554 if (isnan(a)) return -1;
1555 if (isnan(b)) return -1;
1556 if (!finite(a) || !finite(b)) {
1557 a = finite(a) ? 0 : copysign(1.0, a);
1558 b = finite(b) ? 0 : copysign(1.0, b);
1560 if (a > b) return 1;
1561 if (a == b) return 0;
1566 s4 builtin_dcmpg(double a, double b)
1568 if (isnan(a)) return 1;
1569 if (isnan(b)) return 1;
1570 if (!finite(a) || !finite(b)) {
1571 a = finite(a) ? 0 : copysign(1.0, a);
1572 b = finite(b) ? 0 : copysign(1.0, b);
1574 if (a > b) return 1;
1575 if (a == b) return 0;
1580 /*********************** Conversion operations ****************************/
1582 s8 builtin_i2l(s4 i)
1595 float builtin_i2f(s4 a)
1597 float f = (float) a;
1602 double builtin_i2d(s4 a)
1604 double d = (double) a;
1609 s4 builtin_l2i(s8 l)
1619 float builtin_l2f(s8 a)
1622 float f = (float) a;
1630 double builtin_l2d(s8 a)
1633 double d = (double) a;
1641 s4 builtin_f2i(float a)
1644 return builtin_d2i((double) a);
1653 if (a < (-2147483648))
1654 return (-2147483648);
1657 f = copysignf((float) 1.0, a);
1660 return (-2147483648); */
1664 s8 builtin_f2l(float a)
1667 return builtin_d2l((double) a);
1672 if (a > 9223372036854775807L)
1673 return 9223372036854775807L;
1674 if (a < (-9223372036854775808L))
1675 return (-9223372036854775808L);
1680 f = copysignf((float) 1.0, a);
1682 return 9223372036854775807L;
1683 return (-9223372036854775808L); */
1687 double builtin_f2d(float a)
1689 if (finitef(a)) return (double) a;
1692 return longBitsToDouble(DBL_NAN);
1694 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1699 s4 builtin_d2i(double a)
1704 if (a >= 2147483647)
1706 if (a <= (-2147483647-1))
1707 return (-2147483647-1);
1712 d = copysign(1.0, a);
1715 return (-2147483647-1);
1719 s8 builtin_d2l(double a)
1724 if (a >= 9223372036854775807LL)
1725 return 9223372036854775807LL;
1726 if (a <= (-9223372036854775807LL-1))
1727 return (-9223372036854775807LL-1);
1732 d = copysign(1.0, a);
1734 return 9223372036854775807LL;
1735 return (-9223372036854775807LL-1);
1739 float builtin_d2f(double a)
1745 return intBitsToFloat(FLT_NAN);
1747 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1752 /* used to convert FLT_xxx defines into float values */
1754 inline float intBitsToFloat(s4 i)
1763 /* used to convert DBL_xxx defines into double values */
1765 inline float longBitsToDouble(s8 l)
1774 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1776 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1782 panic("Internal error: builtin_dummy called (native function is missing)");
1783 return 0; /* for the compiler */
1787 /* builtin_asm_get_exceptionptrptr *********************************************
1789 this is a wrapper for calls from asmpart
1791 *******************************************************************************/
1793 java_objectheader **builtin_asm_get_exceptionptrptr()
1795 return builtin_get_exceptionptrptr();
1799 methodinfo *builtin_asm_get_threadrootmethod()
1801 return *threadrootmethod;
1805 inline void* builtin_asm_get_stackframeinfo()
1807 /*log_text("builtin_asm_get_stackframeinfo()");*/
1808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1809 return &THREADINFO->_stackframeinfo;
1811 #if defined(__GNUC__)
1812 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1814 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1818 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1819 /* stacktraceelement *el;*/
1822 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1823 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1825 *el=MNEW(stacktraceelement,s+1); /*GC*/
1827 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1829 #if defined(__GNUC__)
1830 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1832 (*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 */
1837 * These are local overrides for various environment variables in Emacs.
1838 * Please do not remove this and leave it at the end of the file, where
1839 * Emacs will automagically detect them.
1840 * ---------------------------------------------------------------------
1843 * indent-tabs-mode: t