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 793 2003-12-16 18:50:39Z 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;
396 /******************* function: builtin_canstore *******************************
398 Checks, if an object can be stored in an array.
399 Return value: 1 ... possible
402 ******************************************************************************/
404 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
406 arraydescriptor *desc;
407 arraydescriptor *valuedesc;
408 vftbl *componentvftbl;
415 /* The following is guaranteed (by verifier checks):
417 * *) a->...vftbl->arraydesc != NULL
418 * *) a->...vftbl->arraydesc->componentvftbl != NULL
419 * *) o->vftbl is not an interface vftbl
422 desc = a->header.objheader.vftbl->arraydesc;
423 componentvftbl = desc->componentvftbl;
424 valuevftbl = o->vftbl;
426 if ((dim_m1 = desc->dimension - 1) == 0) {
429 /* {a is a one-dimensional array} */
430 /* {a is an array of references} */
432 if (valuevftbl == componentvftbl)
435 if ((base = componentvftbl->baseval) <= 0)
436 /* an array of interface references */
437 return (valuevftbl->interfacetablelength > -base &&
438 valuevftbl->interfacetable[base] != NULL);
440 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
444 res = (unsigned)(valuevftbl->baseval - base)
445 <= (unsigned)(componentvftbl->diffval);
447 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
453 /* {a has dimension > 1} */
454 /* {componentvftbl->arraydesc != NULL} */
456 /* check if o is an array */
457 if ((valuedesc = valuevftbl->arraydesc) == NULL)
459 /* {o is an array} */
461 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
465 /* This is an optimized version where a is guaranteed to be one-dimensional */
466 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
468 arraydescriptor *desc;
476 /* The following is guaranteed (by verifier checks):
478 * *) a->...vftbl->arraydesc != NULL
479 * *) a->...vftbl->arraydesc->elementvftbl != NULL
480 * *) a->...vftbl->arraydesc->dimension == 1
481 * *) o->vftbl is not an interface vftbl
484 desc = a->header.objheader.vftbl->arraydesc;
485 elementvftbl = desc->elementvftbl;
486 valuevftbl = o->vftbl;
488 /* {a is a one-dimensional array} */
490 if (valuevftbl == elementvftbl)
493 if ((base = elementvftbl->baseval) <= 0)
494 /* an array of interface references */
495 return (valuevftbl->interfacetablelength > -base &&
496 valuevftbl->interfacetable[base] != NULL);
498 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
502 res = (unsigned)(valuevftbl->baseval - base)
503 <= (unsigned)(elementvftbl->diffval);
505 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
513 /* This is an optimized version where a is guaranteed to be a
514 * one-dimensional array of a class type */
515 /* XXX this could be inlined by the code generator */
516 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
524 /* The following is guaranteed (by verifier checks):
526 * *) a->...vftbl->arraydesc != NULL
527 * *) a->...vftbl->arraydesc->elementvftbl != NULL
528 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
529 * *) a->...vftbl->arraydesc->dimension == 1
530 * *) o->vftbl is not an interface vftbl
533 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
534 valuevftbl = o->vftbl;
536 /* {a is a one-dimensional array} */
538 if (valuevftbl == elementvftbl)
541 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
545 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
546 <= (unsigned)(elementvftbl->diffval);
548 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
556 /******************** Function: builtin_new **********************************
558 Creates a new instance of class c on the heap.
559 Return value: pointer to the object or NULL if no memory is
562 *****************************************************************************/
565 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
567 java_objectheader *builtin_new(classinfo *c)
569 java_objectheader *o;
573 #ifdef SIZE_FROM_CLASSINFO
574 c->alignedsize = align_size(c->instancesize);
575 o = heap_allocate(c->alignedsize, true, c->finalizer);
577 o = heap_allocate(c->instancesize, true, c->finalizer);
581 memset(o, 0, c->instancesize);
588 /********************** Function: builtin_newarray **************************
590 Creates an array with the given vftbl on the heap.
592 Return value: pointer to the array or NULL if no memory is available
594 CAUTION: The given vftbl must be the vftbl of the *array* class,
595 not of the element class.
597 *****************************************************************************/
599 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
602 arraydescriptor *desc = arrayvftbl->arraydesc;
603 s4 dataoffset = desc->dataoffset;
604 s4 componentsize = desc->componentsize;
608 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
611 #ifdef SIZE_FROM_CLASSINFO
612 actualsize = align_size(dataoffset + size * componentsize);
614 actualsize = dataoffset + size * componentsize;
617 if (((u4)actualsize)<((u4)size)) { /* overflow */
618 exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
621 a = heap_allocate(actualsize,
622 (desc->arraytype == ARRAYTYPE_OBJECT),
626 memset(a, 0, actualsize);
629 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
631 a->objheader.vftbl = arrayvftbl;
633 #ifdef SIZE_FROM_CLASSINFO
634 a->alignedsize = actualsize;
641 /********************** Function: builtin_anewarray *************************
643 Creates an array of references to the given class type on the heap.
645 Return value: pointer to the array or NULL if no memory is available
647 XXX This function does not do The Right Thing, because it uses a
648 classinfo pointer at runtime. builtin_newarray should be used
651 *****************************************************************************/
653 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
655 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
659 /******************** Function: builtin_newarray_int ***********************
661 Creates an array of 32 bit Integers on the heap.
663 Return value: pointer to the array or NULL if no memory is available
665 *****************************************************************************/
667 java_intarray *builtin_newarray_int(s4 size)
669 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
673 /******************** Function: builtin_newarray_long ***********************
675 Creates an array of 64 bit Integers on the heap.
677 Return value: pointer to the array or NULL if no memory is available
679 *****************************************************************************/
681 java_longarray *builtin_newarray_long(s4 size)
683 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
687 /******************** function: builtin_newarray_float ***********************
689 Creates an array of 32 bit IEEE floats on the heap.
691 Return value: pointer to the array or NULL if no memory is available
693 *****************************************************************************/
695 java_floatarray *builtin_newarray_float(s4 size)
697 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
701 /******************** function: builtin_newarray_double ***********************
703 Creates an array of 64 bit IEEE floats on the heap.
705 Return value: pointer to the array or NULL if no memory is available
707 *****************************************************************************/
709 java_doublearray *builtin_newarray_double(s4 size)
711 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
715 /******************** function: builtin_newarray_byte ***********************
717 Creates an array of 8 bit Integers on the heap.
719 Return value: pointer to the array or NULL if no memory is available
721 *****************************************************************************/
723 java_bytearray *builtin_newarray_byte(s4 size)
725 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
729 /******************** function: builtin_newarray_char ************************
731 Creates an array of characters on the heap.
733 Return value: pointer to the array or NULL if no memory is available
735 *****************************************************************************/
737 java_chararray *builtin_newarray_char(s4 size)
739 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
743 /******************** function: builtin_newarray_short ***********************
745 Creates an array of 16 bit Integers on the heap.
747 Return value: pointer to the array or NULL if no memory is available
749 *****************************************************************************/
751 java_shortarray *builtin_newarray_short(s4 size)
753 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
757 /******************** function: builtin_newarray_boolean ************************
759 Creates an array of bytes on the heap. The array is designated as an array
760 of booleans (important for casts)
762 Return value: pointer to the array or NULL if no memory is available
764 *****************************************************************************/
766 java_booleanarray *builtin_newarray_boolean(s4 size)
768 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
772 /**************** function: builtin_nmultianewarray ***************************
774 Creates a multi-dimensional array on the heap. The dimensions are passed in
778 n............number of dimensions to create
779 arrayvftbl...vftbl of the array class
780 dims.........array containing the size of each dimension to create
782 Return value: pointer to the array or NULL if no memory is available
784 ******************************************************************************/
786 /* Helper functions */
788 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
792 vftbl *componentvftbl;
794 /* create this dimension */
795 size = (int) dims[0];
796 a = builtin_newarray(size,arrayvftbl);
799 /* if this is the last dimension return */
802 /* get the vftbl of the components to create */
803 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
804 if (!componentvftbl) /* XXX the verifier could check this */
805 panic ("multianewarray with too many dimensions");
807 /* create the component arrays */
808 for (i = 0; i < size; i++) {
809 java_arrayheader *ea =
810 builtin_nmultianewarray(n,componentvftbl,dims+1);
811 if (!ea) return NULL;
812 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
819 /*****************************************************************************
822 Various functions for printing a message at method entry or exit (for
825 *****************************************************************************/
830 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
831 methodinfo *method, int *pos,
838 log_text("WARNING: unmatched methodindent--");
840 if (verbose || runverbose) {
841 printf("Exception ");
843 utf_display (exceptionptr->vftbl->class->name);
846 printf("Error: <Nullpointer instead of exception>");
847 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
848 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
849 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
850 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
851 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
852 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
853 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
854 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
855 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
856 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
859 printf(" thrown in ");
861 utf_display (method->class->name);
863 utf_display (method->name);
864 if (method->flags & ACC_SYNCHRONIZED)
868 printf("(%p) at position %p\n", method->entrypoint, pos);
871 printf("call_java_method\n");
878 #ifdef TRACE_ARGS_NUM
879 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
880 #if TRACE_ARGS_NUM > 6
886 char logtext[MAXLOGTEXT];
887 for (i = 0; i < methodindent; i++)
889 sprintf(logtext + methodindent, "called: ");
890 utf_sprint(logtext + strlen(logtext), method->class->name);
891 sprintf(logtext + strlen(logtext), ".");
892 utf_sprint(logtext + strlen(logtext), method->name);
893 utf_sprint(logtext + strlen(logtext), method->descriptor);
894 sprintf(logtext + strlen(logtext), "(");
896 switch (method->paramcount) {
900 #if defined(__I386__)
902 sprintf(logtext+strlen(logtext), "%llx", a0);
906 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
910 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
914 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
919 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
924 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
925 a0, a1, a2, a3, a4, a5);
928 #if TRACE_ARGS_NUM > 6
930 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
931 a0, a1, a2, a3, a4, a5, a6);
935 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
936 a0, a1, a2, a3, a4, a5, a6, a7);
940 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
941 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
945 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
946 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
951 sprintf(logtext+strlen(logtext), "%lx", a0);
955 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
959 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
963 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
968 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
973 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
974 a0, a1, a2, a3, a4, a5);
977 #if TRACE_ARGS_NUM > 6
979 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
980 a0, a1, a2, a3, a4, a5, a6);
984 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
985 a0, a1, a2, a3, a4, a5, a6, a7);
989 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
990 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
994 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
995 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
1000 sprintf (logtext+strlen(logtext), ")");
1008 void builtin_displaymethodstart(methodinfo *method)
1010 char logtext[MAXLOGTEXT];
1011 sprintf(logtext, " ");
1012 sprintf(logtext + methodindent, "called: ");
1013 utf_sprint(logtext + strlen(logtext), method->class->name);
1014 sprintf(logtext + strlen(logtext), ".");
1015 utf_sprint(logtext + strlen(logtext), method->name);
1016 utf_sprint(logtext + strlen(logtext), method->descriptor);
1022 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1025 char logtext[MAXLOGTEXT];
1026 for (i = 0; i < methodindent; i++)
1031 log_text("WARNING: unmatched methodindent--");
1032 sprintf(logtext + methodindent, "finished: ");
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);
1038 switch (method->returntype) {
1040 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1043 #if defined(__I386__)
1044 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1046 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1050 #if defined(__I386__)
1051 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1053 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1057 sprintf(logtext + strlen(logtext), "->%g", f);
1060 sprintf(logtext + strlen(logtext), "->%g", d);
1067 void builtin_displaymethodexception(methodinfo *method)
1070 char logtext[MAXLOGTEXT];
1071 for (i = 0; i < methodindent; i++)
1073 sprintf(logtext + methodindent, "exception abort: ");
1074 utf_sprint(logtext + strlen(logtext), method->class->name);
1075 sprintf(logtext + strlen(logtext), ".");
1076 utf_sprint(logtext + strlen(logtext), method->name);
1077 utf_sprint(logtext + strlen(logtext), method->descriptor);
1082 /****************************************************************************
1083 SYNCHRONIZATION FUNCTIONS
1084 *****************************************************************************/
1087 * Lock the mutex of an object.
1089 void internal_lock_mutex_for_object(java_objectheader *object)
1092 mutexHashEntry *entry;
1095 assert(object != 0);
1097 hashValue = MUTEX_HASH_VALUE(object);
1098 entry = &mutexHashTable[hashValue];
1100 if (entry->object != 0) {
1101 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1103 entry->mutex.holder = 0;
1104 entry->mutex.count = 0;
1105 entry->mutex.muxWaiters = 0;
1108 while (entry->next != 0 && entry->object != object)
1109 entry = entry->next;
1111 if (entry->object != object) {
1112 entry->next = firstFreeOverflowEntry;
1113 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1115 entry = entry->next;
1118 assert(entry->conditionCount == 0);
1123 entry->mutex.holder = 0;
1124 entry->mutex.count = 0;
1125 entry->mutex.muxWaiters = 0;
1128 if (entry->object == 0)
1129 entry->object = object;
1131 internal_lock_mutex(&entry->mutex);
1137 * Unlocks the mutex of an object.
1139 void internal_unlock_mutex_for_object (java_objectheader *object)
1143 mutexHashEntry *entry;
1145 hashValue = MUTEX_HASH_VALUE(object);
1146 entry = &mutexHashTable[hashValue];
1148 if (entry->object == object) {
1149 internal_unlock_mutex(&entry->mutex);
1152 while (entry->next != 0 && entry->next->object != object)
1153 entry = entry->next;
1155 assert(entry->next != 0);
1157 internal_unlock_mutex(&entry->next->mutex);
1159 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1160 mutexHashEntry *unlinked = entry->next;
1162 entry->next = unlinked->next;
1163 unlinked->next = firstFreeOverflowEntry;
1164 firstFreeOverflowEntry = unlinked;
1171 void builtin_monitorenter(java_objectheader *o)
1176 assert(blockInts == 0);
1180 hashValue = MUTEX_HASH_VALUE(o);
1181 if (mutexHashTable[hashValue].object == o
1182 && mutexHashTable[hashValue].mutex.holder == currentThread)
1183 ++mutexHashTable[hashValue].mutex.count;
1185 internal_lock_mutex_for_object(o);
1189 assert(blockInts == 0);
1194 void builtin_monitorexit (java_objectheader *o)
1199 assert(blockInts == 0);
1203 hashValue = MUTEX_HASH_VALUE(o);
1204 if (mutexHashTable[hashValue].object == o) {
1205 if (mutexHashTable[hashValue].mutex.count == 1
1206 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1207 internal_unlock_mutex_for_object(o);
1209 --mutexHashTable[hashValue].mutex.count;
1212 internal_unlock_mutex_for_object(o);
1216 assert(blockInts == 0);
1221 /*****************************************************************************
1222 MISCELLANEOUS HELPER FUNCTIONS
1223 *****************************************************************************/
1227 /*********** Functions for integer divisions *****************************
1229 On some systems (eg. DEC ALPHA), integer division is not supported by the
1230 CPU. These helper functions implement the missing functionality.
1232 ******************************************************************************/
1234 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1235 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1238 /************** Functions for long arithmetics *******************************
1240 On systems where 64 bit Integers are not supported by the CPU, these
1241 functions are needed.
1243 ******************************************************************************/
1246 s8 builtin_ladd(s8 a, s8 b)
1251 return builtin_i2l(0);
1255 s8 builtin_lsub(s8 a, s8 b)
1260 return builtin_i2l(0);
1264 s8 builtin_lmul(s8 a, s8 b)
1269 return builtin_i2l(0);
1273 s8 builtin_ldiv(s8 a, s8 b)
1278 return builtin_i2l(0);
1282 s8 builtin_lrem(s8 a, s8 b)
1287 return builtin_i2l(0);
1291 s8 builtin_lshl(s8 a, s4 b)
1294 return a << (b & 63);
1296 return builtin_i2l(0);
1300 s8 builtin_lshr(s8 a, s4 b)
1303 return a >> (b & 63);
1305 return builtin_i2l(0);
1309 s8 builtin_lushr(s8 a, s4 b)
1312 return ((u8) a) >> (b & 63);
1314 return builtin_i2l(0);
1318 s8 builtin_land(s8 a, s8 b)
1323 return builtin_i2l(0);
1327 s8 builtin_lor(s8 a, s8 b)
1332 return builtin_i2l(0);
1336 s8 builtin_lxor(s8 a, s8 b)
1341 return builtin_i2l(0);
1345 s8 builtin_lneg(s8 a)
1350 return builtin_i2l(0);
1354 s4 builtin_lcmp(s8 a, s8 b)
1357 if (a < b) return -1;
1358 if (a > b) return 1;
1369 /*********** Functions for floating point operations *************************/
1371 float builtin_fadd(float a, float b)
1373 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1374 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1385 if (copysignf(1.0, a) == copysignf(1.0, b))
1388 return intBitsToFloat(FLT_NAN);
1394 float builtin_fsub(float a, float b)
1396 return builtin_fadd(a, builtin_fneg(b));
1400 float builtin_fmul(float a, float b)
1402 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1403 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1405 if (finitef(b)) return a * b;
1407 if (a == 0) return intBitsToFloat(FLT_NAN);
1408 else return copysignf(b, copysignf(1.0, b)*a);
1413 if (b == 0) return intBitsToFloat(FLT_NAN);
1414 else return copysignf(a, copysignf(1.0, a)*b);
1417 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1423 float builtin_fdiv(float a, float b)
1425 if (finitef(a) && finitef(b)) {
1430 return intBitsToFloat(FLT_POSINF);
1432 return intBitsToFloat(FLT_NEGINF);
1435 return intBitsToFloat(FLT_NAN);
1439 float builtin_frem(float a, float b)
1445 float builtin_fneg(float a)
1447 if (isnanf(a)) return a;
1449 if (finitef(a)) return -a;
1450 else return copysignf(a, -copysignf(1.0, a));
1455 s4 builtin_fcmpl(float a, float b)
1457 if (isnanf(a)) return -1;
1458 if (isnanf(b)) return -1;
1459 if (!finitef(a) || !finitef(b)) {
1460 a = finitef(a) ? 0 : copysignf(1.0, a);
1461 b = finitef(b) ? 0 : copysignf(1.0, b);
1463 if (a > b) return 1;
1464 if (a == b) return 0;
1469 s4 builtin_fcmpg(float a, float b)
1471 if (isnanf(a)) return 1;
1472 if (isnanf(b)) return 1;
1473 if (!finitef(a) || !finitef(b)) {
1474 a = finitef(a) ? 0 : copysignf(1.0, a);
1475 b = finitef(b) ? 0 : copysignf(1.0, b);
1477 if (a > b) return 1;
1478 if (a == b) return 0;
1484 /************************* Functions for doubles ****************************/
1486 double builtin_dadd(double a, double b)
1488 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1489 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1491 if (finite(b)) return a + b;
1495 if (finite(b)) return a;
1497 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1498 else return longBitsToDouble(DBL_NAN);
1504 double builtin_dsub(double a, double b)
1506 return builtin_dadd(a, builtin_dneg(b));
1510 double builtin_dmul(double a, double b)
1512 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1513 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1515 if (finite(b)) return a * b;
1517 if (a == 0) return longBitsToDouble(DBL_NAN);
1518 else return copysign(b, copysign(1.0, b) * a);
1523 if (b == 0) return longBitsToDouble(DBL_NAN);
1524 else return copysign(a, copysign(1.0, a) * b);
1527 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1533 double builtin_ddiv(double a, double b)
1541 return longBitsToDouble(DBL_NAN);
1543 return copysign(0.0, b);
1549 return longBitsToDouble(DBL_POSINF);
1551 return longBitsToDouble(DBL_NEGINF);
1554 return longBitsToDouble(DBL_NAN);
1557 /* if (finite(a) && finite(b)) { */
1562 /* return longBitsToDouble(DBL_POSINF); */
1563 /* else if (a < 0) */
1564 /* return longBitsToDouble(DBL_NEGINF); */
1568 /* keep compiler happy */
1573 double builtin_drem(double a, double b)
1579 double builtin_dneg(double a)
1581 if (isnan(a)) return a;
1583 if (finite(a)) return -a;
1584 else return copysign(a, -copysign(1.0, a));
1589 s4 builtin_dcmpl(double a, double b)
1591 if (isnan(a)) return -1;
1592 if (isnan(b)) return -1;
1593 if (!finite(a) || !finite(b)) {
1594 a = finite(a) ? 0 : copysign(1.0, a);
1595 b = finite(b) ? 0 : copysign(1.0, b);
1597 if (a > b) return 1;
1598 if (a == b) return 0;
1603 s4 builtin_dcmpg(double a, double b)
1605 if (isnan(a)) return 1;
1606 if (isnan(b)) return 1;
1607 if (!finite(a) || !finite(b)) {
1608 a = finite(a) ? 0 : copysign(1.0, a);
1609 b = finite(b) ? 0 : copysign(1.0, b);
1611 if (a > b) return 1;
1612 if (a == b) return 0;
1617 /*********************** Conversion operations ****************************/
1619 s8 builtin_i2l(s4 i)
1632 float builtin_i2f(s4 a)
1634 float f = (float) a;
1639 double builtin_i2d(s4 a)
1641 double d = (double) a;
1646 s4 builtin_l2i(s8 l)
1656 float builtin_l2f(s8 a)
1659 float f = (float) a;
1667 double builtin_l2d(s8 a)
1670 double d = (double) a;
1678 s4 builtin_f2i(float a)
1681 return builtin_d2i((double) a);
1690 if (a < (-2147483648))
1691 return (-2147483648);
1694 f = copysignf((float) 1.0, a);
1697 return (-2147483648); */
1701 s8 builtin_f2l(float a)
1704 return builtin_d2l((double) a);
1709 if (a > 9223372036854775807L)
1710 return 9223372036854775807L;
1711 if (a < (-9223372036854775808L))
1712 return (-9223372036854775808L);
1717 f = copysignf((float) 1.0, a);
1719 return 9223372036854775807L;
1720 return (-9223372036854775808L); */
1724 double builtin_f2d(float a)
1726 if (finitef(a)) return (double) a;
1729 return longBitsToDouble(DBL_NAN);
1731 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1736 s4 builtin_d2i(double a)
1741 if (a >= 2147483647)
1743 if (a <= (-2147483647-1))
1744 return (-2147483647-1);
1749 d = copysign(1.0, a);
1752 return (-2147483647-1);
1756 s8 builtin_d2l(double a)
1761 if (a >= 9223372036854775807LL)
1762 return 9223372036854775807LL;
1763 if (a <= (-9223372036854775807LL-1))
1764 return (-9223372036854775807LL-1);
1769 d = copysign(1.0, a);
1771 return 9223372036854775807LL;
1772 return (-9223372036854775807LL-1);
1776 float builtin_d2f(double a)
1782 return intBitsToFloat(FLT_NAN);
1784 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1789 /* used to convert FLT_xxx defines into float values */
1791 inline float intBitsToFloat(s4 i)
1800 /* used to convert DBL_xxx defines into double values */
1802 inline float longBitsToDouble(s8 l)
1811 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1813 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1818 * These are local overrides for various environment variables in Emacs.
1819 * Please do not remove this and leave it at the end of the file, where
1820 * Emacs will automagically detect them.
1821 * ---------------------------------------------------------------------
1824 * indent-tabs-mode: t