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 868 2004-01-10 20:12:10Z edwin $
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 void builtin_reset_exceptionptr()
397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
399 _exceptionptr = NULL;
401 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
404 panic("builtin_reset_exceptionptr should not be used in this configuration");
409 /******************* function: builtin_canstore *******************************
411 Checks, if an object can be stored in an array.
412 Return value: 1 ... possible
415 ******************************************************************************/
417 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
419 arraydescriptor *desc;
420 arraydescriptor *valuedesc;
421 vftbl *componentvftbl;
428 /* The following is guaranteed (by verifier checks):
430 * *) a->...vftbl->arraydesc != NULL
431 * *) a->...vftbl->arraydesc->componentvftbl != NULL
432 * *) o->vftbl is not an interface vftbl
435 desc = a->header.objheader.vftbl->arraydesc;
436 componentvftbl = desc->componentvftbl;
437 valuevftbl = o->vftbl;
439 if ((dim_m1 = desc->dimension - 1) == 0) {
442 /* {a is a one-dimensional array} */
443 /* {a is an array of references} */
445 if (valuevftbl == componentvftbl)
448 if ((base = componentvftbl->baseval) <= 0)
449 /* an array of interface references */
450 return (valuevftbl->interfacetablelength > -base &&
451 valuevftbl->interfacetable[base] != NULL);
453 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
457 res = (unsigned)(valuevftbl->baseval - base)
458 <= (unsigned)(componentvftbl->diffval);
460 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
466 /* {a has dimension > 1} */
467 /* {componentvftbl->arraydesc != NULL} */
469 /* check if o is an array */
470 if ((valuedesc = valuevftbl->arraydesc) == NULL)
472 /* {o is an array} */
474 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
478 /* This is an optimized version where a is guaranteed to be one-dimensional */
479 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
481 arraydescriptor *desc;
489 /* The following is guaranteed (by verifier checks):
491 * *) a->...vftbl->arraydesc != NULL
492 * *) a->...vftbl->arraydesc->elementvftbl != NULL
493 * *) a->...vftbl->arraydesc->dimension == 1
494 * *) o->vftbl is not an interface vftbl
497 desc = a->header.objheader.vftbl->arraydesc;
498 elementvftbl = desc->elementvftbl;
499 valuevftbl = o->vftbl;
501 /* {a is a one-dimensional array} */
503 if (valuevftbl == elementvftbl)
506 if ((base = elementvftbl->baseval) <= 0)
507 /* an array of interface references */
508 return (valuevftbl->interfacetablelength > -base &&
509 valuevftbl->interfacetable[base] != NULL);
511 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
515 res = (unsigned)(valuevftbl->baseval - base)
516 <= (unsigned)(elementvftbl->diffval);
518 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
526 /* This is an optimized version where a is guaranteed to be a
527 * one-dimensional array of a class type */
528 /* XXX this could be inlined by the code generator */
529 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
537 /* The following is guaranteed (by verifier checks):
539 * *) a->...vftbl->arraydesc != NULL
540 * *) a->...vftbl->arraydesc->elementvftbl != NULL
541 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
542 * *) a->...vftbl->arraydesc->dimension == 1
543 * *) o->vftbl is not an interface vftbl
546 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
547 valuevftbl = o->vftbl;
549 /* {a is a one-dimensional array} */
551 if (valuevftbl == elementvftbl)
554 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
558 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
559 <= (unsigned)(elementvftbl->diffval);
561 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
569 /******************** Function: builtin_new **********************************
571 Creates a new instance of class c on the heap.
572 Return value: pointer to the object or NULL if no memory is
575 *****************************************************************************/
578 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
580 java_objectheader *builtin_new(classinfo *c)
582 java_objectheader *o;
585 char logtext[MAXLOGTEXT];
586 sprintf(logtext, "Initialize class ");
587 utf_sprint(logtext + strlen(logtext), c->name);
588 sprintf(logtext + strlen(logtext), " (from builtin_new)");
593 #ifdef SIZE_FROM_CLASSINFO
594 c->alignedsize = align_size(c->instancesize);
595 o = heap_allocate(c->alignedsize, true, c->finalizer);
597 o = heap_allocate(c->instancesize, true, c->finalizer);
601 memset(o, 0, c->instancesize);
608 /********************** Function: builtin_newarray **************************
610 Creates an array with the given vftbl on the heap.
612 Return value: pointer to the array or NULL if no memory is available
614 CAUTION: The given vftbl must be the vftbl of the *array* class,
615 not of the element class.
617 *****************************************************************************/
619 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
622 arraydescriptor *desc = arrayvftbl->arraydesc;
623 s4 dataoffset = desc->dataoffset;
624 s4 componentsize = desc->componentsize;
628 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
631 #ifdef SIZE_FROM_CLASSINFO
632 actualsize = align_size(dataoffset + size * componentsize);
634 actualsize = dataoffset + size * componentsize;
637 if (((u4)actualsize)<((u4)size)) { /* overflow */
638 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
641 a = heap_allocate(actualsize,
642 (desc->arraytype == ARRAYTYPE_OBJECT),
646 memset(a, 0, actualsize);
649 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
651 a->objheader.vftbl = arrayvftbl;
653 #ifdef SIZE_FROM_CLASSINFO
654 a->alignedsize = actualsize;
661 /********************** Function: builtin_anewarray *************************
663 Creates an array of references to the given class type on the heap.
665 Return value: pointer to the array or NULL if no memory is available
667 XXX This function does not do The Right Thing, because it uses a
668 classinfo pointer at runtime. builtin_newarray should be used
671 *****************************************************************************/
673 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
675 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
679 /******************** Function: builtin_newarray_int ***********************
681 Creates an array of 32 bit Integers on the heap.
683 Return value: pointer to the array or NULL if no memory is available
685 *****************************************************************************/
687 java_intarray *builtin_newarray_int(s4 size)
689 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
693 /******************** Function: builtin_newarray_long ***********************
695 Creates an array of 64 bit Integers on the heap.
697 Return value: pointer to the array or NULL if no memory is available
699 *****************************************************************************/
701 java_longarray *builtin_newarray_long(s4 size)
703 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
707 /******************** function: builtin_newarray_float ***********************
709 Creates an array of 32 bit IEEE floats on the heap.
711 Return value: pointer to the array or NULL if no memory is available
713 *****************************************************************************/
715 java_floatarray *builtin_newarray_float(s4 size)
717 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
721 /******************** function: builtin_newarray_double ***********************
723 Creates an array of 64 bit IEEE floats on the heap.
725 Return value: pointer to the array or NULL if no memory is available
727 *****************************************************************************/
729 java_doublearray *builtin_newarray_double(s4 size)
731 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
735 /******************** function: builtin_newarray_byte ***********************
737 Creates an array of 8 bit Integers on the heap.
739 Return value: pointer to the array or NULL if no memory is available
741 *****************************************************************************/
743 java_bytearray *builtin_newarray_byte(s4 size)
745 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
749 /******************** function: builtin_newarray_char ************************
751 Creates an array of characters on the heap.
753 Return value: pointer to the array or NULL if no memory is available
755 *****************************************************************************/
757 java_chararray *builtin_newarray_char(s4 size)
759 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
763 /******************** function: builtin_newarray_short ***********************
765 Creates an array of 16 bit Integers on the heap.
767 Return value: pointer to the array or NULL if no memory is available
769 *****************************************************************************/
771 java_shortarray *builtin_newarray_short(s4 size)
773 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
777 /******************** function: builtin_newarray_boolean ************************
779 Creates an array of bytes on the heap. The array is designated as an array
780 of booleans (important for casts)
782 Return value: pointer to the array or NULL if no memory is available
784 *****************************************************************************/
786 java_booleanarray *builtin_newarray_boolean(s4 size)
788 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
792 /**************** function: builtin_nmultianewarray ***************************
794 Creates a multi-dimensional array on the heap. The dimensions are passed in
798 n............number of dimensions to create
799 arrayvftbl...vftbl of the array class
800 dims.........array containing the size of each dimension to create
802 Return value: pointer to the array or NULL if no memory is available
804 ******************************************************************************/
806 /* Helper functions */
808 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
812 vftbl *componentvftbl;
814 /* create this dimension */
815 size = (int) dims[0];
816 a = builtin_newarray(size,arrayvftbl);
819 /* if this is the last dimension return */
822 /* get the vftbl of the components to create */
823 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
824 if (!componentvftbl) /* XXX the verifier could check this */
825 panic ("multianewarray with too many dimensions");
827 /* create the component arrays */
828 for (i = 0; i < size; i++) {
829 java_arrayheader *ea =
830 builtin_nmultianewarray(n,componentvftbl,dims+1);
831 if (!ea) return NULL;
832 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
839 /*****************************************************************************
842 Various functions for printing a message at method entry or exit (for
845 *****************************************************************************/
850 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
851 methodinfo *method, int *pos,
858 log_text("WARNING: unmatched methodindent--");
860 if (verbose || runverbose) {
861 printf("Exception ");
863 utf_display (_exceptionptr->vftbl->class->name);
866 printf("Error: <Nullpointer instead of exception>");
867 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
868 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
869 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
870 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
871 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
872 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
873 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
874 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
875 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
876 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
879 printf(" thrown in ");
881 utf_display (method->class->name);
883 utf_display (method->name);
884 if (method->flags & ACC_SYNCHRONIZED)
888 printf("(%p) at position %p\n", method->entrypoint, pos);
891 printf("call_java_method\n");
894 return _exceptionptr;
898 #ifdef TRACE_ARGS_NUM
899 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
900 #if TRACE_ARGS_NUM > 6
906 char logtext[MAXLOGTEXT];
907 for (i = 0; i < methodindent; i++)
909 sprintf(logtext + methodindent, "called: ");
910 utf_sprint(logtext + strlen(logtext), method->class->name);
911 sprintf(logtext + strlen(logtext), ".");
912 utf_sprint(logtext + strlen(logtext), method->name);
913 utf_sprint(logtext + strlen(logtext), method->descriptor);
914 sprintf(logtext + strlen(logtext), "(");
916 switch (method->paramcount) {
920 #if defined(__I386__)
922 sprintf(logtext+strlen(logtext), "%llx", a0);
926 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
930 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
934 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
939 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
944 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
945 a0, a1, a2, a3, a4, a5);
948 #if TRACE_ARGS_NUM > 6
950 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
951 a0, a1, a2, a3, a4, a5, a6);
955 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
956 a0, a1, a2, a3, a4, a5, a6, a7);
960 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
961 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
965 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
966 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
971 sprintf(logtext+strlen(logtext), "%lx", a0);
975 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
979 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
983 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
988 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
993 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
994 a0, a1, a2, a3, a4, a5);
997 #if TRACE_ARGS_NUM > 6
999 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1000 a0, a1, a2, a3, a4, a5, a6);
1004 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1005 a0, a1, a2, a3, a4, a5, a6, a7);
1009 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1010 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
1014 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1015 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
1020 sprintf (logtext+strlen(logtext), ")");
1028 void builtin_displaymethodstart(methodinfo *method)
1030 char logtext[MAXLOGTEXT];
1031 sprintf(logtext, " ");
1032 sprintf(logtext + methodindent, "called: ");
1033 utf_sprint(logtext + strlen(logtext), method->class->name);
1034 sprintf(logtext + strlen(logtext), ".");
1035 utf_sprint(logtext + strlen(logtext), method->name);
1036 utf_sprint(logtext + strlen(logtext), method->descriptor);
1042 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1045 char logtext[MAXLOGTEXT];
1046 for (i = 0; i < methodindent; i++)
1051 log_text("WARNING: unmatched methodindent--");
1052 sprintf(logtext + methodindent, "finished: ");
1053 utf_sprint(logtext + strlen(logtext), method->class->name);
1054 sprintf(logtext + strlen(logtext), ".");
1055 utf_sprint(logtext + strlen(logtext), method->name);
1056 utf_sprint(logtext + strlen(logtext), method->descriptor);
1058 switch (method->returntype) {
1060 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1063 #if defined(__I386__)
1064 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1066 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1070 #if defined(__I386__)
1071 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1073 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1077 sprintf(logtext + strlen(logtext), "->%g", f);
1080 sprintf(logtext + strlen(logtext), "->%g", d);
1087 void builtin_displaymethodexception(methodinfo *method)
1090 char logtext[MAXLOGTEXT];
1091 for (i = 0; i < methodindent; i++)
1093 sprintf(logtext + methodindent, "exception abort: ");
1094 utf_sprint(logtext + strlen(logtext), method->class->name);
1095 sprintf(logtext + strlen(logtext), ".");
1096 utf_sprint(logtext + strlen(logtext), method->name);
1097 utf_sprint(logtext + strlen(logtext), method->descriptor);
1102 /****************************************************************************
1103 SYNCHRONIZATION FUNCTIONS
1104 *****************************************************************************/
1107 * Lock the mutex of an object.
1109 void internal_lock_mutex_for_object(java_objectheader *object)
1112 mutexHashEntry *entry;
1115 assert(object != 0);
1117 hashValue = MUTEX_HASH_VALUE(object);
1118 entry = &mutexHashTable[hashValue];
1120 if (entry->object != 0) {
1121 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1123 entry->mutex.holder = 0;
1124 entry->mutex.count = 0;
1125 entry->mutex.muxWaiters = 0;
1128 while (entry->next != 0 && entry->object != object)
1129 entry = entry->next;
1131 if (entry->object != object) {
1132 entry->next = firstFreeOverflowEntry;
1133 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1135 entry = entry->next;
1138 assert(entry->conditionCount == 0);
1143 entry->mutex.holder = 0;
1144 entry->mutex.count = 0;
1145 entry->mutex.muxWaiters = 0;
1148 if (entry->object == 0)
1149 entry->object = object;
1151 internal_lock_mutex(&entry->mutex);
1157 * Unlocks the mutex of an object.
1159 void internal_unlock_mutex_for_object (java_objectheader *object)
1163 mutexHashEntry *entry;
1165 hashValue = MUTEX_HASH_VALUE(object);
1166 entry = &mutexHashTable[hashValue];
1168 if (entry->object == object) {
1169 internal_unlock_mutex(&entry->mutex);
1172 while (entry->next != 0 && entry->next->object != object)
1173 entry = entry->next;
1175 assert(entry->next != 0);
1177 internal_unlock_mutex(&entry->next->mutex);
1179 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1180 mutexHashEntry *unlinked = entry->next;
1182 entry->next = unlinked->next;
1183 unlinked->next = firstFreeOverflowEntry;
1184 firstFreeOverflowEntry = unlinked;
1191 void builtin_monitorenter(java_objectheader *o)
1196 assert(blockInts == 0);
1200 hashValue = MUTEX_HASH_VALUE(o);
1201 if (mutexHashTable[hashValue].object == o
1202 && mutexHashTable[hashValue].mutex.holder == currentThread)
1203 ++mutexHashTable[hashValue].mutex.count;
1205 internal_lock_mutex_for_object(o);
1209 assert(blockInts == 0);
1214 void builtin_monitorexit (java_objectheader *o)
1219 assert(blockInts == 0);
1223 hashValue = MUTEX_HASH_VALUE(o);
1224 if (mutexHashTable[hashValue].object == o) {
1225 if (mutexHashTable[hashValue].mutex.count == 1
1226 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1227 internal_unlock_mutex_for_object(o);
1229 --mutexHashTable[hashValue].mutex.count;
1232 internal_unlock_mutex_for_object(o);
1236 assert(blockInts == 0);
1241 /*****************************************************************************
1242 MISCELLANEOUS HELPER FUNCTIONS
1243 *****************************************************************************/
1247 /*********** Functions for integer divisions *****************************
1249 On some systems (eg. DEC ALPHA), integer division is not supported by the
1250 CPU. These helper functions implement the missing functionality.
1252 ******************************************************************************/
1254 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1255 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1258 /************** Functions for long arithmetics *******************************
1260 On systems where 64 bit Integers are not supported by the CPU, these
1261 functions are needed.
1263 ******************************************************************************/
1266 s8 builtin_ladd(s8 a, s8 b)
1271 return builtin_i2l(0);
1275 s8 builtin_lsub(s8 a, s8 b)
1280 return builtin_i2l(0);
1284 s8 builtin_lmul(s8 a, s8 b)
1289 return builtin_i2l(0);
1293 s8 builtin_ldiv(s8 a, s8 b)
1298 return builtin_i2l(0);
1302 s8 builtin_lrem(s8 a, s8 b)
1307 return builtin_i2l(0);
1311 s8 builtin_lshl(s8 a, s4 b)
1314 return a << (b & 63);
1316 return builtin_i2l(0);
1320 s8 builtin_lshr(s8 a, s4 b)
1323 return a >> (b & 63);
1325 return builtin_i2l(0);
1329 s8 builtin_lushr(s8 a, s4 b)
1332 return ((u8) a) >> (b & 63);
1334 return builtin_i2l(0);
1338 s8 builtin_land(s8 a, s8 b)
1343 return builtin_i2l(0);
1347 s8 builtin_lor(s8 a, s8 b)
1352 return builtin_i2l(0);
1356 s8 builtin_lxor(s8 a, s8 b)
1361 return builtin_i2l(0);
1365 s8 builtin_lneg(s8 a)
1370 return builtin_i2l(0);
1374 s4 builtin_lcmp(s8 a, s8 b)
1377 if (a < b) return -1;
1378 if (a > b) return 1;
1389 /*********** Functions for floating point operations *************************/
1391 float builtin_fadd(float a, float b)
1393 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1394 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1405 if (copysignf(1.0, a) == copysignf(1.0, b))
1408 return intBitsToFloat(FLT_NAN);
1414 float builtin_fsub(float a, float b)
1416 return builtin_fadd(a, builtin_fneg(b));
1420 float builtin_fmul(float a, float b)
1422 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1423 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1425 if (finitef(b)) return a * b;
1427 if (a == 0) return intBitsToFloat(FLT_NAN);
1428 else return copysignf(b, copysignf(1.0, b)*a);
1433 if (b == 0) return intBitsToFloat(FLT_NAN);
1434 else return copysignf(a, copysignf(1.0, a)*b);
1437 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1443 float builtin_fdiv(float a, float b)
1445 if (finitef(a) && finitef(b)) {
1450 return intBitsToFloat(FLT_POSINF);
1452 return intBitsToFloat(FLT_NEGINF);
1455 return intBitsToFloat(FLT_NAN);
1459 float builtin_frem(float a, float b)
1465 float builtin_fneg(float a)
1467 if (isnanf(a)) return a;
1469 if (finitef(a)) return -a;
1470 else return copysignf(a, -copysignf(1.0, a));
1475 s4 builtin_fcmpl(float a, float b)
1477 if (isnanf(a)) return -1;
1478 if (isnanf(b)) return -1;
1479 if (!finitef(a) || !finitef(b)) {
1480 a = finitef(a) ? 0 : copysignf(1.0, a);
1481 b = finitef(b) ? 0 : copysignf(1.0, b);
1483 if (a > b) return 1;
1484 if (a == b) return 0;
1489 s4 builtin_fcmpg(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;
1504 /************************* Functions for doubles ****************************/
1506 double builtin_dadd(double a, double b)
1508 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1509 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1511 if (finite(b)) return a + b;
1515 if (finite(b)) return a;
1517 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1518 else return longBitsToDouble(DBL_NAN);
1524 double builtin_dsub(double a, double b)
1526 return builtin_dadd(a, builtin_dneg(b));
1530 double builtin_dmul(double a, double b)
1532 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1533 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1535 if (finite(b)) return a * b;
1537 if (a == 0) return longBitsToDouble(DBL_NAN);
1538 else return copysign(b, copysign(1.0, b) * a);
1543 if (b == 0) return longBitsToDouble(DBL_NAN);
1544 else return copysign(a, copysign(1.0, a) * b);
1547 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1553 double builtin_ddiv(double a, double b)
1561 return longBitsToDouble(DBL_NAN);
1563 return copysign(0.0, b);
1569 return longBitsToDouble(DBL_POSINF);
1571 return longBitsToDouble(DBL_NEGINF);
1574 return longBitsToDouble(DBL_NAN);
1577 /* if (finite(a) && finite(b)) { */
1582 /* return longBitsToDouble(DBL_POSINF); */
1583 /* else if (a < 0) */
1584 /* return longBitsToDouble(DBL_NEGINF); */
1588 /* keep compiler happy */
1593 double builtin_drem(double a, double b)
1599 double builtin_dneg(double a)
1601 if (isnan(a)) return a;
1603 if (finite(a)) return -a;
1604 else return copysign(a, -copysign(1.0, a));
1609 s4 builtin_dcmpl(double a, double b)
1611 if (isnan(a)) return -1;
1612 if (isnan(b)) return -1;
1613 if (!finite(a) || !finite(b)) {
1614 a = finite(a) ? 0 : copysign(1.0, a);
1615 b = finite(b) ? 0 : copysign(1.0, b);
1617 if (a > b) return 1;
1618 if (a == b) return 0;
1623 s4 builtin_dcmpg(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 /*********************** Conversion operations ****************************/
1639 s8 builtin_i2l(s4 i)
1652 float builtin_i2f(s4 a)
1654 float f = (float) a;
1659 double builtin_i2d(s4 a)
1661 double d = (double) a;
1666 s4 builtin_l2i(s8 l)
1676 float builtin_l2f(s8 a)
1679 float f = (float) a;
1687 double builtin_l2d(s8 a)
1690 double d = (double) a;
1698 s4 builtin_f2i(float a)
1701 return builtin_d2i((double) a);
1710 if (a < (-2147483648))
1711 return (-2147483648);
1714 f = copysignf((float) 1.0, a);
1717 return (-2147483648); */
1721 s8 builtin_f2l(float a)
1724 return builtin_d2l((double) a);
1729 if (a > 9223372036854775807L)
1730 return 9223372036854775807L;
1731 if (a < (-9223372036854775808L))
1732 return (-9223372036854775808L);
1737 f = copysignf((float) 1.0, a);
1739 return 9223372036854775807L;
1740 return (-9223372036854775808L); */
1744 double builtin_f2d(float a)
1746 if (finitef(a)) return (double) a;
1749 return longBitsToDouble(DBL_NAN);
1751 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1756 s4 builtin_d2i(double a)
1761 if (a >= 2147483647)
1763 if (a <= (-2147483647-1))
1764 return (-2147483647-1);
1769 d = copysign(1.0, a);
1772 return (-2147483647-1);
1776 s8 builtin_d2l(double a)
1781 if (a >= 9223372036854775807LL)
1782 return 9223372036854775807LL;
1783 if (a <= (-9223372036854775807LL-1))
1784 return (-9223372036854775807LL-1);
1789 d = copysign(1.0, a);
1791 return 9223372036854775807LL;
1792 return (-9223372036854775807LL-1);
1796 float builtin_d2f(double a)
1802 return intBitsToFloat(FLT_NAN);
1804 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1809 /* used to convert FLT_xxx defines into float values */
1811 inline float intBitsToFloat(s4 i)
1820 /* used to convert DBL_xxx defines into double values */
1822 inline float longBitsToDouble(s8 l)
1831 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1833 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1838 panic("Internal error: builtin_dummy called (native function is missing)");
1839 return 0; /* for the compiler */
1844 * These are local overrides for various environment variables in Emacs.
1845 * Please do not remove this and leave it at the end of the file, where
1846 * Emacs will automagically detect them.
1847 * ---------------------------------------------------------------------
1850 * indent-tabs-mode: t