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 781 2003-12-15 15:24:44Z twisti $
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "toolbox/loging.h"
55 #include "toolbox/memory.h"
56 #include "nat/java_lang_Cloneable.h"
57 #include "nat/java_lang_VMObject.h"
60 #undef DEBUG /*define DEBUG 1*/
64 builtin_descriptor builtin_desc[] = {
65 {(functionptr) builtin_instanceof, "instanceof"},
66 {(functionptr) builtin_checkcast, "checkcast"},
67 {(functionptr) asm_builtin_checkcast, "checkcast"},
68 {(functionptr) builtin_arrayinstanceof, "arrayinstanceof"},
70 {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
72 {(functionptr) builtin_checkarraycast, "checkarraycast"},
73 {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
74 {(functionptr) asm_builtin_aastore, "aastore"},
75 {(functionptr) builtin_new, "new"},
76 {(functionptr) builtin_newarray, "newarray"},
77 {(functionptr) builtin_anewarray, "anewarray"},
80 * have 2 parameters (needs stack manipulation)
82 {(functionptr) asm_builtin_newarray, "newarray"},
84 {(functionptr) builtin_newarray_boolean, "newarray_boolean"},
85 {(functionptr) builtin_newarray_char, "newarray_char"},
86 {(functionptr) builtin_newarray_float, "newarray_float"},
87 {(functionptr) builtin_newarray_double, "newarray_double"},
88 {(functionptr) builtin_newarray_byte, "newarray_byte"},
89 {(functionptr) builtin_newarray_short, "newarray_short"},
90 {(functionptr) builtin_newarray_int, "newarray_int"},
91 {(functionptr) builtin_newarray_long, "newarray_long"},
92 {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
93 {(functionptr) builtin_displaymethodstop, "displaymethodstop"},
94 {(functionptr) builtin_monitorenter, "monitorenter"},
95 {(functionptr) asm_builtin_monitorenter, "monitorenter"},
96 {(functionptr) builtin_monitorexit, "monitorexit"},
97 {(functionptr) asm_builtin_monitorexit, "monitorexit"},
99 {(functionptr) builtin_idiv, "idiv"},
100 {(functionptr) asm_builtin_idiv, "idiv"},
101 {(functionptr) builtin_irem, "irem"},
102 {(functionptr) asm_builtin_irem, "irem"},
104 {(functionptr) builtin_ladd, "ladd"},
105 {(functionptr) builtin_lsub, "lsub"},
106 {(functionptr) builtin_lmul, "lmul"},
107 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
108 {(functionptr) builtin_ldiv, "ldiv"},
109 {(functionptr) asm_builtin_ldiv, "ldiv"},
110 {(functionptr) builtin_lrem, "lrem"},
111 {(functionptr) asm_builtin_lrem, "lrem"},
113 {(functionptr) builtin_lshl, "lshl"},
114 {(functionptr) builtin_lshr, "lshr"},
115 {(functionptr) builtin_lushr, "lushr"},
116 {(functionptr) builtin_land, "land"},
117 {(functionptr) builtin_lor, "lor"},
118 {(functionptr) builtin_lxor, "lxor"},
119 {(functionptr) builtin_lneg, "lneg"},
120 {(functionptr) builtin_lcmp, "lcmp"},
121 {(functionptr) builtin_fadd, "fadd"},
122 {(functionptr) builtin_fsub, "fsub"},
123 {(functionptr) builtin_fmul, "fmul"},
124 {(functionptr) builtin_fdiv, "fdiv"},
125 {(functionptr) builtin_frem, "frem"},
126 {(functionptr) builtin_fneg, "fneg"},
127 {(functionptr) builtin_fcmpl, "fcmpl"},
128 {(functionptr) builtin_fcmpg, "fcmpg"},
129 {(functionptr) builtin_dadd, "dadd"},
130 {(functionptr) builtin_dsub, "dsub"},
131 {(functionptr) builtin_dmul, "dmul"},
132 {(functionptr) builtin_ddiv, "ddiv"},
133 {(functionptr) builtin_drem, "drem"},
134 {(functionptr) builtin_dneg, "dneg"},
135 {(functionptr) builtin_dcmpl, "dcmpl"},
136 {(functionptr) builtin_dcmpg, "dcmpg"},
137 {(functionptr) builtin_i2l, "i2l"},
138 {(functionptr) builtin_i2f, "i2f"},
139 {(functionptr) builtin_i2d, "i2d"},
140 {(functionptr) builtin_l2i, "l2i"},
141 {(functionptr) builtin_l2f, "l2f"},
142 {(functionptr) builtin_l2d, "l2d"},
143 {(functionptr) builtin_f2i, "f2i"},
144 {(functionptr) builtin_f2l, "f2l"},
145 {(functionptr) builtin_f2d, "f2d"},
146 {(functionptr) builtin_d2i, "d2i"},
147 {(functionptr) builtin_d2l, "d2l"},
148 #if defined(__I386__)
149 {(functionptr) asm_builtin_f2i, "f2i"},
150 {(functionptr) asm_builtin_f2l, "f2l"},
151 {(functionptr) asm_builtin_d2i, "d2i"},
152 {(functionptr) asm_builtin_d2l, "d2l"},
154 {(functionptr) builtin_d2f, "d2f"},
155 {(functionptr) NULL, "unknown"}
160 /*****************************************************************************
162 *****************************************************************************/
166 /*************** internal function: builtin_isanysubclass *********************
168 Checks a subclass relation between two classes. Implemented interfaces
169 are interpreted as super classes.
170 Return value: 1 ... sub is subclass of super
173 *****************************************************************************/
174 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
179 if (super->flags & ACC_INTERFACE)
180 return (sub->vftbl->interfacetablelength > super->index) &&
181 (sub->vftbl->interfacetable[-super->index] != NULL);
194 for (tmp=sub;tmp!=0;tmp=tmp->super) {
196 utf_display(tmp->name);
200 for (tmp=super;tmp!=0;tmp=tmp->super) {
202 utf_display(tmp->name);
207 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
208 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
209 super->vftbl->diffval); */
211 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
215 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
216 (unsigned) (super->vftbl->diffval);
218 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
225 /* XXX inline this? */
226 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
231 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
235 if ((base = super->baseval) <= 0)
236 /* super is an interface */
237 res = (sub->interfacetablelength > -base) &&
238 (sub->interfacetable[base] != NULL);
240 res = (unsigned) (sub->baseval - base)
241 <= (unsigned) (super->diffval);
243 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
251 /****************** function: builtin_instanceof *****************************
253 Checks if an object is an instance of some given class (or subclass of
254 that class). If class is an interface, checks if the interface is
256 Return value: 1 ... obj is an instance of class or implements the interface
257 0 ... otherwise or if obj == NULL
259 *****************************************************************************/
261 /* XXX should use vftbl */
262 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
265 log_text ("builtin_instanceof called");
268 return builtin_isanysubclass (obj->vftbl->class, class);
273 /**************** function: builtin_checkcast *******************************
275 The same as builtin_instanceof except that 1 is returned when
278 ****************************************************************************/
280 /* XXX should use vftbl */
281 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
284 log_text("builtin_checkcast called");
289 if (builtin_isanysubclass(obj->vftbl->class, class))
293 printf("#### checkcast failed ");
294 utf_display(obj->vftbl->class->name);
296 utf_display(class->name);
304 /*********** internal function: builtin_descriptorscompatible ******************
306 Checks if two array type descriptors are assignment compatible
307 Return value: 1 ... target = desc is possible
310 ******************************************************************************/
312 /* XXX inline this? */
313 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
315 if (desc==target) return 1;
316 if (desc->arraytype != target->arraytype) return 0;
317 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
319 /* {both arrays are arrays of references} */
320 if (desc->dimension == target->dimension)
321 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
322 if (desc->dimension < target->dimension) return 0;
324 /* {desc has higher dimension than target} */
325 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
329 /******************** function: builtin_checkarraycast ***********************
331 Checks if an object is really a subtype of the requested array type.
332 The object has to be an array to begin with. For simple arrays (int, short,
333 double, etc.) the types have to match exactly.
334 For arrays of objects, the type of elements in the array has to be a
335 subtype (or the same type) of the requested element type. For arrays of
336 arrays (which in turn can again be arrays of arrays), the types at the
337 lowest level have to satisfy the corresponding sub class relation.
339 Return value: 1 ... cast is possible
342 ATTENTION: a cast with a NULL pointer is always possible.
344 *****************************************************************************/
346 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
348 arraydescriptor *desc;
351 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
353 return builtin_descriptorscompatible(desc, target->arraydesc);
357 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
360 return builtin_checkarraycast(obj, target);
364 /************************** exception functions *******************************
366 ******************************************************************************/
368 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
371 char logtext[MAXLOGTEXT];
372 sprintf(logtext, "Builtin exception thrown: ");
373 if (local_exceptionptr)
374 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
376 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
377 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
378 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
379 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
380 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
381 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
382 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
383 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
384 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
385 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
386 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
390 exceptionptr = local_exceptionptr;
391 return local_exceptionptr;
395 /******************* function: builtin_canstore *******************************
397 Checks, if an object can be stored in an array.
398 Return value: 1 ... possible
401 ******************************************************************************/
403 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
405 arraydescriptor *desc;
406 arraydescriptor *valuedesc;
407 vftbl *componentvftbl;
414 /* The following is guaranteed (by verifier checks):
416 * *) a->...vftbl->arraydesc != NULL
417 * *) a->...vftbl->arraydesc->componentvftbl != NULL
418 * *) o->vftbl is not an interface vftbl
421 desc = a->header.objheader.vftbl->arraydesc;
422 componentvftbl = desc->componentvftbl;
423 valuevftbl = o->vftbl;
425 if ((dim_m1 = desc->dimension - 1) == 0) {
428 /* {a is a one-dimensional array} */
429 /* {a is an array of references} */
431 if (valuevftbl == componentvftbl)
434 if ((base = componentvftbl->baseval) <= 0)
435 /* an array of interface references */
436 return (valuevftbl->interfacetablelength > -base &&
437 valuevftbl->interfacetable[base] != NULL);
439 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
443 res = (unsigned)(valuevftbl->baseval - base)
444 <= (unsigned)(componentvftbl->diffval);
446 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
452 /* {a has dimension > 1} */
453 /* {componentvftbl->arraydesc != NULL} */
455 /* check if o is an array */
456 if ((valuedesc = valuevftbl->arraydesc) == NULL)
458 /* {o is an array} */
460 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
464 /* This is an optimized version where a is guaranteed to be one-dimensional */
465 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
467 arraydescriptor *desc;
475 /* The following is guaranteed (by verifier checks):
477 * *) a->...vftbl->arraydesc != NULL
478 * *) a->...vftbl->arraydesc->elementvftbl != NULL
479 * *) a->...vftbl->arraydesc->dimension == 1
480 * *) o->vftbl is not an interface vftbl
483 desc = a->header.objheader.vftbl->arraydesc;
484 elementvftbl = desc->elementvftbl;
485 valuevftbl = o->vftbl;
487 /* {a is a one-dimensional array} */
489 if (valuevftbl == elementvftbl)
492 if ((base = elementvftbl->baseval) <= 0)
493 /* an array of interface references */
494 return (valuevftbl->interfacetablelength > -base &&
495 valuevftbl->interfacetable[base] != NULL);
497 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
501 res = (unsigned)(valuevftbl->baseval - base)
502 <= (unsigned)(elementvftbl->diffval);
504 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
512 /* This is an optimized version where a is guaranteed to be a
513 * one-dimensional array of a class type */
514 /* XXX this could be inlined by the code generator */
515 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
523 /* The following is guaranteed (by verifier checks):
525 * *) a->...vftbl->arraydesc != NULL
526 * *) a->...vftbl->arraydesc->elementvftbl != NULL
527 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
528 * *) a->...vftbl->arraydesc->dimension == 1
529 * *) o->vftbl is not an interface vftbl
532 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
533 valuevftbl = o->vftbl;
535 /* {a is a one-dimensional array} */
537 if (valuevftbl == elementvftbl)
540 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
544 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
545 <= (unsigned)(elementvftbl->diffval);
547 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
555 /******************** Function: builtin_new **********************************
557 Creates a new instance of class c on the heap.
558 Return value: pointer to the object or NULL if no memory is
561 *****************************************************************************/
564 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
566 java_objectheader *builtin_new(classinfo *c)
568 java_objectheader *o;
572 #ifdef SIZE_FROM_CLASSINFO
573 c->alignedsize = align_size(c->instancesize);
574 o = heap_allocate(c->alignedsize, true, c->finalizer);
576 o = heap_allocate(c->instancesize, true, c->finalizer);
580 memset(o, 0, c->instancesize);
587 /********************** Function: builtin_newarray **************************
589 Creates an array with the given vftbl on the heap.
591 Return value: pointer to the array or NULL if no memory is available
593 CAUTION: The given vftbl must be the vftbl of the *array* class,
594 not of the element class.
596 *****************************************************************************/
598 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
601 arraydescriptor *desc = arrayvftbl->arraydesc;
602 s4 dataoffset = desc->dataoffset;
603 s4 componentsize = desc->componentsize;
607 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
610 #ifdef SIZE_FROM_CLASSINFO
611 actualsize = align_size(dataoffset + size * componentsize);
613 actualsize = dataoffset + size * componentsize;
616 if (((u4)actualsize)<((u4)size)) { /* overflow */
617 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
620 a = (java_arrayheader *) heap_allocate(actualsize,
621 (desc->arraytype == ARRAYTYPE_OBJECT),
624 memset(a,0,actualsize);
627 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
629 a->objheader.vftbl = arrayvftbl;
631 #ifdef SIZE_FROM_CLASSINFO
632 a->alignedsize = actualsize;
639 /********************** Function: builtin_anewarray *************************
641 Creates an array of references to the given class type on the heap.
643 Return value: pointer to the array or NULL if no memory is available
645 XXX This function does not do The Right Thing, because it uses a
646 classinfo pointer at runtime. builtin_newarray should be used
649 *****************************************************************************/
651 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
653 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
657 /******************** Function: builtin_newarray_int ***********************
659 Creates an array of 32 bit Integers on the heap.
661 Return value: pointer to the array or NULL if no memory is available
663 *****************************************************************************/
665 java_intarray *builtin_newarray_int(s4 size)
667 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
671 /******************** Function: builtin_newarray_long ***********************
673 Creates an array of 64 bit Integers on the heap.
675 Return value: pointer to the array or NULL if no memory is available
677 *****************************************************************************/
679 java_longarray *builtin_newarray_long(s4 size)
681 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
685 /******************** function: builtin_newarray_float ***********************
687 Creates an array of 32 bit IEEE floats on the heap.
689 Return value: pointer to the array or NULL if no memory is available
691 *****************************************************************************/
693 java_floatarray *builtin_newarray_float(s4 size)
695 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
699 /******************** function: builtin_newarray_double ***********************
701 Creates an array of 64 bit IEEE floats on the heap.
703 Return value: pointer to the array or NULL if no memory is available
705 *****************************************************************************/
707 java_doublearray *builtin_newarray_double(s4 size)
709 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
713 /******************** function: builtin_newarray_byte ***********************
715 Creates an array of 8 bit Integers on the heap.
717 Return value: pointer to the array or NULL if no memory is available
719 *****************************************************************************/
721 java_bytearray *builtin_newarray_byte(s4 size)
723 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
727 /******************** function: builtin_newarray_char ************************
729 Creates an array of characters on the heap.
731 Return value: pointer to the array or NULL if no memory is available
733 *****************************************************************************/
735 java_chararray *builtin_newarray_char(s4 size)
737 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
741 /******************** function: builtin_newarray_short ***********************
743 Creates an array of 16 bit Integers on the heap.
745 Return value: pointer to the array or NULL if no memory is available
747 *****************************************************************************/
749 java_shortarray *builtin_newarray_short(s4 size)
751 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
755 /******************** function: builtin_newarray_boolean ************************
757 Creates an array of bytes on the heap. The array is designated as an array
758 of booleans (important for casts)
760 Return value: pointer to the array or NULL if no memory is available
762 *****************************************************************************/
764 java_booleanarray *builtin_newarray_boolean(s4 size)
766 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
770 /**************** function: builtin_nmultianewarray ***************************
772 Creates a multi-dimensional array on the heap. The dimensions are passed in
776 n............number of dimensions to create
777 arrayvftbl...vftbl of the array class
778 dims.........array containing the size of each dimension to create
780 Return value: pointer to the array or NULL if no memory is available
782 ******************************************************************************/
784 /* Helper functions */
786 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
790 vftbl *componentvftbl;
792 /* create this dimension */
793 size = (int) dims[0];
794 a = builtin_newarray(size,arrayvftbl);
797 /* if this is the last dimension return */
800 /* get the vftbl of the components to create */
801 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
802 if (!componentvftbl) /* XXX the verifier could check this */
803 panic ("multianewarray with too many dimensions");
805 /* create the component arrays */
806 for (i = 0; i < size; i++) {
807 java_arrayheader *ea =
808 builtin_nmultianewarray(n,componentvftbl,dims+1);
809 if (!ea) return NULL;
810 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
817 /*****************************************************************************
820 Various functions for printing a message at method entry or exit (for
823 *****************************************************************************/
828 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
829 methodinfo *method, int *pos,
834 if (verbose || runverbose) {
835 printf("Exception ");
837 utf_display (exceptionptr->vftbl->class->name);
840 printf("Error: <Nullpointer instead of exception>");
841 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
842 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
843 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
844 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
845 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
846 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
847 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
848 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
849 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
850 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
853 printf(" thrown in ");
855 utf_display (method->class->name);
857 utf_display (method->name);
858 if (method->flags & ACC_SYNCHRONIZED)
862 printf("(%p) at position %p\n", method->entrypoint, pos);
865 printf("call_java_method\n");
872 #ifdef TRACE_ARGS_NUM
873 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
874 #if TRACE_ARGS_NUM > 6
880 char logtext[MAXLOGTEXT];
881 for (i = 0; i < methodindent; i++)
883 sprintf(logtext + methodindent, "called: ");
884 utf_sprint(logtext + strlen(logtext), method->class->name);
885 sprintf(logtext + strlen(logtext), ".");
886 utf_sprint(logtext + strlen(logtext), method->name);
887 utf_sprint(logtext + strlen(logtext), method->descriptor);
888 sprintf(logtext + strlen(logtext), "(");
890 switch (method->paramcount) {
894 #if defined(__I386__)
896 sprintf(logtext+strlen(logtext), "%llx", a0);
900 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
904 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
908 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
913 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
918 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
919 a0, a1, a2, a3, a4, a5);
922 #if TRACE_ARGS_NUM > 6
924 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
925 a0, a1, a2, a3, a4, a5, a6);
929 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
930 a0, a1, a2, a3, a4, a5, a6, a7);
934 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
935 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
939 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
940 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
945 sprintf(logtext+strlen(logtext), "%lx", a0);
949 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
953 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
957 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
962 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
967 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
968 a0, a1, a2, a3, a4, a5);
971 #if TRACE_ARGS_NUM > 6
973 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
974 a0, a1, a2, a3, a4, a5, a6);
978 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
979 a0, a1, a2, a3, a4, a5, a6, a7);
983 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
984 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
988 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
989 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
994 sprintf (logtext+strlen(logtext), ")");
1002 void builtin_displaymethodstart(methodinfo *method)
1004 char logtext[MAXLOGTEXT];
1005 sprintf(logtext, " ");
1006 sprintf(logtext + methodindent, "called: ");
1007 utf_sprint(logtext + strlen(logtext), method->class->name);
1008 sprintf(logtext + strlen(logtext), ".");
1009 utf_sprint(logtext + strlen(logtext), method->name);
1010 utf_sprint(logtext + strlen(logtext), method->descriptor);
1016 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1019 char logtext[MAXLOGTEXT];
1020 for (i = 0; i < methodindent; i++)
1023 sprintf(logtext + methodindent, "finished: ");
1024 utf_sprint(logtext + strlen(logtext), method->class->name);
1025 sprintf(logtext + strlen(logtext), ".");
1026 utf_sprint(logtext + strlen(logtext), method->name);
1027 utf_sprint(logtext + strlen(logtext), method->descriptor);
1029 switch (method->returntype) {
1031 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1034 #if defined(__I386__)
1035 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1037 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1041 #if defined(__I386__)
1042 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1044 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1048 sprintf(logtext + strlen(logtext), "->%g", f);
1051 sprintf(logtext + strlen(logtext), "->%g", d);
1058 void builtin_displaymethodexception(methodinfo *method)
1061 char logtext[MAXLOGTEXT];
1062 for (i = 0; i < methodindent; i++)
1064 sprintf(logtext + methodindent, "exception abort: ");
1065 utf_sprint(logtext + strlen(logtext), method->class->name);
1066 sprintf(logtext + strlen(logtext), ".");
1067 utf_sprint(logtext + strlen(logtext), method->name);
1068 utf_sprint(logtext + strlen(logtext), method->descriptor);
1073 /****************************************************************************
1074 SYNCHRONIZATION FUNCTIONS
1075 *****************************************************************************/
1078 * Lock the mutex of an object.
1080 void internal_lock_mutex_for_object(java_objectheader *object)
1083 mutexHashEntry *entry;
1086 assert(object != 0);
1088 hashValue = MUTEX_HASH_VALUE(object);
1089 entry = &mutexHashTable[hashValue];
1091 if (entry->object != 0) {
1092 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1094 entry->mutex.holder = 0;
1095 entry->mutex.count = 0;
1096 entry->mutex.muxWaiters = 0;
1099 while (entry->next != 0 && entry->object != object)
1100 entry = entry->next;
1102 if (entry->object != object) {
1103 entry->next = firstFreeOverflowEntry;
1104 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1106 entry = entry->next;
1109 assert(entry->conditionCount == 0);
1114 entry->mutex.holder = 0;
1115 entry->mutex.count = 0;
1116 entry->mutex.muxWaiters = 0;
1119 if (entry->object == 0)
1120 entry->object = object;
1122 internal_lock_mutex(&entry->mutex);
1128 * Unlocks the mutex of an object.
1130 void internal_unlock_mutex_for_object (java_objectheader *object)
1134 mutexHashEntry *entry;
1136 hashValue = MUTEX_HASH_VALUE(object);
1137 entry = &mutexHashTable[hashValue];
1139 if (entry->object == object) {
1140 internal_unlock_mutex(&entry->mutex);
1143 while (entry->next != 0 && entry->next->object != object)
1144 entry = entry->next;
1146 assert(entry->next != 0);
1148 internal_unlock_mutex(&entry->next->mutex);
1150 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1151 mutexHashEntry *unlinked = entry->next;
1153 entry->next = unlinked->next;
1154 unlinked->next = firstFreeOverflowEntry;
1155 firstFreeOverflowEntry = unlinked;
1162 void builtin_monitorenter(java_objectheader *o)
1167 assert(blockInts == 0);
1171 hashValue = MUTEX_HASH_VALUE(o);
1172 if (mutexHashTable[hashValue].object == o
1173 && mutexHashTable[hashValue].mutex.holder == currentThread)
1174 ++mutexHashTable[hashValue].mutex.count;
1176 internal_lock_mutex_for_object(o);
1180 assert(blockInts == 0);
1185 void builtin_monitorexit (java_objectheader *o)
1190 assert(blockInts == 0);
1194 hashValue = MUTEX_HASH_VALUE(o);
1195 if (mutexHashTable[hashValue].object == o) {
1196 if (mutexHashTable[hashValue].mutex.count == 1
1197 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1198 internal_unlock_mutex_for_object(o);
1200 --mutexHashTable[hashValue].mutex.count;
1203 internal_unlock_mutex_for_object(o);
1207 assert(blockInts == 0);
1212 /*****************************************************************************
1213 MISCELLANEOUS HELPER FUNCTIONS
1214 *****************************************************************************/
1218 /*********** Functions for integer divisions *****************************
1220 On some systems (eg. DEC ALPHA), integer division is not supported by the
1221 CPU. These helper functions implement the missing functionality.
1223 ******************************************************************************/
1225 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1226 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1229 /************** Functions for long arithmetics *******************************
1231 On systems where 64 bit Integers are not supported by the CPU, these
1232 functions are needed.
1234 ******************************************************************************/
1237 s8 builtin_ladd(s8 a, s8 b)
1242 return builtin_i2l(0);
1246 s8 builtin_lsub(s8 a, s8 b)
1251 return builtin_i2l(0);
1255 s8 builtin_lmul(s8 a, s8 b)
1260 return builtin_i2l(0);
1264 s8 builtin_ldiv(s8 a, s8 b)
1269 return builtin_i2l(0);
1273 s8 builtin_lrem(s8 a, s8 b)
1278 return builtin_i2l(0);
1282 s8 builtin_lshl(s8 a, s4 b)
1285 return a << (b & 63);
1287 return builtin_i2l(0);
1291 s8 builtin_lshr(s8 a, s4 b)
1294 return a >> (b & 63);
1296 return builtin_i2l(0);
1300 s8 builtin_lushr(s8 a, s4 b)
1303 return ((u8) a) >> (b & 63);
1305 return builtin_i2l(0);
1309 s8 builtin_land(s8 a, s8 b)
1314 return builtin_i2l(0);
1318 s8 builtin_lor(s8 a, s8 b)
1323 return builtin_i2l(0);
1327 s8 builtin_lxor(s8 a, s8 b)
1332 return builtin_i2l(0);
1336 s8 builtin_lneg(s8 a)
1341 return builtin_i2l(0);
1345 s4 builtin_lcmp(s8 a, s8 b)
1348 if (a < b) return -1;
1349 if (a > b) return 1;
1360 /*********** Functions for floating point operations *************************/
1362 float builtin_fadd(float a, float b)
1364 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1365 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1376 if (copysignf(1.0, a) == copysignf(1.0, b))
1379 return intBitsToFloat(FLT_NAN);
1385 float builtin_fsub(float a, float b)
1387 return builtin_fadd(a, builtin_fneg(b));
1391 float builtin_fmul(float a, float b)
1393 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1394 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1396 if (finitef(b)) return a * b;
1398 if (a == 0) return intBitsToFloat(FLT_NAN);
1399 else return copysignf(b, copysignf(1.0, b)*a);
1404 if (b == 0) return intBitsToFloat(FLT_NAN);
1405 else return copysignf(a, copysignf(1.0, a)*b);
1408 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1414 float builtin_fdiv(float a, float b)
1416 if (finitef(a) && finitef(b)) {
1421 return intBitsToFloat(FLT_POSINF);
1423 return intBitsToFloat(FLT_NEGINF);
1426 return intBitsToFloat(FLT_NAN);
1430 float builtin_frem(float a, float b)
1436 float builtin_fneg(float a)
1438 if (isnanf(a)) return a;
1440 if (finitef(a)) return -a;
1441 else return copysignf(a, -copysignf(1.0, a));
1446 s4 builtin_fcmpl(float a, float b)
1448 if (isnanf(a)) return -1;
1449 if (isnanf(b)) return -1;
1450 if (!finitef(a) || !finitef(b)) {
1451 a = finitef(a) ? 0 : copysignf(1.0, a);
1452 b = finitef(b) ? 0 : copysignf(1.0, b);
1454 if (a > b) return 1;
1455 if (a == b) return 0;
1460 s4 builtin_fcmpg(float a, float b)
1462 if (isnanf(a)) return 1;
1463 if (isnanf(b)) return 1;
1464 if (!finitef(a) || !finitef(b)) {
1465 a = finitef(a) ? 0 : copysignf(1.0, a);
1466 b = finitef(b) ? 0 : copysignf(1.0, b);
1468 if (a > b) return 1;
1469 if (a == b) return 0;
1475 /************************* Functions for doubles ****************************/
1477 double builtin_dadd(double a, double b)
1479 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1480 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1482 if (finite(b)) return a + b;
1486 if (finite(b)) return a;
1488 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1489 else return longBitsToDouble(DBL_NAN);
1495 double builtin_dsub(double a, double b)
1497 return builtin_dadd(a, builtin_dneg(b));
1501 double builtin_dmul(double a, double b)
1503 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1504 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1506 if (finite(b)) return a * b;
1508 if (a == 0) return longBitsToDouble(DBL_NAN);
1509 else return copysign(b, copysign(1.0, b) * a);
1514 if (b == 0) return longBitsToDouble(DBL_NAN);
1515 else return copysign(a, copysign(1.0, a) * b);
1518 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1524 double builtin_ddiv(double a, double b)
1532 return longBitsToDouble(DBL_NAN);
1534 return copysign(0.0, b);
1540 return longBitsToDouble(DBL_POSINF);
1542 return longBitsToDouble(DBL_NEGINF);
1545 return longBitsToDouble(DBL_NAN);
1548 /* if (finite(a) && finite(b)) { */
1553 /* return longBitsToDouble(DBL_POSINF); */
1554 /* else if (a < 0) */
1555 /* return longBitsToDouble(DBL_NEGINF); */
1559 /* keep compiler happy */
1564 double builtin_drem(double a, double b)
1570 double builtin_dneg(double a)
1572 if (isnan(a)) return a;
1574 if (finite(a)) return -a;
1575 else return copysign(a, -copysign(1.0, a));
1580 s4 builtin_dcmpl(double a, double b)
1582 if (isnan(a)) return -1;
1583 if (isnan(b)) return -1;
1584 if (!finite(a) || !finite(b)) {
1585 a = finite(a) ? 0 : copysign(1.0, a);
1586 b = finite(b) ? 0 : copysign(1.0, b);
1588 if (a > b) return 1;
1589 if (a == b) return 0;
1594 s4 builtin_dcmpg(double a, double b)
1596 if (isnan(a)) return 1;
1597 if (isnan(b)) return 1;
1598 if (!finite(a) || !finite(b)) {
1599 a = finite(a) ? 0 : copysign(1.0, a);
1600 b = finite(b) ? 0 : copysign(1.0, b);
1602 if (a > b) return 1;
1603 if (a == b) return 0;
1608 /*********************** Conversion operations ****************************/
1610 s8 builtin_i2l(s4 i)
1623 float builtin_i2f(s4 a)
1625 float f = (float) a;
1630 double builtin_i2d(s4 a)
1632 double d = (double) a;
1637 s4 builtin_l2i(s8 l)
1647 float builtin_l2f(s8 a)
1650 float f = (float) a;
1658 double builtin_l2d(s8 a)
1661 double d = (double) a;
1669 s4 builtin_f2i(float a)
1672 return builtin_d2i((double) a);
1681 if (a < (-2147483648))
1682 return (-2147483648);
1685 f = copysignf((float) 1.0, a);
1688 return (-2147483648); */
1692 s8 builtin_f2l(float a)
1695 return builtin_d2l((double) a);
1700 if (a > 9223372036854775807L)
1701 return 9223372036854775807L;
1702 if (a < (-9223372036854775808L))
1703 return (-9223372036854775808L);
1708 f = copysignf((float) 1.0, a);
1710 return 9223372036854775807L;
1711 return (-9223372036854775808L); */
1715 double builtin_f2d(float a)
1717 if (finitef(a)) return (double) a;
1720 return longBitsToDouble(DBL_NAN);
1722 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1727 s4 builtin_d2i(double a)
1732 if (a >= 2147483647)
1734 if (a <= (-2147483647-1))
1735 return (-2147483647-1);
1740 d = copysign(1.0, a);
1743 return (-2147483647-1);
1747 s8 builtin_d2l(double a)
1752 if (a >= 9223372036854775807LL)
1753 return 9223372036854775807LL;
1754 if (a <= (-9223372036854775807LL-1))
1755 return (-9223372036854775807LL-1);
1760 d = copysign(1.0, a);
1762 return 9223372036854775807LL;
1763 return (-9223372036854775807LL-1);
1767 float builtin_d2f(double a)
1773 return intBitsToFloat(FLT_NAN);
1775 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1780 /* used to convert FLT_xxx defines into float values */
1782 inline float intBitsToFloat(s4 i)
1791 /* used to convert DBL_xxx defines into double values */
1793 inline float longBitsToDouble(s8 l)
1802 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1804 return Java_java_lang_VMObject_clone(0, 0, o);
1809 * These are local overrides for various environment variables in Emacs.
1810 * Please do not remove this and leave it at the end of the file, where
1811 * Emacs will automagically detect them.
1812 * ---------------------------------------------------------------------
1815 * indent-tabs-mode: t