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 853 2004-01-06 15:36:25Z twisti $
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*/
65 builtin_descriptor builtin_desc[] = {
66 {(functionptr) builtin_instanceof, "instanceof"},
67 {(functionptr) builtin_checkcast, "checkcast"},
68 {(functionptr) asm_builtin_checkcast, "checkcast"},
69 {(functionptr) builtin_arrayinstanceof, "arrayinstanceof"},
71 {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
73 {(functionptr) builtin_checkarraycast, "checkarraycast"},
74 {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
75 {(functionptr) asm_builtin_aastore, "aastore"},
76 {(functionptr) builtin_new, "new"},
77 {(functionptr) builtin_newarray, "newarray"},
78 {(functionptr) builtin_anewarray, "anewarray"},
81 * have 2 parameters (needs stack manipulation)
83 {(functionptr) asm_builtin_newarray, "newarray"},
85 {(functionptr) builtin_newarray_boolean, "newarray_boolean"},
86 {(functionptr) builtin_newarray_char, "newarray_char"},
87 {(functionptr) builtin_newarray_float, "newarray_float"},
88 {(functionptr) builtin_newarray_double, "newarray_double"},
89 {(functionptr) builtin_newarray_byte, "newarray_byte"},
90 {(functionptr) builtin_newarray_short, "newarray_short"},
91 {(functionptr) builtin_newarray_int, "newarray_int"},
92 {(functionptr) builtin_newarray_long, "newarray_long"},
93 {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
94 {(functionptr) builtin_displaymethodstop, "displaymethodstop"},
95 {(functionptr) builtin_monitorenter, "monitorenter"},
96 {(functionptr) asm_builtin_monitorenter, "monitorenter"},
97 {(functionptr) builtin_monitorexit, "monitorexit"},
98 {(functionptr) asm_builtin_monitorexit, "monitorexit"},
100 {(functionptr) builtin_idiv, "idiv"},
101 {(functionptr) asm_builtin_idiv, "idiv"},
102 {(functionptr) builtin_irem, "irem"},
103 {(functionptr) asm_builtin_irem, "irem"},
105 {(functionptr) builtin_ladd, "ladd"},
106 {(functionptr) builtin_lsub, "lsub"},
107 {(functionptr) builtin_lmul, "lmul"},
108 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
109 {(functionptr) builtin_ldiv, "ldiv"},
110 {(functionptr) asm_builtin_ldiv, "ldiv"},
111 {(functionptr) builtin_lrem, "lrem"},
112 {(functionptr) asm_builtin_lrem, "lrem"},
114 {(functionptr) builtin_lshl, "lshl"},
115 {(functionptr) builtin_lshr, "lshr"},
116 {(functionptr) builtin_lushr, "lushr"},
117 {(functionptr) builtin_land, "land"},
118 {(functionptr) builtin_lor, "lor"},
119 {(functionptr) builtin_lxor, "lxor"},
120 {(functionptr) builtin_lneg, "lneg"},
121 {(functionptr) builtin_lcmp, "lcmp"},
122 {(functionptr) builtin_fadd, "fadd"},
123 {(functionptr) builtin_fsub, "fsub"},
124 {(functionptr) builtin_fmul, "fmul"},
125 {(functionptr) builtin_fdiv, "fdiv"},
126 {(functionptr) builtin_frem, "frem"},
127 {(functionptr) builtin_fneg, "fneg"},
128 {(functionptr) builtin_fcmpl, "fcmpl"},
129 {(functionptr) builtin_fcmpg, "fcmpg"},
130 {(functionptr) builtin_dadd, "dadd"},
131 {(functionptr) builtin_dsub, "dsub"},
132 {(functionptr) builtin_dmul, "dmul"},
133 {(functionptr) builtin_ddiv, "ddiv"},
134 {(functionptr) builtin_drem, "drem"},
135 {(functionptr) builtin_dneg, "dneg"},
136 {(functionptr) builtin_dcmpl, "dcmpl"},
137 {(functionptr) builtin_dcmpg, "dcmpg"},
138 {(functionptr) builtin_i2l, "i2l"},
139 {(functionptr) builtin_i2f, "i2f"},
140 {(functionptr) builtin_i2d, "i2d"},
141 {(functionptr) builtin_l2i, "l2i"},
142 {(functionptr) builtin_l2f, "l2f"},
143 {(functionptr) builtin_l2d, "l2d"},
144 {(functionptr) builtin_f2i, "f2i"},
145 {(functionptr) builtin_f2l, "f2l"},
146 {(functionptr) builtin_f2d, "f2d"},
147 {(functionptr) builtin_d2i, "d2i"},
148 {(functionptr) builtin_d2l, "d2l"},
149 #if defined(__I386__)
150 {(functionptr) asm_builtin_f2i, "f2i"},
151 {(functionptr) asm_builtin_f2l, "f2l"},
152 {(functionptr) asm_builtin_d2i, "d2i"},
153 {(functionptr) asm_builtin_d2l, "d2l"},
155 {(functionptr) builtin_d2f, "d2f"},
156 {(functionptr) NULL, "unknown"}
161 /*****************************************************************************
163 *****************************************************************************/
167 /*************** internal function: builtin_isanysubclass *********************
169 Checks a subclass relation between two classes. Implemented interfaces
170 are interpreted as super classes.
171 Return value: 1 ... sub is subclass of super
174 *****************************************************************************/
175 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
180 if (super->flags & ACC_INTERFACE)
181 return (sub->vftbl->interfacetablelength > super->index) &&
182 (sub->vftbl->interfacetable[-super->index] != NULL);
195 for (tmp=sub;tmp!=0;tmp=tmp->super) {
197 utf_display(tmp->name);
201 for (tmp=super;tmp!=0;tmp=tmp->super) {
203 utf_display(tmp->name);
208 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
209 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
210 super->vftbl->diffval); */
212 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
216 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
217 (unsigned) (super->vftbl->diffval);
219 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
226 /* XXX inline this? */
227 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
232 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
236 if ((base = super->baseval) <= 0)
237 /* super is an interface */
238 res = (sub->interfacetablelength > -base) &&
239 (sub->interfacetable[base] != NULL);
241 res = (unsigned) (sub->baseval - base)
242 <= (unsigned) (super->diffval);
244 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
252 /****************** function: builtin_instanceof *****************************
254 Checks if an object is an instance of some given class (or subclass of
255 that class). If class is an interface, checks if the interface is
257 Return value: 1 ... obj is an instance of class or implements the interface
258 0 ... otherwise or if obj == NULL
260 *****************************************************************************/
262 /* XXX should use vftbl */
263 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
266 log_text ("builtin_instanceof called");
269 return builtin_isanysubclass (obj->vftbl->class, class);
274 /**************** function: builtin_checkcast *******************************
276 The same as builtin_instanceof except that 1 is returned when
279 ****************************************************************************/
281 /* XXX should use vftbl */
282 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
285 log_text("builtin_checkcast called");
290 if (builtin_isanysubclass(obj->vftbl->class, class))
294 printf("#### checkcast failed ");
295 utf_display(obj->vftbl->class->name);
297 utf_display(class->name);
305 /*********** internal function: builtin_descriptorscompatible ******************
307 Checks if two array type descriptors are assignment compatible
308 Return value: 1 ... target = desc is possible
311 ******************************************************************************/
313 /* XXX inline this? */
314 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
316 if (desc==target) return 1;
317 if (desc->arraytype != target->arraytype) return 0;
318 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
320 /* {both arrays are arrays of references} */
321 if (desc->dimension == target->dimension)
322 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
323 if (desc->dimension < target->dimension) return 0;
325 /* {desc has higher dimension than target} */
326 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
330 /******************** function: builtin_checkarraycast ***********************
332 Checks if an object is really a subtype of the requested array type.
333 The object has to be an array to begin with. For simple arrays (int, short,
334 double, etc.) the types have to match exactly.
335 For arrays of objects, the type of elements in the array has to be a
336 subtype (or the same type) of the requested element type. For arrays of
337 arrays (which in turn can again be arrays of arrays), the types at the
338 lowest level have to satisfy the corresponding sub class relation.
340 Return value: 1 ... cast is possible
343 ATTENTION: a cast with a NULL pointer is always possible.
345 *****************************************************************************/
347 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
349 arraydescriptor *desc;
352 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
354 return builtin_descriptorscompatible(desc, target->arraydesc);
358 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
361 return builtin_checkarraycast(obj, target);
365 /************************** exception functions *******************************
367 ******************************************************************************/
369 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
372 char logtext[MAXLOGTEXT];
373 sprintf(logtext, "Builtin exception thrown: ");
374 if (local_exceptionptr)
375 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
377 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
378 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
379 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
380 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
381 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
382 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
383 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
384 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
385 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
386 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
387 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
391 exceptionptr = local_exceptionptr;
392 return local_exceptionptr;
395 java_objectheader *builtin_get_exceptionptr()
397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
401 pthread_getspecific(tkey_exceptionptr);
404 panic("builtin_get_exceptionptr should not be used in this configuration");
409 void builtin_set_exceptionptr(java_objectheader *e)
411 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
415 pthread_setspecific(tkey_exceptionptr, e);
418 panic("builtin_set_exceptionptr should not be used in this configuration");
423 /******************* function: builtin_canstore *******************************
425 Checks, if an object can be stored in an array.
426 Return value: 1 ... possible
429 ******************************************************************************/
431 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
433 arraydescriptor *desc;
434 arraydescriptor *valuedesc;
435 vftbl *componentvftbl;
442 /* The following is guaranteed (by verifier checks):
444 * *) a->...vftbl->arraydesc != NULL
445 * *) a->...vftbl->arraydesc->componentvftbl != NULL
446 * *) o->vftbl is not an interface vftbl
449 desc = a->header.objheader.vftbl->arraydesc;
450 componentvftbl = desc->componentvftbl;
451 valuevftbl = o->vftbl;
453 if ((dim_m1 = desc->dimension - 1) == 0) {
456 /* {a is a one-dimensional array} */
457 /* {a is an array of references} */
459 if (valuevftbl == componentvftbl)
462 if ((base = componentvftbl->baseval) <= 0)
463 /* an array of interface references */
464 return (valuevftbl->interfacetablelength > -base &&
465 valuevftbl->interfacetable[base] != NULL);
467 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
471 res = (unsigned)(valuevftbl->baseval - base)
472 <= (unsigned)(componentvftbl->diffval);
474 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
480 /* {a has dimension > 1} */
481 /* {componentvftbl->arraydesc != NULL} */
483 /* check if o is an array */
484 if ((valuedesc = valuevftbl->arraydesc) == NULL)
486 /* {o is an array} */
488 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
492 /* This is an optimized version where a is guaranteed to be one-dimensional */
493 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
495 arraydescriptor *desc;
503 /* The following is guaranteed (by verifier checks):
505 * *) a->...vftbl->arraydesc != NULL
506 * *) a->...vftbl->arraydesc->elementvftbl != NULL
507 * *) a->...vftbl->arraydesc->dimension == 1
508 * *) o->vftbl is not an interface vftbl
511 desc = a->header.objheader.vftbl->arraydesc;
512 elementvftbl = desc->elementvftbl;
513 valuevftbl = o->vftbl;
515 /* {a is a one-dimensional array} */
517 if (valuevftbl == elementvftbl)
520 if ((base = elementvftbl->baseval) <= 0)
521 /* an array of interface references */
522 return (valuevftbl->interfacetablelength > -base &&
523 valuevftbl->interfacetable[base] != NULL);
525 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
529 res = (unsigned)(valuevftbl->baseval - base)
530 <= (unsigned)(elementvftbl->diffval);
532 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
540 /* This is an optimized version where a is guaranteed to be a
541 * one-dimensional array of a class type */
542 /* XXX this could be inlined by the code generator */
543 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
551 /* The following is guaranteed (by verifier checks):
553 * *) a->...vftbl->arraydesc != NULL
554 * *) a->...vftbl->arraydesc->elementvftbl != NULL
555 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
556 * *) a->...vftbl->arraydesc->dimension == 1
557 * *) o->vftbl is not an interface vftbl
560 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
561 valuevftbl = o->vftbl;
563 /* {a is a one-dimensional array} */
565 if (valuevftbl == elementvftbl)
568 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
572 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
573 <= (unsigned)(elementvftbl->diffval);
575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
583 /******************** Function: builtin_new **********************************
585 Creates a new instance of class c on the heap.
586 Return value: pointer to the object or NULL if no memory is
589 *****************************************************************************/
592 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
594 java_objectheader *builtin_new(classinfo *c)
596 java_objectheader *o;
599 char logtext[MAXLOGTEXT];
600 sprintf(logtext, "Initialize class ");
601 utf_sprint(logtext + strlen(logtext), c->name);
602 sprintf(logtext + strlen(logtext), " (from builtin_new)");
607 #ifdef SIZE_FROM_CLASSINFO
608 c->alignedsize = align_size(c->instancesize);
609 o = heap_allocate(c->alignedsize, true, c->finalizer);
611 o = heap_allocate(c->instancesize, true, c->finalizer);
615 memset(o, 0, c->instancesize);
622 /********************** Function: builtin_newarray **************************
624 Creates an array with the given vftbl on the heap.
626 Return value: pointer to the array or NULL if no memory is available
628 CAUTION: The given vftbl must be the vftbl of the *array* class,
629 not of the element class.
631 *****************************************************************************/
633 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
636 arraydescriptor *desc = arrayvftbl->arraydesc;
637 s4 dataoffset = desc->dataoffset;
638 s4 componentsize = desc->componentsize;
642 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
645 #ifdef SIZE_FROM_CLASSINFO
646 actualsize = align_size(dataoffset + size * componentsize);
648 actualsize = dataoffset + size * componentsize;
651 if (((u4)actualsize)<((u4)size)) { /* overflow */
652 exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
655 a = heap_allocate(actualsize,
656 (desc->arraytype == ARRAYTYPE_OBJECT),
660 memset(a, 0, actualsize);
663 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
665 a->objheader.vftbl = arrayvftbl;
667 #ifdef SIZE_FROM_CLASSINFO
668 a->alignedsize = actualsize;
675 /********************** Function: builtin_anewarray *************************
677 Creates an array of references to the given class type on the heap.
679 Return value: pointer to the array or NULL if no memory is available
681 XXX This function does not do The Right Thing, because it uses a
682 classinfo pointer at runtime. builtin_newarray should be used
685 *****************************************************************************/
687 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
689 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
693 /******************** Function: builtin_newarray_int ***********************
695 Creates an array of 32 bit Integers on the heap.
697 Return value: pointer to the array or NULL if no memory is available
699 *****************************************************************************/
701 java_intarray *builtin_newarray_int(s4 size)
703 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
707 /******************** Function: builtin_newarray_long ***********************
709 Creates an array of 64 bit Integers on the heap.
711 Return value: pointer to the array or NULL if no memory is available
713 *****************************************************************************/
715 java_longarray *builtin_newarray_long(s4 size)
717 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
721 /******************** function: builtin_newarray_float ***********************
723 Creates an array of 32 bit IEEE floats on the heap.
725 Return value: pointer to the array or NULL if no memory is available
727 *****************************************************************************/
729 java_floatarray *builtin_newarray_float(s4 size)
731 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
735 /******************** function: builtin_newarray_double ***********************
737 Creates an array of 64 bit IEEE floats on the heap.
739 Return value: pointer to the array or NULL if no memory is available
741 *****************************************************************************/
743 java_doublearray *builtin_newarray_double(s4 size)
745 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
749 /******************** function: builtin_newarray_byte ***********************
751 Creates an array of 8 bit Integers on the heap.
753 Return value: pointer to the array or NULL if no memory is available
755 *****************************************************************************/
757 java_bytearray *builtin_newarray_byte(s4 size)
759 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
763 /******************** function: builtin_newarray_char ************************
765 Creates an array of characters on the heap.
767 Return value: pointer to the array or NULL if no memory is available
769 *****************************************************************************/
771 java_chararray *builtin_newarray_char(s4 size)
773 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
777 /******************** function: builtin_newarray_short ***********************
779 Creates an array of 16 bit Integers on the heap.
781 Return value: pointer to the array or NULL if no memory is available
783 *****************************************************************************/
785 java_shortarray *builtin_newarray_short(s4 size)
787 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
791 /******************** function: builtin_newarray_boolean ************************
793 Creates an array of bytes on the heap. The array is designated as an array
794 of booleans (important for casts)
796 Return value: pointer to the array or NULL if no memory is available
798 *****************************************************************************/
800 java_booleanarray *builtin_newarray_boolean(s4 size)
802 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
806 /**************** function: builtin_nmultianewarray ***************************
808 Creates a multi-dimensional array on the heap. The dimensions are passed in
812 n............number of dimensions to create
813 arrayvftbl...vftbl of the array class
814 dims.........array containing the size of each dimension to create
816 Return value: pointer to the array or NULL if no memory is available
818 ******************************************************************************/
820 /* Helper functions */
822 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
826 vftbl *componentvftbl;
828 /* create this dimension */
829 size = (int) dims[0];
830 a = builtin_newarray(size,arrayvftbl);
833 /* if this is the last dimension return */
836 /* get the vftbl of the components to create */
837 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
838 if (!componentvftbl) /* XXX the verifier could check this */
839 panic ("multianewarray with too many dimensions");
841 /* create the component arrays */
842 for (i = 0; i < size; i++) {
843 java_arrayheader *ea =
844 builtin_nmultianewarray(n,componentvftbl,dims+1);
845 if (!ea) return NULL;
846 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
853 /*****************************************************************************
856 Various functions for printing a message at method entry or exit (for
859 *****************************************************************************/
864 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
865 methodinfo *method, int *pos,
872 log_text("WARNING: unmatched methodindent--");
874 if (verbose || runverbose) {
875 printf("Exception ");
877 utf_display (exceptionptr->vftbl->class->name);
880 printf("Error: <Nullpointer instead of exception>");
881 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
882 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
883 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
884 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
885 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
886 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
887 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
888 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
889 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
890 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
893 printf(" thrown in ");
895 utf_display (method->class->name);
897 utf_display (method->name);
898 if (method->flags & ACC_SYNCHRONIZED)
902 printf("(%p) at position %p\n", method->entrypoint, pos);
905 printf("call_java_method\n");
912 #ifdef TRACE_ARGS_NUM
913 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
914 #if TRACE_ARGS_NUM > 6
920 char logtext[MAXLOGTEXT];
921 for (i = 0; i < methodindent; i++)
923 sprintf(logtext + methodindent, "called: ");
924 utf_sprint(logtext + strlen(logtext), method->class->name);
925 sprintf(logtext + strlen(logtext), ".");
926 utf_sprint(logtext + strlen(logtext), method->name);
927 utf_sprint(logtext + strlen(logtext), method->descriptor);
928 sprintf(logtext + strlen(logtext), "(");
930 switch (method->paramcount) {
934 #if defined(__I386__)
936 sprintf(logtext+strlen(logtext), "%llx", a0);
940 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
944 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
948 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
953 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
958 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
959 a0, a1, a2, a3, a4, a5);
962 #if TRACE_ARGS_NUM > 6
964 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
965 a0, a1, a2, a3, a4, a5, a6);
969 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
970 a0, a1, a2, a3, a4, a5, a6, a7);
974 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
975 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
979 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
980 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
985 sprintf(logtext+strlen(logtext), "%lx", a0);
989 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
993 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
997 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1002 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1003 a0, a1, a2, a3, a4);
1007 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1008 a0, a1, a2, a3, a4, a5);
1011 #if TRACE_ARGS_NUM > 6
1013 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1014 a0, a1, a2, a3, a4, a5, a6);
1018 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1019 a0, a1, a2, a3, a4, a5, a6, a7);
1023 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1024 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
1028 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1029 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
1034 sprintf (logtext+strlen(logtext), ")");
1042 void builtin_displaymethodstart(methodinfo *method)
1044 char logtext[MAXLOGTEXT];
1045 sprintf(logtext, " ");
1046 sprintf(logtext + methodindent, "called: ");
1047 utf_sprint(logtext + strlen(logtext), method->class->name);
1048 sprintf(logtext + strlen(logtext), ".");
1049 utf_sprint(logtext + strlen(logtext), method->name);
1050 utf_sprint(logtext + strlen(logtext), method->descriptor);
1056 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1059 char logtext[MAXLOGTEXT];
1060 for (i = 0; i < methodindent; i++)
1065 log_text("WARNING: unmatched methodindent--");
1066 sprintf(logtext + methodindent, "finished: ");
1067 utf_sprint(logtext + strlen(logtext), method->class->name);
1068 sprintf(logtext + strlen(logtext), ".");
1069 utf_sprint(logtext + strlen(logtext), method->name);
1070 utf_sprint(logtext + strlen(logtext), method->descriptor);
1072 switch (method->returntype) {
1074 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1077 #if defined(__I386__)
1078 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1080 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1084 #if defined(__I386__)
1085 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1087 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1091 sprintf(logtext + strlen(logtext), "->%g", f);
1094 sprintf(logtext + strlen(logtext), "->%g", d);
1101 void builtin_displaymethodexception(methodinfo *method)
1104 char logtext[MAXLOGTEXT];
1105 for (i = 0; i < methodindent; i++)
1107 sprintf(logtext + methodindent, "exception abort: ");
1108 utf_sprint(logtext + strlen(logtext), method->class->name);
1109 sprintf(logtext + strlen(logtext), ".");
1110 utf_sprint(logtext + strlen(logtext), method->name);
1111 utf_sprint(logtext + strlen(logtext), method->descriptor);
1116 /****************************************************************************
1117 SYNCHRONIZATION FUNCTIONS
1118 *****************************************************************************/
1121 * Lock the mutex of an object.
1123 void internal_lock_mutex_for_object(java_objectheader *object)
1126 mutexHashEntry *entry;
1129 assert(object != 0);
1131 hashValue = MUTEX_HASH_VALUE(object);
1132 entry = &mutexHashTable[hashValue];
1134 if (entry->object != 0) {
1135 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1137 entry->mutex.holder = 0;
1138 entry->mutex.count = 0;
1139 entry->mutex.muxWaiters = 0;
1142 while (entry->next != 0 && entry->object != object)
1143 entry = entry->next;
1145 if (entry->object != object) {
1146 entry->next = firstFreeOverflowEntry;
1147 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1149 entry = entry->next;
1152 assert(entry->conditionCount == 0);
1157 entry->mutex.holder = 0;
1158 entry->mutex.count = 0;
1159 entry->mutex.muxWaiters = 0;
1162 if (entry->object == 0)
1163 entry->object = object;
1165 internal_lock_mutex(&entry->mutex);
1171 * Unlocks the mutex of an object.
1173 void internal_unlock_mutex_for_object (java_objectheader *object)
1177 mutexHashEntry *entry;
1179 hashValue = MUTEX_HASH_VALUE(object);
1180 entry = &mutexHashTable[hashValue];
1182 if (entry->object == object) {
1183 internal_unlock_mutex(&entry->mutex);
1186 while (entry->next != 0 && entry->next->object != object)
1187 entry = entry->next;
1189 assert(entry->next != 0);
1191 internal_unlock_mutex(&entry->next->mutex);
1193 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1194 mutexHashEntry *unlinked = entry->next;
1196 entry->next = unlinked->next;
1197 unlinked->next = firstFreeOverflowEntry;
1198 firstFreeOverflowEntry = unlinked;
1205 void builtin_monitorenter(java_objectheader *o)
1210 assert(blockInts == 0);
1214 hashValue = MUTEX_HASH_VALUE(o);
1215 if (mutexHashTable[hashValue].object == o
1216 && mutexHashTable[hashValue].mutex.holder == currentThread)
1217 ++mutexHashTable[hashValue].mutex.count;
1219 internal_lock_mutex_for_object(o);
1223 assert(blockInts == 0);
1228 void builtin_monitorexit (java_objectheader *o)
1233 assert(blockInts == 0);
1237 hashValue = MUTEX_HASH_VALUE(o);
1238 if (mutexHashTable[hashValue].object == o) {
1239 if (mutexHashTable[hashValue].mutex.count == 1
1240 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1241 internal_unlock_mutex_for_object(o);
1243 --mutexHashTable[hashValue].mutex.count;
1246 internal_unlock_mutex_for_object(o);
1250 assert(blockInts == 0);
1255 /*****************************************************************************
1256 MISCELLANEOUS HELPER FUNCTIONS
1257 *****************************************************************************/
1261 /*********** Functions for integer divisions *****************************
1263 On some systems (eg. DEC ALPHA), integer division is not supported by the
1264 CPU. These helper functions implement the missing functionality.
1266 ******************************************************************************/
1268 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1269 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1272 /************** Functions for long arithmetics *******************************
1274 On systems where 64 bit Integers are not supported by the CPU, these
1275 functions are needed.
1277 ******************************************************************************/
1280 s8 builtin_ladd(s8 a, s8 b)
1285 return builtin_i2l(0);
1289 s8 builtin_lsub(s8 a, s8 b)
1294 return builtin_i2l(0);
1298 s8 builtin_lmul(s8 a, s8 b)
1303 return builtin_i2l(0);
1307 s8 builtin_ldiv(s8 a, s8 b)
1312 return builtin_i2l(0);
1316 s8 builtin_lrem(s8 a, s8 b)
1321 return builtin_i2l(0);
1325 s8 builtin_lshl(s8 a, s4 b)
1328 return a << (b & 63);
1330 return builtin_i2l(0);
1334 s8 builtin_lshr(s8 a, s4 b)
1337 return a >> (b & 63);
1339 return builtin_i2l(0);
1343 s8 builtin_lushr(s8 a, s4 b)
1346 return ((u8) a) >> (b & 63);
1348 return builtin_i2l(0);
1352 s8 builtin_land(s8 a, s8 b)
1357 return builtin_i2l(0);
1361 s8 builtin_lor(s8 a, s8 b)
1366 return builtin_i2l(0);
1370 s8 builtin_lxor(s8 a, s8 b)
1375 return builtin_i2l(0);
1379 s8 builtin_lneg(s8 a)
1384 return builtin_i2l(0);
1388 s4 builtin_lcmp(s8 a, s8 b)
1391 if (a < b) return -1;
1392 if (a > b) return 1;
1403 /*********** Functions for floating point operations *************************/
1405 float builtin_fadd(float a, float b)
1407 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1408 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1419 if (copysignf(1.0, a) == copysignf(1.0, b))
1422 return intBitsToFloat(FLT_NAN);
1428 float builtin_fsub(float a, float b)
1430 return builtin_fadd(a, builtin_fneg(b));
1434 float builtin_fmul(float a, float b)
1436 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1437 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1439 if (finitef(b)) return a * b;
1441 if (a == 0) return intBitsToFloat(FLT_NAN);
1442 else return copysignf(b, copysignf(1.0, b)*a);
1447 if (b == 0) return intBitsToFloat(FLT_NAN);
1448 else return copysignf(a, copysignf(1.0, a)*b);
1451 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1457 float builtin_fdiv(float a, float b)
1459 if (finitef(a) && finitef(b)) {
1464 return intBitsToFloat(FLT_POSINF);
1466 return intBitsToFloat(FLT_NEGINF);
1469 return intBitsToFloat(FLT_NAN);
1473 float builtin_frem(float a, float b)
1479 float builtin_fneg(float a)
1481 if (isnanf(a)) return a;
1483 if (finitef(a)) return -a;
1484 else return copysignf(a, -copysignf(1.0, a));
1489 s4 builtin_fcmpl(float a, float b)
1491 if (isnanf(a)) return -1;
1492 if (isnanf(b)) return -1;
1493 if (!finitef(a) || !finitef(b)) {
1494 a = finitef(a) ? 0 : copysignf(1.0, a);
1495 b = finitef(b) ? 0 : copysignf(1.0, b);
1497 if (a > b) return 1;
1498 if (a == b) return 0;
1503 s4 builtin_fcmpg(float a, float b)
1505 if (isnanf(a)) return 1;
1506 if (isnanf(b)) return 1;
1507 if (!finitef(a) || !finitef(b)) {
1508 a = finitef(a) ? 0 : copysignf(1.0, a);
1509 b = finitef(b) ? 0 : copysignf(1.0, b);
1511 if (a > b) return 1;
1512 if (a == b) return 0;
1518 /************************* Functions for doubles ****************************/
1520 double builtin_dadd(double a, double b)
1522 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1523 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1525 if (finite(b)) return a + b;
1529 if (finite(b)) return a;
1531 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1532 else return longBitsToDouble(DBL_NAN);
1538 double builtin_dsub(double a, double b)
1540 return builtin_dadd(a, builtin_dneg(b));
1544 double builtin_dmul(double a, double b)
1546 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1547 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1549 if (finite(b)) return a * b;
1551 if (a == 0) return longBitsToDouble(DBL_NAN);
1552 else return copysign(b, copysign(1.0, b) * a);
1557 if (b == 0) return longBitsToDouble(DBL_NAN);
1558 else return copysign(a, copysign(1.0, a) * b);
1561 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1567 double builtin_ddiv(double a, double b)
1575 return longBitsToDouble(DBL_NAN);
1577 return copysign(0.0, b);
1583 return longBitsToDouble(DBL_POSINF);
1585 return longBitsToDouble(DBL_NEGINF);
1588 return longBitsToDouble(DBL_NAN);
1591 /* if (finite(a) && finite(b)) { */
1596 /* return longBitsToDouble(DBL_POSINF); */
1597 /* else if (a < 0) */
1598 /* return longBitsToDouble(DBL_NEGINF); */
1602 /* keep compiler happy */
1607 double builtin_drem(double a, double b)
1613 double builtin_dneg(double a)
1615 if (isnan(a)) return a;
1617 if (finite(a)) return -a;
1618 else return copysign(a, -copysign(1.0, a));
1623 s4 builtin_dcmpl(double a, double b)
1625 if (isnan(a)) return -1;
1626 if (isnan(b)) return -1;
1627 if (!finite(a) || !finite(b)) {
1628 a = finite(a) ? 0 : copysign(1.0, a);
1629 b = finite(b) ? 0 : copysign(1.0, b);
1631 if (a > b) return 1;
1632 if (a == b) return 0;
1637 s4 builtin_dcmpg(double a, double b)
1639 if (isnan(a)) return 1;
1640 if (isnan(b)) return 1;
1641 if (!finite(a) || !finite(b)) {
1642 a = finite(a) ? 0 : copysign(1.0, a);
1643 b = finite(b) ? 0 : copysign(1.0, b);
1645 if (a > b) return 1;
1646 if (a == b) return 0;
1651 /*********************** Conversion operations ****************************/
1653 s8 builtin_i2l(s4 i)
1666 float builtin_i2f(s4 a)
1668 float f = (float) a;
1673 double builtin_i2d(s4 a)
1675 double d = (double) a;
1680 s4 builtin_l2i(s8 l)
1690 float builtin_l2f(s8 a)
1693 float f = (float) a;
1701 double builtin_l2d(s8 a)
1704 double d = (double) a;
1712 s4 builtin_f2i(float a)
1715 return builtin_d2i((double) a);
1724 if (a < (-2147483648))
1725 return (-2147483648);
1728 f = copysignf((float) 1.0, a);
1731 return (-2147483648); */
1735 s8 builtin_f2l(float a)
1738 return builtin_d2l((double) a);
1743 if (a > 9223372036854775807L)
1744 return 9223372036854775807L;
1745 if (a < (-9223372036854775808L))
1746 return (-9223372036854775808L);
1751 f = copysignf((float) 1.0, a);
1753 return 9223372036854775807L;
1754 return (-9223372036854775808L); */
1758 double builtin_f2d(float a)
1760 if (finitef(a)) return (double) a;
1763 return longBitsToDouble(DBL_NAN);
1765 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1770 s4 builtin_d2i(double a)
1775 if (a >= 2147483647)
1777 if (a <= (-2147483647-1))
1778 return (-2147483647-1);
1783 d = copysign(1.0, a);
1786 return (-2147483647-1);
1790 s8 builtin_d2l(double a)
1795 if (a >= 9223372036854775807LL)
1796 return 9223372036854775807LL;
1797 if (a <= (-9223372036854775807LL-1))
1798 return (-9223372036854775807LL-1);
1803 d = copysign(1.0, a);
1805 return 9223372036854775807LL;
1806 return (-9223372036854775807LL-1);
1810 float builtin_d2f(double a)
1816 return intBitsToFloat(FLT_NAN);
1818 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1823 /* used to convert FLT_xxx defines into float values */
1825 inline float intBitsToFloat(s4 i)
1834 /* used to convert DBL_xxx defines into double values */
1836 inline float longBitsToDouble(s8 l)
1845 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1847 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1852 * These are local overrides for various environment variables in Emacs.
1853 * Please do not remove this and leave it at the end of the file, where
1854 * Emacs will automagically detect them.
1855 * ---------------------------------------------------------------------
1858 * indent-tabs-mode: t