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 1219 2004-06-29 14:37:41Z twisti $
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 *sub,vftbl *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 *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 *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 *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;
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)
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 *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 *arrayvftbl, long *dims)
703 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
707 vftbl *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 void builtin_monitorexit(java_objectheader *o)
1147 #if defined(USE_THREADS)
1148 #if !defined(NATIVE_THREADS)
1153 hashValue = MUTEX_HASH_VALUE(o);
1154 if (mutexHashTable[hashValue].object == o) {
1155 if (mutexHashTable[hashValue].mutex.count == 1
1156 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1157 internal_unlock_mutex_for_object(o);
1159 --mutexHashTable[hashValue].mutex.count;
1162 internal_unlock_mutex_for_object(o);
1166 monitorExit((threadobject *) THREADOBJECT, o);
1172 /*****************************************************************************
1173 MISCELLANEOUS HELPER FUNCTIONS
1174 *****************************************************************************/
1178 /*********** Functions for integer divisions *****************************
1180 On some systems (eg. DEC ALPHA), integer division is not supported by the
1181 CPU. These helper functions implement the missing functionality.
1183 ******************************************************************************/
1185 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1186 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1189 /************** Functions for long arithmetics *******************************
1191 On systems where 64 bit Integers are not supported by the CPU, these
1192 functions are needed.
1194 ******************************************************************************/
1197 s8 builtin_ladd(s8 a, s8 b)
1202 return builtin_i2l(0);
1206 s8 builtin_lsub(s8 a, s8 b)
1211 return builtin_i2l(0);
1215 s8 builtin_lmul(s8 a, s8 b)
1220 return builtin_i2l(0);
1224 s8 builtin_ldiv(s8 a, s8 b)
1229 return builtin_i2l(0);
1233 s8 builtin_lrem(s8 a, s8 b)
1238 return builtin_i2l(0);
1242 s8 builtin_lshl(s8 a, s4 b)
1245 return a << (b & 63);
1247 return builtin_i2l(0);
1251 s8 builtin_lshr(s8 a, s4 b)
1254 return a >> (b & 63);
1256 return builtin_i2l(0);
1260 s8 builtin_lushr(s8 a, s4 b)
1263 return ((u8) a) >> (b & 63);
1265 return builtin_i2l(0);
1269 s8 builtin_land(s8 a, s8 b)
1274 return builtin_i2l(0);
1278 s8 builtin_lor(s8 a, s8 b)
1283 return builtin_i2l(0);
1287 s8 builtin_lxor(s8 a, s8 b)
1292 return builtin_i2l(0);
1296 s8 builtin_lneg(s8 a)
1301 return builtin_i2l(0);
1305 s4 builtin_lcmp(s8 a, s8 b)
1308 if (a < b) return -1;
1309 if (a > b) return 1;
1320 /*********** Functions for floating point operations *************************/
1322 float builtin_fadd(float a, float b)
1324 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1325 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1336 if (copysignf(1.0, a) == copysignf(1.0, b))
1339 return intBitsToFloat(FLT_NAN);
1345 float builtin_fsub(float a, float b)
1347 return builtin_fadd(a, builtin_fneg(b));
1351 float builtin_fmul(float a, float b)
1353 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1354 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1356 if (finitef(b)) return a * b;
1358 if (a == 0) return intBitsToFloat(FLT_NAN);
1359 else return copysignf(b, copysignf(1.0, b)*a);
1364 if (b == 0) return intBitsToFloat(FLT_NAN);
1365 else return copysignf(a, copysignf(1.0, a)*b);
1368 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1374 float builtin_fdiv(float a, float b)
1376 if (finitef(a) && finitef(b)) {
1381 return intBitsToFloat(FLT_POSINF);
1383 return intBitsToFloat(FLT_NEGINF);
1386 return intBitsToFloat(FLT_NAN);
1390 float builtin_frem(float a, float b)
1396 float builtin_fneg(float a)
1398 if (isnanf(a)) return a;
1400 if (finitef(a)) return -a;
1401 else return copysignf(a, -copysignf(1.0, a));
1406 s4 builtin_fcmpl(float a, float b)
1408 if (isnanf(a)) return -1;
1409 if (isnanf(b)) return -1;
1410 if (!finitef(a) || !finitef(b)) {
1411 a = finitef(a) ? 0 : copysignf(1.0, a);
1412 b = finitef(b) ? 0 : copysignf(1.0, b);
1414 if (a > b) return 1;
1415 if (a == b) return 0;
1420 s4 builtin_fcmpg(float a, float b)
1422 if (isnanf(a)) return 1;
1423 if (isnanf(b)) return 1;
1424 if (!finitef(a) || !finitef(b)) {
1425 a = finitef(a) ? 0 : copysignf(1.0, a);
1426 b = finitef(b) ? 0 : copysignf(1.0, b);
1428 if (a > b) return 1;
1429 if (a == b) return 0;
1435 /************************* Functions for doubles ****************************/
1437 double builtin_dadd(double a, double b)
1439 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1440 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1442 if (finite(b)) return a + b;
1446 if (finite(b)) return a;
1448 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1449 else return longBitsToDouble(DBL_NAN);
1455 double builtin_dsub(double a, double b)
1457 return builtin_dadd(a, builtin_dneg(b));
1461 double builtin_dmul(double a, double b)
1463 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1464 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1466 if (finite(b)) return a * b;
1468 if (a == 0) return longBitsToDouble(DBL_NAN);
1469 else return copysign(b, copysign(1.0, b) * a);
1474 if (b == 0) return longBitsToDouble(DBL_NAN);
1475 else return copysign(a, copysign(1.0, a) * b);
1478 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1484 double builtin_ddiv(double a, double b)
1492 return longBitsToDouble(DBL_NAN);
1494 return copysign(0.0, b);
1500 return longBitsToDouble(DBL_POSINF);
1502 return longBitsToDouble(DBL_NEGINF);
1505 return longBitsToDouble(DBL_NAN);
1508 /* if (finite(a) && finite(b)) { */
1513 /* return longBitsToDouble(DBL_POSINF); */
1514 /* else if (a < 0) */
1515 /* return longBitsToDouble(DBL_NEGINF); */
1519 /* keep compiler happy */
1524 double builtin_drem(double a, double b)
1530 double builtin_dneg(double a)
1532 if (isnan(a)) return a;
1534 if (finite(a)) return -a;
1535 else return copysign(a, -copysign(1.0, a));
1540 s4 builtin_dcmpl(double a, double b)
1542 if (isnan(a)) return -1;
1543 if (isnan(b)) return -1;
1544 if (!finite(a) || !finite(b)) {
1545 a = finite(a) ? 0 : copysign(1.0, a);
1546 b = finite(b) ? 0 : copysign(1.0, b);
1548 if (a > b) return 1;
1549 if (a == b) return 0;
1554 s4 builtin_dcmpg(double a, double b)
1556 if (isnan(a)) return 1;
1557 if (isnan(b)) return 1;
1558 if (!finite(a) || !finite(b)) {
1559 a = finite(a) ? 0 : copysign(1.0, a);
1560 b = finite(b) ? 0 : copysign(1.0, b);
1562 if (a > b) return 1;
1563 if (a == b) return 0;
1568 /*********************** Conversion operations ****************************/
1570 s8 builtin_i2l(s4 i)
1583 float builtin_i2f(s4 a)
1585 float f = (float) a;
1590 double builtin_i2d(s4 a)
1592 double d = (double) a;
1597 s4 builtin_l2i(s8 l)
1607 float builtin_l2f(s8 a)
1610 float f = (float) a;
1618 double builtin_l2d(s8 a)
1621 double d = (double) a;
1629 s4 builtin_f2i(float a)
1632 return builtin_d2i((double) a);
1641 if (a < (-2147483648))
1642 return (-2147483648);
1645 f = copysignf((float) 1.0, a);
1648 return (-2147483648); */
1652 s8 builtin_f2l(float a)
1655 return builtin_d2l((double) a);
1660 if (a > 9223372036854775807L)
1661 return 9223372036854775807L;
1662 if (a < (-9223372036854775808L))
1663 return (-9223372036854775808L);
1668 f = copysignf((float) 1.0, a);
1670 return 9223372036854775807L;
1671 return (-9223372036854775808L); */
1675 double builtin_f2d(float a)
1677 if (finitef(a)) return (double) a;
1680 return longBitsToDouble(DBL_NAN);
1682 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1687 s4 builtin_d2i(double a)
1692 if (a >= 2147483647)
1694 if (a <= (-2147483647-1))
1695 return (-2147483647-1);
1700 d = copysign(1.0, a);
1703 return (-2147483647-1);
1707 s8 builtin_d2l(double a)
1712 if (a >= 9223372036854775807LL)
1713 return 9223372036854775807LL;
1714 if (a <= (-9223372036854775807LL-1))
1715 return (-9223372036854775807LL-1);
1720 d = copysign(1.0, a);
1722 return 9223372036854775807LL;
1723 return (-9223372036854775807LL-1);
1727 float builtin_d2f(double a)
1733 return intBitsToFloat(FLT_NAN);
1735 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1740 /* used to convert FLT_xxx defines into float values */
1742 inline float intBitsToFloat(s4 i)
1751 /* used to convert DBL_xxx defines into double values */
1753 inline float longBitsToDouble(s8 l)
1762 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1764 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1770 panic("Internal error: builtin_dummy called (native function is missing)");
1771 return 0; /* for the compiler */
1775 /* builtin_asm_get_exceptionptrptr *********************************************
1777 this is a wrapper for calls from asmpart
1779 *******************************************************************************/
1781 java_objectheader **builtin_asm_get_exceptionptrptr()
1783 return builtin_get_exceptionptrptr();
1787 methodinfo *builtin_asm_get_threadrootmethod()
1789 return *threadrootmethod;
1793 inline void* builtin_asm_get_stackframeinfo()
1795 /*log_text("builtin_asm_get_stackframeinfo()");*/
1796 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1797 return &THREADINFO->_stackframeinfo;
1799 #if defined(__GNUC__)
1800 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1802 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1806 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1807 /* stacktraceelement *el;*/
1810 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1811 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1813 *el=MNEW(stacktraceelement,s+1); /*GC*/
1815 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1817 #if defined(__GNUC__)
1818 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1820 (*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 */
1825 * These are local overrides for various environment variables in Emacs.
1826 * Please do not remove this and leave it at the end of the file, where
1827 * Emacs will automagically detect them.
1828 * ---------------------------------------------------------------------
1831 * indent-tabs-mode: t