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 851 2004-01-05 23:59:28Z 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*/
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;
600 #ifdef SIZE_FROM_CLASSINFO
601 c->alignedsize = align_size(c->instancesize);
602 o = heap_allocate(c->alignedsize, true, c->finalizer);
604 o = heap_allocate(c->instancesize, true, c->finalizer);
608 memset(o, 0, c->instancesize);
615 /********************** Function: builtin_newarray **************************
617 Creates an array with the given vftbl on the heap.
619 Return value: pointer to the array or NULL if no memory is available
621 CAUTION: The given vftbl must be the vftbl of the *array* class,
622 not of the element class.
624 *****************************************************************************/
626 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
629 arraydescriptor *desc = arrayvftbl->arraydesc;
630 s4 dataoffset = desc->dataoffset;
631 s4 componentsize = desc->componentsize;
635 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
638 #ifdef SIZE_FROM_CLASSINFO
639 actualsize = align_size(dataoffset + size * componentsize);
641 actualsize = dataoffset + size * componentsize;
644 if (((u4)actualsize)<((u4)size)) { /* overflow */
645 exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
648 a = heap_allocate(actualsize,
649 (desc->arraytype == ARRAYTYPE_OBJECT),
653 memset(a, 0, actualsize);
656 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
658 a->objheader.vftbl = arrayvftbl;
660 #ifdef SIZE_FROM_CLASSINFO
661 a->alignedsize = actualsize;
668 /********************** Function: builtin_anewarray *************************
670 Creates an array of references to the given class type on the heap.
672 Return value: pointer to the array or NULL if no memory is available
674 XXX This function does not do The Right Thing, because it uses a
675 classinfo pointer at runtime. builtin_newarray should be used
678 *****************************************************************************/
680 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
682 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
686 /******************** Function: builtin_newarray_int ***********************
688 Creates an array of 32 bit Integers on the heap.
690 Return value: pointer to the array or NULL if no memory is available
692 *****************************************************************************/
694 java_intarray *builtin_newarray_int(s4 size)
696 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
700 /******************** Function: builtin_newarray_long ***********************
702 Creates an array of 64 bit Integers on the heap.
704 Return value: pointer to the array or NULL if no memory is available
706 *****************************************************************************/
708 java_longarray *builtin_newarray_long(s4 size)
710 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
714 /******************** function: builtin_newarray_float ***********************
716 Creates an array of 32 bit IEEE floats on the heap.
718 Return value: pointer to the array or NULL if no memory is available
720 *****************************************************************************/
722 java_floatarray *builtin_newarray_float(s4 size)
724 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
728 /******************** function: builtin_newarray_double ***********************
730 Creates an array of 64 bit IEEE floats on the heap.
732 Return value: pointer to the array or NULL if no memory is available
734 *****************************************************************************/
736 java_doublearray *builtin_newarray_double(s4 size)
738 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
742 /******************** function: builtin_newarray_byte ***********************
744 Creates an array of 8 bit Integers on the heap.
746 Return value: pointer to the array or NULL if no memory is available
748 *****************************************************************************/
750 java_bytearray *builtin_newarray_byte(s4 size)
752 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
756 /******************** function: builtin_newarray_char ************************
758 Creates an array of characters on the heap.
760 Return value: pointer to the array or NULL if no memory is available
762 *****************************************************************************/
764 java_chararray *builtin_newarray_char(s4 size)
766 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
770 /******************** function: builtin_newarray_short ***********************
772 Creates an array of 16 bit Integers on the heap.
774 Return value: pointer to the array or NULL if no memory is available
776 *****************************************************************************/
778 java_shortarray *builtin_newarray_short(s4 size)
780 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
784 /******************** function: builtin_newarray_boolean ************************
786 Creates an array of bytes on the heap. The array is designated as an array
787 of booleans (important for casts)
789 Return value: pointer to the array or NULL if no memory is available
791 *****************************************************************************/
793 java_booleanarray *builtin_newarray_boolean(s4 size)
795 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
799 /**************** function: builtin_nmultianewarray ***************************
801 Creates a multi-dimensional array on the heap. The dimensions are passed in
805 n............number of dimensions to create
806 arrayvftbl...vftbl of the array class
807 dims.........array containing the size of each dimension to create
809 Return value: pointer to the array or NULL if no memory is available
811 ******************************************************************************/
813 /* Helper functions */
815 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
819 vftbl *componentvftbl;
821 /* create this dimension */
822 size = (int) dims[0];
823 a = builtin_newarray(size,arrayvftbl);
826 /* if this is the last dimension return */
829 /* get the vftbl of the components to create */
830 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
831 if (!componentvftbl) /* XXX the verifier could check this */
832 panic ("multianewarray with too many dimensions");
834 /* create the component arrays */
835 for (i = 0; i < size; i++) {
836 java_arrayheader *ea =
837 builtin_nmultianewarray(n,componentvftbl,dims+1);
838 if (!ea) return NULL;
839 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
846 /*****************************************************************************
849 Various functions for printing a message at method entry or exit (for
852 *****************************************************************************/
857 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
858 methodinfo *method, int *pos,
865 log_text("WARNING: unmatched methodindent--");
867 if (verbose || runverbose) {
868 printf("Exception ");
870 utf_display (exceptionptr->vftbl->class->name);
873 printf("Error: <Nullpointer instead of exception>");
874 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
875 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
876 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
877 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
878 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
879 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
880 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
881 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
882 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
883 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
886 printf(" thrown in ");
888 utf_display (method->class->name);
890 utf_display (method->name);
891 if (method->flags & ACC_SYNCHRONIZED)
895 printf("(%p) at position %p\n", method->entrypoint, pos);
898 printf("call_java_method\n");
905 #ifdef TRACE_ARGS_NUM
906 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
907 #if TRACE_ARGS_NUM > 6
913 char logtext[MAXLOGTEXT];
914 for (i = 0; i < methodindent; i++)
916 sprintf(logtext + methodindent, "called: ");
917 utf_sprint(logtext + strlen(logtext), method->class->name);
918 sprintf(logtext + strlen(logtext), ".");
919 utf_sprint(logtext + strlen(logtext), method->name);
920 utf_sprint(logtext + strlen(logtext), method->descriptor);
921 sprintf(logtext + strlen(logtext), "(");
923 switch (method->paramcount) {
927 #if defined(__I386__)
929 sprintf(logtext+strlen(logtext), "%llx", a0);
933 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
937 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
941 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
946 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
951 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
952 a0, a1, a2, a3, a4, a5);
955 #if TRACE_ARGS_NUM > 6
957 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
958 a0, a1, a2, a3, a4, a5, a6);
962 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
963 a0, a1, a2, a3, a4, a5, a6, a7);
967 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
968 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
972 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
973 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
978 sprintf(logtext+strlen(logtext), "%lx", a0);
982 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
986 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
990 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
995 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1000 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1001 a0, a1, a2, a3, a4, a5);
1004 #if TRACE_ARGS_NUM > 6
1006 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1007 a0, a1, a2, a3, a4, a5, a6);
1011 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1012 a0, a1, a2, a3, a4, a5, a6, a7);
1016 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1017 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
1021 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1022 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
1027 sprintf (logtext+strlen(logtext), ")");
1035 void builtin_displaymethodstart(methodinfo *method)
1037 char logtext[MAXLOGTEXT];
1038 sprintf(logtext, " ");
1039 sprintf(logtext + methodindent, "called: ");
1040 utf_sprint(logtext + strlen(logtext), method->class->name);
1041 sprintf(logtext + strlen(logtext), ".");
1042 utf_sprint(logtext + strlen(logtext), method->name);
1043 utf_sprint(logtext + strlen(logtext), method->descriptor);
1049 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1052 char logtext[MAXLOGTEXT];
1053 for (i = 0; i < methodindent; i++)
1058 log_text("WARNING: unmatched methodindent--");
1059 sprintf(logtext + methodindent, "finished: ");
1060 utf_sprint(logtext + strlen(logtext), method->class->name);
1061 sprintf(logtext + strlen(logtext), ".");
1062 utf_sprint(logtext + strlen(logtext), method->name);
1063 utf_sprint(logtext + strlen(logtext), method->descriptor);
1065 switch (method->returntype) {
1067 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1070 #if defined(__I386__)
1071 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1073 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1077 #if defined(__I386__)
1078 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1080 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1084 sprintf(logtext + strlen(logtext), "->%g", f);
1087 sprintf(logtext + strlen(logtext), "->%g", d);
1094 void builtin_displaymethodexception(methodinfo *method)
1097 char logtext[MAXLOGTEXT];
1098 for (i = 0; i < methodindent; i++)
1100 sprintf(logtext + methodindent, "exception abort: ");
1101 utf_sprint(logtext + strlen(logtext), method->class->name);
1102 sprintf(logtext + strlen(logtext), ".");
1103 utf_sprint(logtext + strlen(logtext), method->name);
1104 utf_sprint(logtext + strlen(logtext), method->descriptor);
1109 /****************************************************************************
1110 SYNCHRONIZATION FUNCTIONS
1111 *****************************************************************************/
1114 * Lock the mutex of an object.
1116 void internal_lock_mutex_for_object(java_objectheader *object)
1119 mutexHashEntry *entry;
1122 assert(object != 0);
1124 hashValue = MUTEX_HASH_VALUE(object);
1125 entry = &mutexHashTable[hashValue];
1127 if (entry->object != 0) {
1128 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1130 entry->mutex.holder = 0;
1131 entry->mutex.count = 0;
1132 entry->mutex.muxWaiters = 0;
1135 while (entry->next != 0 && entry->object != object)
1136 entry = entry->next;
1138 if (entry->object != object) {
1139 entry->next = firstFreeOverflowEntry;
1140 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1142 entry = entry->next;
1145 assert(entry->conditionCount == 0);
1150 entry->mutex.holder = 0;
1151 entry->mutex.count = 0;
1152 entry->mutex.muxWaiters = 0;
1155 if (entry->object == 0)
1156 entry->object = object;
1158 internal_lock_mutex(&entry->mutex);
1164 * Unlocks the mutex of an object.
1166 void internal_unlock_mutex_for_object (java_objectheader *object)
1170 mutexHashEntry *entry;
1172 hashValue = MUTEX_HASH_VALUE(object);
1173 entry = &mutexHashTable[hashValue];
1175 if (entry->object == object) {
1176 internal_unlock_mutex(&entry->mutex);
1179 while (entry->next != 0 && entry->next->object != object)
1180 entry = entry->next;
1182 assert(entry->next != 0);
1184 internal_unlock_mutex(&entry->next->mutex);
1186 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1187 mutexHashEntry *unlinked = entry->next;
1189 entry->next = unlinked->next;
1190 unlinked->next = firstFreeOverflowEntry;
1191 firstFreeOverflowEntry = unlinked;
1198 void builtin_monitorenter(java_objectheader *o)
1203 assert(blockInts == 0);
1207 hashValue = MUTEX_HASH_VALUE(o);
1208 if (mutexHashTable[hashValue].object == o
1209 && mutexHashTable[hashValue].mutex.holder == currentThread)
1210 ++mutexHashTable[hashValue].mutex.count;
1212 internal_lock_mutex_for_object(o);
1216 assert(blockInts == 0);
1221 void builtin_monitorexit (java_objectheader *o)
1226 assert(blockInts == 0);
1230 hashValue = MUTEX_HASH_VALUE(o);
1231 if (mutexHashTable[hashValue].object == o) {
1232 if (mutexHashTable[hashValue].mutex.count == 1
1233 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1234 internal_unlock_mutex_for_object(o);
1236 --mutexHashTable[hashValue].mutex.count;
1239 internal_unlock_mutex_for_object(o);
1243 assert(blockInts == 0);
1248 /*****************************************************************************
1249 MISCELLANEOUS HELPER FUNCTIONS
1250 *****************************************************************************/
1254 /*********** Functions for integer divisions *****************************
1256 On some systems (eg. DEC ALPHA), integer division is not supported by the
1257 CPU. These helper functions implement the missing functionality.
1259 ******************************************************************************/
1261 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1262 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1265 /************** Functions for long arithmetics *******************************
1267 On systems where 64 bit Integers are not supported by the CPU, these
1268 functions are needed.
1270 ******************************************************************************/
1273 s8 builtin_ladd(s8 a, s8 b)
1278 return builtin_i2l(0);
1282 s8 builtin_lsub(s8 a, s8 b)
1287 return builtin_i2l(0);
1291 s8 builtin_lmul(s8 a, s8 b)
1296 return builtin_i2l(0);
1300 s8 builtin_ldiv(s8 a, s8 b)
1305 return builtin_i2l(0);
1309 s8 builtin_lrem(s8 a, s8 b)
1314 return builtin_i2l(0);
1318 s8 builtin_lshl(s8 a, s4 b)
1321 return a << (b & 63);
1323 return builtin_i2l(0);
1327 s8 builtin_lshr(s8 a, s4 b)
1330 return a >> (b & 63);
1332 return builtin_i2l(0);
1336 s8 builtin_lushr(s8 a, s4 b)
1339 return ((u8) a) >> (b & 63);
1341 return builtin_i2l(0);
1345 s8 builtin_land(s8 a, s8 b)
1350 return builtin_i2l(0);
1354 s8 builtin_lor(s8 a, s8 b)
1359 return builtin_i2l(0);
1363 s8 builtin_lxor(s8 a, s8 b)
1368 return builtin_i2l(0);
1372 s8 builtin_lneg(s8 a)
1377 return builtin_i2l(0);
1381 s4 builtin_lcmp(s8 a, s8 b)
1384 if (a < b) return -1;
1385 if (a > b) return 1;
1396 /*********** Functions for floating point operations *************************/
1398 float builtin_fadd(float a, float b)
1400 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1401 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1412 if (copysignf(1.0, a) == copysignf(1.0, b))
1415 return intBitsToFloat(FLT_NAN);
1421 float builtin_fsub(float a, float b)
1423 return builtin_fadd(a, builtin_fneg(b));
1427 float builtin_fmul(float a, float b)
1429 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1430 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1432 if (finitef(b)) return a * b;
1434 if (a == 0) return intBitsToFloat(FLT_NAN);
1435 else return copysignf(b, copysignf(1.0, b)*a);
1440 if (b == 0) return intBitsToFloat(FLT_NAN);
1441 else return copysignf(a, copysignf(1.0, a)*b);
1444 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1450 float builtin_fdiv(float a, float b)
1452 if (finitef(a) && finitef(b)) {
1457 return intBitsToFloat(FLT_POSINF);
1459 return intBitsToFloat(FLT_NEGINF);
1462 return intBitsToFloat(FLT_NAN);
1466 float builtin_frem(float a, float b)
1472 float builtin_fneg(float a)
1474 if (isnanf(a)) return a;
1476 if (finitef(a)) return -a;
1477 else return copysignf(a, -copysignf(1.0, a));
1482 s4 builtin_fcmpl(float a, float b)
1484 if (isnanf(a)) return -1;
1485 if (isnanf(b)) return -1;
1486 if (!finitef(a) || !finitef(b)) {
1487 a = finitef(a) ? 0 : copysignf(1.0, a);
1488 b = finitef(b) ? 0 : copysignf(1.0, b);
1490 if (a > b) return 1;
1491 if (a == b) return 0;
1496 s4 builtin_fcmpg(float a, float b)
1498 if (isnanf(a)) return 1;
1499 if (isnanf(b)) return 1;
1500 if (!finitef(a) || !finitef(b)) {
1501 a = finitef(a) ? 0 : copysignf(1.0, a);
1502 b = finitef(b) ? 0 : copysignf(1.0, b);
1504 if (a > b) return 1;
1505 if (a == b) return 0;
1511 /************************* Functions for doubles ****************************/
1513 double builtin_dadd(double a, double b)
1515 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1516 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1518 if (finite(b)) return a + b;
1522 if (finite(b)) return a;
1524 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1525 else return longBitsToDouble(DBL_NAN);
1531 double builtin_dsub(double a, double b)
1533 return builtin_dadd(a, builtin_dneg(b));
1537 double builtin_dmul(double a, double b)
1539 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1540 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1542 if (finite(b)) return a * b;
1544 if (a == 0) return longBitsToDouble(DBL_NAN);
1545 else return copysign(b, copysign(1.0, b) * a);
1550 if (b == 0) return longBitsToDouble(DBL_NAN);
1551 else return copysign(a, copysign(1.0, a) * b);
1554 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1560 double builtin_ddiv(double a, double b)
1568 return longBitsToDouble(DBL_NAN);
1570 return copysign(0.0, b);
1576 return longBitsToDouble(DBL_POSINF);
1578 return longBitsToDouble(DBL_NEGINF);
1581 return longBitsToDouble(DBL_NAN);
1584 /* if (finite(a) && finite(b)) { */
1589 /* return longBitsToDouble(DBL_POSINF); */
1590 /* else if (a < 0) */
1591 /* return longBitsToDouble(DBL_NEGINF); */
1595 /* keep compiler happy */
1600 double builtin_drem(double a, double b)
1606 double builtin_dneg(double a)
1608 if (isnan(a)) return a;
1610 if (finite(a)) return -a;
1611 else return copysign(a, -copysign(1.0, a));
1616 s4 builtin_dcmpl(double a, double b)
1618 if (isnan(a)) return -1;
1619 if (isnan(b)) return -1;
1620 if (!finite(a) || !finite(b)) {
1621 a = finite(a) ? 0 : copysign(1.0, a);
1622 b = finite(b) ? 0 : copysign(1.0, b);
1624 if (a > b) return 1;
1625 if (a == b) return 0;
1630 s4 builtin_dcmpg(double a, double b)
1632 if (isnan(a)) return 1;
1633 if (isnan(b)) return 1;
1634 if (!finite(a) || !finite(b)) {
1635 a = finite(a) ? 0 : copysign(1.0, a);
1636 b = finite(b) ? 0 : copysign(1.0, b);
1638 if (a > b) return 1;
1639 if (a == b) return 0;
1644 /*********************** Conversion operations ****************************/
1646 s8 builtin_i2l(s4 i)
1659 float builtin_i2f(s4 a)
1661 float f = (float) a;
1666 double builtin_i2d(s4 a)
1668 double d = (double) a;
1673 s4 builtin_l2i(s8 l)
1683 float builtin_l2f(s8 a)
1686 float f = (float) a;
1694 double builtin_l2d(s8 a)
1697 double d = (double) a;
1705 s4 builtin_f2i(float a)
1708 return builtin_d2i((double) a);
1717 if (a < (-2147483648))
1718 return (-2147483648);
1721 f = copysignf((float) 1.0, a);
1724 return (-2147483648); */
1728 s8 builtin_f2l(float a)
1731 return builtin_d2l((double) a);
1736 if (a > 9223372036854775807L)
1737 return 9223372036854775807L;
1738 if (a < (-9223372036854775808L))
1739 return (-9223372036854775808L);
1744 f = copysignf((float) 1.0, a);
1746 return 9223372036854775807L;
1747 return (-9223372036854775808L); */
1751 double builtin_f2d(float a)
1753 if (finitef(a)) return (double) a;
1756 return longBitsToDouble(DBL_NAN);
1758 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1763 s4 builtin_d2i(double a)
1768 if (a >= 2147483647)
1770 if (a <= (-2147483647-1))
1771 return (-2147483647-1);
1776 d = copysign(1.0, a);
1779 return (-2147483647-1);
1783 s8 builtin_d2l(double a)
1788 if (a >= 9223372036854775807LL)
1789 return 9223372036854775807LL;
1790 if (a <= (-9223372036854775807LL-1))
1791 return (-9223372036854775807LL-1);
1796 d = copysign(1.0, a);
1798 return 9223372036854775807LL;
1799 return (-9223372036854775807LL-1);
1803 float builtin_d2f(double a)
1809 return intBitsToFloat(FLT_NAN);
1811 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1816 /* used to convert FLT_xxx defines into float values */
1818 inline float intBitsToFloat(s4 i)
1827 /* used to convert DBL_xxx defines into double values */
1829 inline float longBitsToDouble(s8 l)
1838 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1840 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1845 * These are local overrides for various environment variables in Emacs.
1846 * Please do not remove this and leave it at the end of the file, where
1847 * Emacs will automagically detect them.
1848 * ---------------------------------------------------------------------
1851 * indent-tabs-mode: t