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 991 2004-03-29 11:22:34Z stefan $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.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)
85 if (super->flags & ACC_INTERFACE)
86 return (sub->vftbl->interfacetablelength > super->index) &&
87 (sub->vftbl->interfacetable[-super->index] != NULL);
100 for (tmp=sub;tmp!=0;tmp=tmp->super) {
102 utf_display(tmp->name);
106 for (tmp=super;tmp!=0;tmp=tmp->super) {
108 utf_display(tmp->name);
113 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
114 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
115 super->vftbl->diffval); */
117 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
121 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
122 (unsigned) (super->vftbl->diffval);
124 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
131 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
136 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
140 if ((base = super->baseval) <= 0)
141 /* super is an interface */
142 res = (sub->interfacetablelength > -base) &&
143 (sub->interfacetable[base] != NULL);
145 res = (unsigned) (sub->baseval - base)
146 <= (unsigned) (super->diffval);
148 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
156 /****************** function: builtin_instanceof *****************************
158 Checks if an object is an instance of some given class (or subclass of
159 that class). If class is an interface, checks if the interface is
161 Return value: 1 ... obj is an instance of class or implements the interface
162 0 ... otherwise or if obj == NULL
164 *****************************************************************************/
166 /* XXX should use vftbl */
167 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
170 log_text ("builtin_instanceof called");
173 return builtin_isanysubclass (obj->vftbl->class, class);
178 /**************** function: builtin_checkcast *******************************
180 The same as builtin_instanceof except that 1 is returned when
183 ****************************************************************************/
185 /* XXX should use vftbl */
186 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
189 log_text("builtin_checkcast called");
194 if (builtin_isanysubclass(obj->vftbl->class, class))
198 printf("#### checkcast failed ");
199 utf_display(obj->vftbl->class->name);
201 utf_display(class->name);
209 /*********** internal function: builtin_descriptorscompatible ******************
211 Checks if two array type descriptors are assignment compatible
212 Return value: 1 ... target = desc is possible
215 ******************************************************************************/
217 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
219 if (desc==target) return 1;
220 if (desc->arraytype != target->arraytype) return 0;
221 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
223 /* {both arrays are arrays of references} */
224 if (desc->dimension == target->dimension) {
225 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
226 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
227 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
229 if (desc->dimension < target->dimension) return 0;
231 /* {desc has higher dimension than target} */
232 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
236 /******************** function: builtin_checkarraycast ***********************
238 Checks if an object is really a subtype of the requested array type.
239 The object has to be an array to begin with. For simple arrays (int, short,
240 double, etc.) the types have to match exactly.
241 For arrays of objects, the type of elements in the array has to be a
242 subtype (or the same type) of the requested element type. For arrays of
243 arrays (which in turn can again be arrays of arrays), the types at the
244 lowest level have to satisfy the corresponding sub class relation.
246 Return value: 1 ... cast is possible
249 ATTENTION: a cast with a NULL pointer is always possible.
251 *****************************************************************************/
253 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
255 arraydescriptor *desc;
258 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
260 return builtin_descriptorscompatible(desc, target->arraydesc);
264 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
267 return builtin_checkarraycast(obj, target);
271 /************************** exception functions *******************************
273 ******************************************************************************/
275 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
278 char logtext[MAXLOGTEXT];
279 sprintf(logtext, "Builtin exception thrown: ");
280 if (local_exceptionptr)
281 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
283 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
284 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
285 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
286 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
287 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
288 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
289 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
290 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
291 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
292 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
293 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
297 *exceptionptr = local_exceptionptr;
298 return local_exceptionptr;
301 void builtin_reset_exceptionptr()
303 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
304 THREADINFO->_exceptionptr = NULL;
306 panic("builtin_reset_exceptionptr should not be used in this configuration");
311 /******************* function: builtin_canstore *******************************
313 Checks, if an object can be stored in an array.
314 Return value: 1 ... possible
317 ******************************************************************************/
319 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
321 arraydescriptor *desc;
322 arraydescriptor *valuedesc;
323 vftbl *componentvftbl;
330 /* The following is guaranteed (by verifier checks):
332 * *) a->...vftbl->arraydesc != NULL
333 * *) a->...vftbl->arraydesc->componentvftbl != NULL
334 * *) o->vftbl is not an interface vftbl
337 desc = a->header.objheader.vftbl->arraydesc;
338 componentvftbl = desc->componentvftbl;
339 valuevftbl = o->vftbl;
341 if ((dim_m1 = desc->dimension - 1) == 0) {
344 /* {a is a one-dimensional array} */
345 /* {a is an array of references} */
347 if (valuevftbl == componentvftbl)
350 if ((base = componentvftbl->baseval) <= 0)
351 /* an array of interface references */
352 return (valuevftbl->interfacetablelength > -base &&
353 valuevftbl->interfacetable[base] != NULL);
355 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
359 res = (unsigned)(valuevftbl->baseval - base)
360 <= (unsigned)(componentvftbl->diffval);
362 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
368 /* {a has dimension > 1} */
369 /* {componentvftbl->arraydesc != NULL} */
371 /* check if o is an array */
372 if ((valuedesc = valuevftbl->arraydesc) == NULL)
374 /* {o is an array} */
376 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
380 /* This is an optimized version where a is guaranteed to be one-dimensional */
381 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
383 arraydescriptor *desc;
391 /* The following is guaranteed (by verifier checks):
393 * *) a->...vftbl->arraydesc != NULL
394 * *) a->...vftbl->arraydesc->elementvftbl != NULL
395 * *) a->...vftbl->arraydesc->dimension == 1
396 * *) o->vftbl is not an interface vftbl
399 desc = a->header.objheader.vftbl->arraydesc;
400 elementvftbl = desc->elementvftbl;
401 valuevftbl = o->vftbl;
403 /* {a is a one-dimensional array} */
405 if (valuevftbl == elementvftbl)
408 if ((base = elementvftbl->baseval) <= 0)
409 /* an array of interface references */
410 return (valuevftbl->interfacetablelength > -base &&
411 valuevftbl->interfacetable[base] != NULL);
413 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
417 res = (unsigned)(valuevftbl->baseval - base)
418 <= (unsigned)(elementvftbl->diffval);
420 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
428 /* This is an optimized version where a is guaranteed to be a
429 * one-dimensional array of a class type */
430 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
438 /* The following is guaranteed (by verifier checks):
440 * *) a->...vftbl->arraydesc != NULL
441 * *) a->...vftbl->arraydesc->elementvftbl != NULL
442 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
443 * *) a->...vftbl->arraydesc->dimension == 1
444 * *) o->vftbl is not an interface vftbl
447 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
448 valuevftbl = o->vftbl;
450 /* {a is a one-dimensional array} */
452 if (valuevftbl == elementvftbl)
455 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
459 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
460 <= (unsigned)(elementvftbl->diffval);
462 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
470 /******************** Function: builtin_new **********************************
472 Creates a new instance of class c on the heap.
473 Return value: pointer to the object or NULL if no memory is
476 *****************************************************************************/
479 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
481 java_objectheader *builtin_new(classinfo *c)
483 java_objectheader *o;
484 /*DEBUGING - NOT THREAD SAFE*/
485 /* static long depth=0;
487 printf("Entering builtin_new:depth(%ld)",depth);*/
489 if (!c->initialized) {
491 char logtext[MAXLOGTEXT];
492 sprintf(logtext, "Initialize class ");
493 utf_sprint(logtext + strlen(logtext), c->name);
494 sprintf(logtext + strlen(logtext), " (from builtin_new)");
500 #ifdef SIZE_FROM_CLASSINFO
501 c->alignedsize = align_size(c->instancesize);
502 o = heap_allocate(c->alignedsize, true, c->finalizer);
504 o = heap_allocate(c->instancesize, true, c->finalizer);
507 /*DEBUGING - NOT THREAD SAFE*/
508 /*printf("Leaving builtin_new: depth(%ld): NULL",depth);
513 memset(o, 0, c->instancesize);
517 /*DEBUGING - NOT THREAD SAFE*/
518 /* printf("Leaving builtin_new: depth(%ld): object",depth);
523 /********************** Function: builtin_newarray **************************
525 Creates an array with the given vftbl on the heap.
527 Return value: pointer to the array or NULL if no memory is available
529 CAUTION: The given vftbl must be the vftbl of the *array* class,
530 not of the element class.
532 *****************************************************************************/
534 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
537 arraydescriptor *desc = arrayvftbl->arraydesc;
538 s4 dataoffset = desc->dataoffset;
539 s4 componentsize = desc->componentsize;
543 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
546 #ifdef SIZE_FROM_CLASSINFO
547 actualsize = align_size(dataoffset + size * componentsize);
549 actualsize = dataoffset + size * componentsize;
552 if (((u4)actualsize)<((u4)size)) { /* overflow */
553 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
556 a = heap_allocate(actualsize,
557 (desc->arraytype == ARRAYTYPE_OBJECT),
561 memset(a, 0, actualsize);
564 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
566 a->objheader.vftbl = arrayvftbl;
568 #ifdef SIZE_FROM_CLASSINFO
569 a->alignedsize = actualsize;
576 /********************** Function: builtin_anewarray *************************
578 Creates an array of references to the given class type on the heap.
580 Return value: pointer to the array or NULL if no memory is available
582 XXX This function does not do The Right Thing, because it uses a
583 classinfo pointer at runtime. builtin_newarray should be used
586 *****************************************************************************/
588 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
591 printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
592 printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
593 utf_display(component->vftbl->class->name);
594 printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
595 utf_display(component->super->name);*/
596 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
600 /******************** Function: builtin_newarray_int ***********************
602 Creates an array of 32 bit Integers on the heap.
604 Return value: pointer to the array or NULL if no memory is available
606 *****************************************************************************/
608 java_intarray *builtin_newarray_int(s4 size)
610 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
614 /******************** Function: builtin_newarray_long ***********************
616 Creates an array of 64 bit Integers on the heap.
618 Return value: pointer to the array or NULL if no memory is available
620 *****************************************************************************/
622 java_longarray *builtin_newarray_long(s4 size)
624 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
628 /******************** function: builtin_newarray_float ***********************
630 Creates an array of 32 bit IEEE floats on the heap.
632 Return value: pointer to the array or NULL if no memory is available
634 *****************************************************************************/
636 java_floatarray *builtin_newarray_float(s4 size)
638 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
642 /******************** function: builtin_newarray_double ***********************
644 Creates an array of 64 bit IEEE floats on the heap.
646 Return value: pointer to the array or NULL if no memory is available
648 *****************************************************************************/
650 java_doublearray *builtin_newarray_double(s4 size)
652 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
656 /******************** function: builtin_newarray_byte ***********************
658 Creates an array of 8 bit Integers on the heap.
660 Return value: pointer to the array or NULL if no memory is available
662 *****************************************************************************/
664 java_bytearray *builtin_newarray_byte(s4 size)
666 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
670 /******************** function: builtin_newarray_char ************************
672 Creates an array of characters on the heap.
674 Return value: pointer to the array or NULL if no memory is available
676 *****************************************************************************/
678 java_chararray *builtin_newarray_char(s4 size)
680 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
684 /******************** function: builtin_newarray_short ***********************
686 Creates an array of 16 bit Integers on the heap.
688 Return value: pointer to the array or NULL if no memory is available
690 *****************************************************************************/
692 java_shortarray *builtin_newarray_short(s4 size)
694 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
698 /******************** function: builtin_newarray_boolean ************************
700 Creates an array of bytes on the heap. The array is designated as an array
701 of booleans (important for casts)
703 Return value: pointer to the array or NULL if no memory is available
705 *****************************************************************************/
707 java_booleanarray *builtin_newarray_boolean(s4 size)
709 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
713 /**************** function: builtin_nmultianewarray ***************************
715 Creates a multi-dimensional array on the heap. The dimensions are passed in
719 n............number of dimensions to create
720 arrayvftbl...vftbl of the array class
721 dims.........array containing the size of each dimension to create
723 Return value: pointer to the array or NULL if no memory is available
725 ******************************************************************************/
727 /* Helper functions */
729 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
733 vftbl *componentvftbl;
735 /* create this dimension */
736 size = (int) dims[0];
737 a = builtin_newarray(size,arrayvftbl);
740 /* if this is the last dimension return */
743 /* get the vftbl of the components to create */
744 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
746 /* The verifier guarantees this. */
747 /* if (!componentvftbl) */
748 /* panic ("multianewarray with too many dimensions"); */
750 /* create the component arrays */
751 for (i = 0; i < size; i++) {
752 java_arrayheader *ea =
753 builtin_nmultianewarray(n,componentvftbl,dims+1);
754 if (!ea) return NULL;
755 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
762 /*****************************************************************************
765 Various functions for printing a message at method entry or exit (for
768 *****************************************************************************/
772 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
773 methodinfo *method, int *pos,
781 log_text("WARNING: unmatched methodindent--");
783 if (verbose || runverbose || verboseexception) {
785 printf("Exception ");
786 utf_display(_exceptionptr->vftbl->class->name);
789 printf("Some Throwable");
791 printf("Error: <Nullpointer instead of exception>");
792 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
793 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
794 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
795 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
796 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
797 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
798 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
799 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
800 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
801 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
804 printf(" thrown in ");
807 utf_display_classname(method->class->name);
809 utf_display(method->name);
810 if (method->flags & ACC_SYNCHRONIZED)
814 if (method->flags & ACC_NATIVE) {
816 printf(")(%p) at position %p\n", method->entrypoint, pos);
818 printf(")(%p) at position %p (",method->entrypoint,pos);
819 if (method->class->sourcefile==NULL)
820 printf("<NO CLASSFILE INFORMATION>");
822 utf_display(method->class->sourcefile);
823 printf(":%d)\n",line);
827 printf("call_java_method\n");
831 return _exceptionptr;
835 #ifdef TRACE_ARGS_NUM
836 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
837 #if TRACE_ARGS_NUM > 6
843 char logtext[MAXLOGTEXT];
844 for (i = 0; i < methodindent; i++)
847 sprintf(logtext + methodindent, "called: ");
848 utf_sprint(logtext + strlen(logtext), method->class->name);
849 sprintf(logtext + strlen(logtext), ".");
850 utf_sprint(logtext + strlen(logtext), method->name);
851 utf_sprint(logtext + strlen(logtext), method->descriptor);
853 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
854 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
855 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
856 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
857 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
858 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
859 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
860 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
861 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
862 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
863 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
866 sprintf(logtext + strlen(logtext), "(");
868 switch (method->paramcount) {
872 #if defined(__I386__) || defined(__POWERPC__)
874 sprintf(logtext+strlen(logtext), "%llx", a0);
878 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
882 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
886 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
891 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
896 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
897 a0, a1, a2, a3, a4, a5);
900 #if TRACE_ARGS_NUM > 6
902 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
903 a0, a1, a2, a3, a4, a5, a6);
907 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
908 a0, a1, a2, a3, a4, a5, a6, a7);
912 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
913 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
917 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
918 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
923 sprintf(logtext+strlen(logtext), "%lx", a0);
927 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
931 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
935 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
940 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
945 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
946 a0, a1, a2, a3, a4, a5);
949 #if TRACE_ARGS_NUM > 6
951 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
952 a0, a1, a2, a3, a4, a5, a6);
956 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
957 a0, a1, a2, a3, a4, a5, a6, a7);
961 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
962 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
966 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
967 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
973 sprintf(logtext + strlen(logtext), ")");
981 void builtin_displaymethodstart(methodinfo *method)
983 char logtext[MAXLOGTEXT];
984 sprintf(logtext, " ");
985 sprintf(logtext + methodindent, "called: ");
986 utf_sprint(logtext + strlen(logtext), method->class->name);
987 sprintf(logtext + strlen(logtext), ".");
988 utf_sprint(logtext + strlen(logtext), method->name);
989 utf_sprint(logtext + strlen(logtext), method->descriptor);
991 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
992 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
993 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
994 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
995 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
996 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
997 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
998 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
999 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
1000 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
1001 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
1008 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1011 char logtext[MAXLOGTEXT];
1012 for (i = 0; i < methodindent; i++)
1017 log_text("WARNING: unmatched methodindent--");
1019 sprintf(logtext + methodindent, "finished: ");
1020 utf_sprint(logtext + strlen(logtext), method->class->name);
1021 sprintf(logtext + strlen(logtext), ".");
1022 utf_sprint(logtext + strlen(logtext), method->name);
1023 utf_sprint(logtext + strlen(logtext), method->descriptor);
1025 switch (method->returntype) {
1027 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1031 #if defined(__I386__) || defined(__POWERPC__)
1032 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1034 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1039 #if defined(__I386__) || defined(__POWERPC__)
1040 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1042 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1047 sprintf(logtext + strlen(logtext), "->%g", f);
1051 sprintf(logtext + strlen(logtext), "->%g", d);
1058 void builtin_displaymethodexception(methodinfo *method)
1061 char logtext[MAXLOGTEXT];
1062 for (i = 0; i < methodindent; i++)
1064 sprintf(logtext + methodindent, "exception abort: ");
1065 utf_sprint(logtext + strlen(logtext), method->class->name);
1066 sprintf(logtext + strlen(logtext), ".");
1067 utf_sprint(logtext + strlen(logtext), method->name);
1068 utf_sprint(logtext + strlen(logtext), method->descriptor);
1073 /****************************************************************************
1074 SYNCHRONIZATION FUNCTIONS
1075 *****************************************************************************/
1078 * Lock the mutex of an object.
1080 void internal_lock_mutex_for_object(java_objectheader *object)
1082 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1083 mutexHashEntry *entry;
1086 assert(object != 0);
1088 hashValue = MUTEX_HASH_VALUE(object);
1089 entry = &mutexHashTable[hashValue];
1091 if (entry->object != 0) {
1092 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1094 entry->mutex.holder = 0;
1095 entry->mutex.count = 0;
1096 entry->mutex.muxWaiters = 0;
1099 while (entry->next != 0 && entry->object != object)
1100 entry = entry->next;
1102 if (entry->object != object) {
1103 entry->next = firstFreeOverflowEntry;
1104 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1106 entry = entry->next;
1109 assert(entry->conditionCount == 0);
1114 entry->mutex.holder = 0;
1115 entry->mutex.count = 0;
1116 entry->mutex.muxWaiters = 0;
1119 if (entry->object == 0)
1120 entry->object = object;
1122 internal_lock_mutex(&entry->mutex);
1128 * Unlocks the mutex of an object.
1130 void internal_unlock_mutex_for_object (java_objectheader *object)
1132 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1134 mutexHashEntry *entry;
1136 hashValue = MUTEX_HASH_VALUE(object);
1137 entry = &mutexHashTable[hashValue];
1139 if (entry->object == object) {
1140 internal_unlock_mutex(&entry->mutex);
1143 while (entry->next != 0 && entry->next->object != object)
1144 entry = entry->next;
1146 assert(entry->next != 0);
1148 internal_unlock_mutex(&entry->next->mutex);
1150 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1151 mutexHashEntry *unlinked = entry->next;
1153 entry->next = unlinked->next;
1154 unlinked->next = firstFreeOverflowEntry;
1155 firstFreeOverflowEntry = unlinked;
1162 void builtin_monitorenter(java_objectheader *o)
1164 #if defined(USE_THREADS)
1165 #if !defined(NATIVE_THREADS)
1168 /*log_text("Monitor enter");*/
1170 assert(blockInts == 0);
1174 hashValue = MUTEX_HASH_VALUE(o);
1175 if (mutexHashTable[hashValue].object == o
1176 && mutexHashTable[hashValue].mutex.holder == currentThread)
1177 ++mutexHashTable[hashValue].mutex.count;
1179 internal_lock_mutex_for_object(o);
1183 assert(blockInts == 0);
1185 monitorEnter((threadobject*) THREADOBJECT, o);
1191 void builtin_monitorexit (java_objectheader *o)
1194 #if defined(USE_THREADS)
1195 #if !defined(NATIVE_THREADS)
1198 /* log_text("Monitor leave"); */
1200 assert(blockInts == 0);
1204 hashValue = MUTEX_HASH_VALUE(o);
1205 if (mutexHashTable[hashValue].object == o) {
1206 if (mutexHashTable[hashValue].mutex.count == 1
1207 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1208 internal_unlock_mutex_for_object(o);
1210 --mutexHashTable[hashValue].mutex.count;
1213 internal_unlock_mutex_for_object(o);
1217 assert(blockInts == 0);
1219 monitorExit((threadobject*) THREADOBJECT, o);
1225 /*****************************************************************************
1226 MISCELLANEOUS HELPER FUNCTIONS
1227 *****************************************************************************/
1231 /*********** Functions for integer divisions *****************************
1233 On some systems (eg. DEC ALPHA), integer division is not supported by the
1234 CPU. These helper functions implement the missing functionality.
1236 ******************************************************************************/
1238 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1239 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1242 /************** Functions for long arithmetics *******************************
1244 On systems where 64 bit Integers are not supported by the CPU, these
1245 functions are needed.
1247 ******************************************************************************/
1250 s8 builtin_ladd(s8 a, s8 b)
1255 return builtin_i2l(0);
1259 s8 builtin_lsub(s8 a, s8 b)
1264 return builtin_i2l(0);
1268 s8 builtin_lmul(s8 a, s8 b)
1273 return builtin_i2l(0);
1277 s8 builtin_ldiv(s8 a, s8 b)
1282 return builtin_i2l(0);
1286 s8 builtin_lrem(s8 a, s8 b)
1291 return builtin_i2l(0);
1295 s8 builtin_lshl(s8 a, s4 b)
1298 return a << (b & 63);
1300 return builtin_i2l(0);
1304 s8 builtin_lshr(s8 a, s4 b)
1307 return a >> (b & 63);
1309 return builtin_i2l(0);
1313 s8 builtin_lushr(s8 a, s4 b)
1316 return ((u8) a) >> (b & 63);
1318 return builtin_i2l(0);
1322 s8 builtin_land(s8 a, s8 b)
1327 return builtin_i2l(0);
1331 s8 builtin_lor(s8 a, s8 b)
1336 return builtin_i2l(0);
1340 s8 builtin_lxor(s8 a, s8 b)
1345 return builtin_i2l(0);
1349 s8 builtin_lneg(s8 a)
1354 return builtin_i2l(0);
1358 s4 builtin_lcmp(s8 a, s8 b)
1361 if (a < b) return -1;
1362 if (a > b) return 1;
1373 /*********** Functions for floating point operations *************************/
1375 float builtin_fadd(float a, float b)
1377 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1378 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1389 if (copysignf(1.0, a) == copysignf(1.0, b))
1392 return intBitsToFloat(FLT_NAN);
1398 float builtin_fsub(float a, float b)
1400 return builtin_fadd(a, builtin_fneg(b));
1404 float builtin_fmul(float a, float b)
1406 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1407 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1409 if (finitef(b)) return a * b;
1411 if (a == 0) return intBitsToFloat(FLT_NAN);
1412 else return copysignf(b, copysignf(1.0, b)*a);
1417 if (b == 0) return intBitsToFloat(FLT_NAN);
1418 else return copysignf(a, copysignf(1.0, a)*b);
1421 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1427 float builtin_fdiv(float a, float b)
1429 if (finitef(a) && finitef(b)) {
1434 return intBitsToFloat(FLT_POSINF);
1436 return intBitsToFloat(FLT_NEGINF);
1439 return intBitsToFloat(FLT_NAN);
1443 float builtin_frem(float a, float b)
1449 float builtin_fneg(float a)
1451 if (isnanf(a)) return a;
1453 if (finitef(a)) return -a;
1454 else return copysignf(a, -copysignf(1.0, a));
1459 s4 builtin_fcmpl(float a, float b)
1461 if (isnanf(a)) return -1;
1462 if (isnanf(b)) return -1;
1463 if (!finitef(a) || !finitef(b)) {
1464 a = finitef(a) ? 0 : copysignf(1.0, a);
1465 b = finitef(b) ? 0 : copysignf(1.0, b);
1467 if (a > b) return 1;
1468 if (a == b) return 0;
1473 s4 builtin_fcmpg(float a, float b)
1475 if (isnanf(a)) return 1;
1476 if (isnanf(b)) return 1;
1477 if (!finitef(a) || !finitef(b)) {
1478 a = finitef(a) ? 0 : copysignf(1.0, a);
1479 b = finitef(b) ? 0 : copysignf(1.0, b);
1481 if (a > b) return 1;
1482 if (a == b) return 0;
1488 /************************* Functions for doubles ****************************/
1490 double builtin_dadd(double a, double b)
1492 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1493 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1495 if (finite(b)) return a + b;
1499 if (finite(b)) return a;
1501 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1502 else return longBitsToDouble(DBL_NAN);
1508 double builtin_dsub(double a, double b)
1510 return builtin_dadd(a, builtin_dneg(b));
1514 double builtin_dmul(double a, double b)
1516 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1517 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1519 if (finite(b)) return a * b;
1521 if (a == 0) return longBitsToDouble(DBL_NAN);
1522 else return copysign(b, copysign(1.0, b) * a);
1527 if (b == 0) return longBitsToDouble(DBL_NAN);
1528 else return copysign(a, copysign(1.0, a) * b);
1531 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1537 double builtin_ddiv(double a, double b)
1545 return longBitsToDouble(DBL_NAN);
1547 return copysign(0.0, b);
1553 return longBitsToDouble(DBL_POSINF);
1555 return longBitsToDouble(DBL_NEGINF);
1558 return longBitsToDouble(DBL_NAN);
1561 /* if (finite(a) && finite(b)) { */
1566 /* return longBitsToDouble(DBL_POSINF); */
1567 /* else if (a < 0) */
1568 /* return longBitsToDouble(DBL_NEGINF); */
1572 /* keep compiler happy */
1577 double builtin_drem(double a, double b)
1583 double builtin_dneg(double a)
1585 if (isnan(a)) return a;
1587 if (finite(a)) return -a;
1588 else return copysign(a, -copysign(1.0, a));
1593 s4 builtin_dcmpl(double a, double b)
1595 if (isnan(a)) return -1;
1596 if (isnan(b)) return -1;
1597 if (!finite(a) || !finite(b)) {
1598 a = finite(a) ? 0 : copysign(1.0, a);
1599 b = finite(b) ? 0 : copysign(1.0, b);
1601 if (a > b) return 1;
1602 if (a == b) return 0;
1607 s4 builtin_dcmpg(double a, double b)
1609 if (isnan(a)) return 1;
1610 if (isnan(b)) return 1;
1611 if (!finite(a) || !finite(b)) {
1612 a = finite(a) ? 0 : copysign(1.0, a);
1613 b = finite(b) ? 0 : copysign(1.0, b);
1615 if (a > b) return 1;
1616 if (a == b) return 0;
1621 /*********************** Conversion operations ****************************/
1623 s8 builtin_i2l(s4 i)
1636 float builtin_i2f(s4 a)
1638 float f = (float) a;
1643 double builtin_i2d(s4 a)
1645 double d = (double) a;
1650 s4 builtin_l2i(s8 l)
1660 float builtin_l2f(s8 a)
1663 float f = (float) a;
1671 double builtin_l2d(s8 a)
1674 double d = (double) a;
1682 s4 builtin_f2i(float a)
1685 return builtin_d2i((double) a);
1694 if (a < (-2147483648))
1695 return (-2147483648);
1698 f = copysignf((float) 1.0, a);
1701 return (-2147483648); */
1705 s8 builtin_f2l(float a)
1708 return builtin_d2l((double) a);
1713 if (a > 9223372036854775807L)
1714 return 9223372036854775807L;
1715 if (a < (-9223372036854775808L))
1716 return (-9223372036854775808L);
1721 f = copysignf((float) 1.0, a);
1723 return 9223372036854775807L;
1724 return (-9223372036854775808L); */
1728 double builtin_f2d(float a)
1730 if (finitef(a)) return (double) a;
1733 return longBitsToDouble(DBL_NAN);
1735 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1740 s4 builtin_d2i(double a)
1745 if (a >= 2147483647)
1747 if (a <= (-2147483647-1))
1748 return (-2147483647-1);
1753 d = copysign(1.0, a);
1756 return (-2147483647-1);
1760 s8 builtin_d2l(double a)
1765 if (a >= 9223372036854775807LL)
1766 return 9223372036854775807LL;
1767 if (a <= (-9223372036854775807LL-1))
1768 return (-9223372036854775807LL-1);
1773 d = copysign(1.0, a);
1775 return 9223372036854775807LL;
1776 return (-9223372036854775807LL-1);
1780 float builtin_d2f(double a)
1786 return intBitsToFloat(FLT_NAN);
1788 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1793 /* used to convert FLT_xxx defines into float values */
1795 inline float intBitsToFloat(s4 i)
1804 /* used to convert DBL_xxx defines into double values */
1806 inline float longBitsToDouble(s8 l)
1815 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1817 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1822 panic("Internal error: builtin_dummy called (native function is missing)");
1823 return 0; /* for the compiler */
1827 inline methodinfo *builtin_asm_get_threadrootmethod() {
1828 return *threadrootmethod;
1833 builtin_asm_get_stackframeinfo(){
1834 /*log_text("builtin_asm_get_stackframeinfo()");*/
1835 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1836 return &THREADINFO->_stackframeinfo;
1838 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1839 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1843 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1844 /* stacktraceelement *el;*/
1847 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1848 *el=GCNEW(stacktraceelement,s+1);
1849 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1851 (*el)[s].linenumber=0;
1856 * These are local overrides for various environment variables in Emacs.
1857 * Please do not remove this and leave it at the end of the file, where
1858 * Emacs will automagically detect them.
1859 * ---------------------------------------------------------------------
1862 * indent-tabs-mode: t