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 907 2004-01-29 13:20:05Z carolyn $
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*/
64 /*****************************************************************************
66 *****************************************************************************/
70 /*************** internal function: builtin_isanysubclass *********************
72 Checks a subclass relation between two classes. Implemented interfaces
73 are interpreted as super classes.
74 Return value: 1 ... sub is subclass of super
77 *****************************************************************************/
78 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
83 if (super->flags & ACC_INTERFACE)
84 return (sub->vftbl->interfacetablelength > super->index) &&
85 (sub->vftbl->interfacetable[-super->index] != NULL);
98 for (tmp=sub;tmp!=0;tmp=tmp->super) {
100 utf_display(tmp->name);
104 for (tmp=super;tmp!=0;tmp=tmp->super) {
106 utf_display(tmp->name);
111 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
112 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
113 super->vftbl->diffval); */
115 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
119 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
120 (unsigned) (super->vftbl->diffval);
122 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
129 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
138 if ((base = super->baseval) <= 0)
139 /* super is an interface */
140 res = (sub->interfacetablelength > -base) &&
141 (sub->interfacetable[base] != NULL);
143 res = (unsigned) (sub->baseval - base)
144 <= (unsigned) (super->diffval);
146 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
154 /****************** function: builtin_instanceof *****************************
156 Checks if an object is an instance of some given class (or subclass of
157 that class). If class is an interface, checks if the interface is
159 Return value: 1 ... obj is an instance of class or implements the interface
160 0 ... otherwise or if obj == NULL
162 *****************************************************************************/
164 /* XXX should use vftbl */
165 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
168 log_text ("builtin_instanceof called");
171 return builtin_isanysubclass (obj->vftbl->class, class);
176 /**************** function: builtin_checkcast *******************************
178 The same as builtin_instanceof except that 1 is returned when
181 ****************************************************************************/
183 /* XXX should use vftbl */
184 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
187 log_text("builtin_checkcast called");
192 if (builtin_isanysubclass(obj->vftbl->class, class))
196 printf("#### checkcast failed ");
197 utf_display(obj->vftbl->class->name);
199 utf_display(class->name);
207 /*********** internal function: builtin_descriptorscompatible ******************
209 Checks if two array type descriptors are assignment compatible
210 Return value: 1 ... target = desc is possible
213 ******************************************************************************/
215 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
217 if (desc==target) return 1;
218 if (desc->arraytype != target->arraytype) return 0;
219 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
221 /* {both arrays are arrays of references} */
222 if (desc->dimension == target->dimension)
223 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
224 if (desc->dimension < target->dimension) return 0;
226 /* {desc has higher dimension than target} */
227 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
231 /******************** function: builtin_checkarraycast ***********************
233 Checks if an object is really a subtype of the requested array type.
234 The object has to be an array to begin with. For simple arrays (int, short,
235 double, etc.) the types have to match exactly.
236 For arrays of objects, the type of elements in the array has to be a
237 subtype (or the same type) of the requested element type. For arrays of
238 arrays (which in turn can again be arrays of arrays), the types at the
239 lowest level have to satisfy the corresponding sub class relation.
241 Return value: 1 ... cast is possible
244 ATTENTION: a cast with a NULL pointer is always possible.
246 *****************************************************************************/
248 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
250 arraydescriptor *desc;
253 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
255 return builtin_descriptorscompatible(desc, target->arraydesc);
259 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
262 return builtin_checkarraycast(obj, target);
266 /************************** exception functions *******************************
268 ******************************************************************************/
270 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
273 char logtext[MAXLOGTEXT];
274 sprintf(logtext, "Builtin exception thrown: ");
275 if (local_exceptionptr)
276 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
278 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
279 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
280 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
281 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
282 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
283 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
284 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
285 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
286 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
287 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
288 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
292 *exceptionptr = local_exceptionptr;
293 return local_exceptionptr;
296 void builtin_reset_exceptionptr()
298 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
300 _exceptionptr = NULL;
302 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
305 panic("builtin_reset_exceptionptr should not be used in this configuration");
310 /******************* function: builtin_canstore *******************************
312 Checks, if an object can be stored in an array.
313 Return value: 1 ... possible
316 ******************************************************************************/
318 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
320 arraydescriptor *desc;
321 arraydescriptor *valuedesc;
322 vftbl *componentvftbl;
329 /* The following is guaranteed (by verifier checks):
331 * *) a->...vftbl->arraydesc != NULL
332 * *) a->...vftbl->arraydesc->componentvftbl != NULL
333 * *) o->vftbl is not an interface vftbl
336 desc = a->header.objheader.vftbl->arraydesc;
337 componentvftbl = desc->componentvftbl;
338 valuevftbl = o->vftbl;
340 if ((dim_m1 = desc->dimension - 1) == 0) {
343 /* {a is a one-dimensional array} */
344 /* {a is an array of references} */
346 if (valuevftbl == componentvftbl)
349 if ((base = componentvftbl->baseval) <= 0)
350 /* an array of interface references */
351 return (valuevftbl->interfacetablelength > -base &&
352 valuevftbl->interfacetable[base] != NULL);
354 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
358 res = (unsigned)(valuevftbl->baseval - base)
359 <= (unsigned)(componentvftbl->diffval);
361 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
367 /* {a has dimension > 1} */
368 /* {componentvftbl->arraydesc != NULL} */
370 /* check if o is an array */
371 if ((valuedesc = valuevftbl->arraydesc) == NULL)
373 /* {o is an array} */
375 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
379 /* This is an optimized version where a is guaranteed to be one-dimensional */
380 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
382 arraydescriptor *desc;
390 /* The following is guaranteed (by verifier checks):
392 * *) a->...vftbl->arraydesc != NULL
393 * *) a->...vftbl->arraydesc->elementvftbl != NULL
394 * *) a->...vftbl->arraydesc->dimension == 1
395 * *) o->vftbl is not an interface vftbl
398 desc = a->header.objheader.vftbl->arraydesc;
399 elementvftbl = desc->elementvftbl;
400 valuevftbl = o->vftbl;
402 /* {a is a one-dimensional array} */
404 if (valuevftbl == elementvftbl)
407 if ((base = elementvftbl->baseval) <= 0)
408 /* an array of interface references */
409 return (valuevftbl->interfacetablelength > -base &&
410 valuevftbl->interfacetable[base] != NULL);
412 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
416 res = (unsigned)(valuevftbl->baseval - base)
417 <= (unsigned)(elementvftbl->diffval);
419 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
427 /* This is an optimized version where a is guaranteed to be a
428 * one-dimensional array of a class type */
429 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
437 /* The following is guaranteed (by verifier checks):
439 * *) a->...vftbl->arraydesc != NULL
440 * *) a->...vftbl->arraydesc->elementvftbl != NULL
441 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
442 * *) a->...vftbl->arraydesc->dimension == 1
443 * *) o->vftbl is not an interface vftbl
446 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
447 valuevftbl = o->vftbl;
449 /* {a is a one-dimensional array} */
451 if (valuevftbl == elementvftbl)
454 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
458 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
459 <= (unsigned)(elementvftbl->diffval);
461 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
469 /******************** Function: builtin_new **********************************
471 Creates a new instance of class c on the heap.
472 Return value: pointer to the object or NULL if no memory is
475 *****************************************************************************/
478 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
480 java_objectheader *builtin_new(classinfo *c)
482 java_objectheader *o;
485 char logtext[MAXLOGTEXT];
486 sprintf(logtext, "Initialize class ");
487 utf_sprint(logtext + strlen(logtext), c->name);
488 sprintf(logtext + strlen(logtext), " (from builtin_new)");
493 #ifdef SIZE_FROM_CLASSINFO
494 c->alignedsize = align_size(c->instancesize);
495 o = heap_allocate(c->alignedsize, true, c->finalizer);
497 o = heap_allocate(c->instancesize, true, c->finalizer);
501 memset(o, 0, c->instancesize);
508 /********************** Function: builtin_newarray **************************
510 Creates an array with the given vftbl on the heap.
512 Return value: pointer to the array or NULL if no memory is available
514 CAUTION: The given vftbl must be the vftbl of the *array* class,
515 not of the element class.
517 *****************************************************************************/
519 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
522 arraydescriptor *desc = arrayvftbl->arraydesc;
523 s4 dataoffset = desc->dataoffset;
524 s4 componentsize = desc->componentsize;
528 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
531 #ifdef SIZE_FROM_CLASSINFO
532 actualsize = align_size(dataoffset + size * componentsize);
534 actualsize = dataoffset + size * componentsize;
537 if (((u4)actualsize)<((u4)size)) { /* overflow */
538 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
541 a = heap_allocate(actualsize,
542 (desc->arraytype == ARRAYTYPE_OBJECT),
546 memset(a, 0, actualsize);
549 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
551 a->objheader.vftbl = arrayvftbl;
553 #ifdef SIZE_FROM_CLASSINFO
554 a->alignedsize = actualsize;
561 /********************** Function: builtin_anewarray *************************
563 Creates an array of references to the given class type on the heap.
565 Return value: pointer to the array or NULL if no memory is available
567 XXX This function does not do The Right Thing, because it uses a
568 classinfo pointer at runtime. builtin_newarray should be used
571 *****************************************************************************/
573 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
575 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
579 /******************** Function: builtin_newarray_int ***********************
581 Creates an array of 32 bit Integers on the heap.
583 Return value: pointer to the array or NULL if no memory is available
585 *****************************************************************************/
587 java_intarray *builtin_newarray_int(s4 size)
589 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
593 /******************** Function: builtin_newarray_long ***********************
595 Creates an array of 64 bit Integers on the heap.
597 Return value: pointer to the array or NULL if no memory is available
599 *****************************************************************************/
601 java_longarray *builtin_newarray_long(s4 size)
603 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
607 /******************** function: builtin_newarray_float ***********************
609 Creates an array of 32 bit IEEE floats on the heap.
611 Return value: pointer to the array or NULL if no memory is available
613 *****************************************************************************/
615 java_floatarray *builtin_newarray_float(s4 size)
617 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
621 /******************** function: builtin_newarray_double ***********************
623 Creates an array of 64 bit IEEE floats on the heap.
625 Return value: pointer to the array or NULL if no memory is available
627 *****************************************************************************/
629 java_doublearray *builtin_newarray_double(s4 size)
631 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
635 /******************** function: builtin_newarray_byte ***********************
637 Creates an array of 8 bit Integers on the heap.
639 Return value: pointer to the array or NULL if no memory is available
641 *****************************************************************************/
643 java_bytearray *builtin_newarray_byte(s4 size)
645 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
649 /******************** function: builtin_newarray_char ************************
651 Creates an array of characters on the heap.
653 Return value: pointer to the array or NULL if no memory is available
655 *****************************************************************************/
657 java_chararray *builtin_newarray_char(s4 size)
659 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
663 /******************** function: builtin_newarray_short ***********************
665 Creates an array of 16 bit Integers on the heap.
667 Return value: pointer to the array or NULL if no memory is available
669 *****************************************************************************/
671 java_shortarray *builtin_newarray_short(s4 size)
673 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
677 /******************** function: builtin_newarray_boolean ************************
679 Creates an array of bytes on the heap. The array is designated as an array
680 of booleans (important for casts)
682 Return value: pointer to the array or NULL if no memory is available
684 *****************************************************************************/
686 java_booleanarray *builtin_newarray_boolean(s4 size)
688 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
692 /**************** function: builtin_nmultianewarray ***************************
694 Creates a multi-dimensional array on the heap. The dimensions are passed in
698 n............number of dimensions to create
699 arrayvftbl...vftbl of the array class
700 dims.........array containing the size of each dimension to create
702 Return value: pointer to the array or NULL if no memory is available
704 ******************************************************************************/
706 /* Helper functions */
708 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
712 vftbl *componentvftbl;
714 /* create this dimension */
715 size = (int) dims[0];
716 a = builtin_newarray(size,arrayvftbl);
719 /* if this is the last dimension return */
722 /* get the vftbl of the components to create */
723 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
725 /* The verifier guarantees this. */
726 /* if (!componentvftbl) */
727 /* panic ("multianewarray with too many dimensions"); */
729 /* create the component arrays */
730 for (i = 0; i < size; i++) {
731 java_arrayheader *ea =
732 builtin_nmultianewarray(n,componentvftbl,dims+1);
733 if (!ea) return NULL;
734 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
741 /*****************************************************************************
744 Various functions for printing a message at method entry or exit (for
747 *****************************************************************************/
752 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
753 methodinfo *method, int *pos,
760 log_text("WARNING: unmatched methodindent--");
762 if (verbose || runverbose) {
763 printf("Exception ");
765 utf_display (_exceptionptr->vftbl->class->name);
768 printf("Error: <Nullpointer instead of exception>");
769 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
770 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
771 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
772 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
773 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
774 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
775 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
776 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
777 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
778 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
781 printf(" thrown in ");
783 utf_display (method->class->name);
785 utf_display (method->name);
786 if (method->flags & ACC_SYNCHRONIZED)
790 printf("(%p) at position %p\n", method->entrypoint, pos);
793 printf("call_java_method\n");
796 return _exceptionptr;
800 #ifdef TRACE_ARGS_NUM
801 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
802 #if TRACE_ARGS_NUM > 6
808 char logtext[MAXLOGTEXT];
809 for (i = 0; i < methodindent; i++)
811 sprintf(logtext + methodindent, "called: ");
812 utf_sprint(logtext + strlen(logtext), method->class->name);
813 sprintf(logtext + strlen(logtext), ".");
814 utf_sprint(logtext + strlen(logtext), method->name);
815 utf_sprint(logtext + strlen(logtext), method->descriptor);
817 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
818 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
819 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
820 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
821 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
822 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
823 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
824 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
825 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
826 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
827 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
830 sprintf(logtext + strlen(logtext), "(");
832 switch (method->paramcount) {
836 #if defined(__I386__)
838 sprintf(logtext+strlen(logtext), "%llx", a0);
842 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
846 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
850 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
855 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
860 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
861 a0, a1, a2, a3, a4, a5);
864 #if TRACE_ARGS_NUM > 6
866 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
867 a0, a1, a2, a3, a4, a5, a6);
871 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
872 a0, a1, a2, a3, a4, a5, a6, a7);
876 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
877 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
881 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
882 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
887 sprintf(logtext+strlen(logtext), "%lx", a0);
891 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
895 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
899 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
904 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
909 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
910 a0, a1, a2, a3, a4, a5);
913 #if TRACE_ARGS_NUM > 6
915 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
916 a0, a1, a2, a3, a4, a5, a6);
920 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
921 a0, a1, a2, a3, a4, a5, a6, a7);
925 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
926 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
930 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
931 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
936 sprintf (logtext+strlen(logtext), ")");
944 void builtin_displaymethodstart(methodinfo *method)
946 char logtext[MAXLOGTEXT];
947 sprintf(logtext, " ");
948 sprintf(logtext + methodindent, "called: ");
949 utf_sprint(logtext + strlen(logtext), method->class->name);
950 sprintf(logtext + strlen(logtext), ".");
951 utf_sprint(logtext + strlen(logtext), method->name);
952 utf_sprint(logtext + strlen(logtext), method->descriptor);
954 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
955 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
956 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
957 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
958 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
959 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
960 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
961 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
962 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
963 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
964 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
971 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
974 char logtext[MAXLOGTEXT];
975 for (i = 0; i < methodindent; i++)
980 log_text("WARNING: unmatched methodindent--");
981 sprintf(logtext + methodindent, "finished: ");
982 utf_sprint(logtext + strlen(logtext), method->class->name);
983 sprintf(logtext + strlen(logtext), ".");
984 utf_sprint(logtext + strlen(logtext), method->name);
985 utf_sprint(logtext + strlen(logtext), method->descriptor);
987 switch (method->returntype) {
989 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
992 #if defined(__I386__)
993 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
995 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
999 #if defined(__I386__)
1000 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1002 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1006 sprintf(logtext + strlen(logtext), "->%g", f);
1009 sprintf(logtext + strlen(logtext), "->%g", d);
1016 void builtin_displaymethodexception(methodinfo *method)
1019 char logtext[MAXLOGTEXT];
1020 for (i = 0; i < methodindent; i++)
1022 sprintf(logtext + methodindent, "exception abort: ");
1023 utf_sprint(logtext + strlen(logtext), method->class->name);
1024 sprintf(logtext + strlen(logtext), ".");
1025 utf_sprint(logtext + strlen(logtext), method->name);
1026 utf_sprint(logtext + strlen(logtext), method->descriptor);
1031 /****************************************************************************
1032 SYNCHRONIZATION FUNCTIONS
1033 *****************************************************************************/
1036 * Lock the mutex of an object.
1038 void internal_lock_mutex_for_object(java_objectheader *object)
1040 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1041 mutexHashEntry *entry;
1044 assert(object != 0);
1046 hashValue = MUTEX_HASH_VALUE(object);
1047 entry = &mutexHashTable[hashValue];
1049 if (entry->object != 0) {
1050 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1052 entry->mutex.holder = 0;
1053 entry->mutex.count = 0;
1054 entry->mutex.muxWaiters = 0;
1057 while (entry->next != 0 && entry->object != object)
1058 entry = entry->next;
1060 if (entry->object != object) {
1061 entry->next = firstFreeOverflowEntry;
1062 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1064 entry = entry->next;
1067 assert(entry->conditionCount == 0);
1072 entry->mutex.holder = 0;
1073 entry->mutex.count = 0;
1074 entry->mutex.muxWaiters = 0;
1077 if (entry->object == 0)
1078 entry->object = object;
1080 internal_lock_mutex(&entry->mutex);
1086 * Unlocks the mutex of an object.
1088 void internal_unlock_mutex_for_object (java_objectheader *object)
1090 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1092 mutexHashEntry *entry;
1094 hashValue = MUTEX_HASH_VALUE(object);
1095 entry = &mutexHashTable[hashValue];
1097 if (entry->object == object) {
1098 internal_unlock_mutex(&entry->mutex);
1101 while (entry->next != 0 && entry->next->object != object)
1102 entry = entry->next;
1104 assert(entry->next != 0);
1106 internal_unlock_mutex(&entry->next->mutex);
1108 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1109 mutexHashEntry *unlinked = entry->next;
1111 entry->next = unlinked->next;
1112 unlinked->next = firstFreeOverflowEntry;
1113 firstFreeOverflowEntry = unlinked;
1120 void builtin_monitorenter(java_objectheader *o)
1122 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1125 assert(blockInts == 0);
1129 hashValue = MUTEX_HASH_VALUE(o);
1130 if (mutexHashTable[hashValue].object == o
1131 && mutexHashTable[hashValue].mutex.holder == currentThread)
1132 ++mutexHashTable[hashValue].mutex.count;
1134 internal_lock_mutex_for_object(o);
1138 assert(blockInts == 0);
1143 void builtin_monitorexit (java_objectheader *o)
1145 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1148 assert(blockInts == 0);
1152 hashValue = MUTEX_HASH_VALUE(o);
1153 if (mutexHashTable[hashValue].object == o) {
1154 if (mutexHashTable[hashValue].mutex.count == 1
1155 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1156 internal_unlock_mutex_for_object(o);
1158 --mutexHashTable[hashValue].mutex.count;
1161 internal_unlock_mutex_for_object(o);
1165 assert(blockInts == 0);
1170 /*****************************************************************************
1171 MISCELLANEOUS HELPER FUNCTIONS
1172 *****************************************************************************/
1176 /*********** Functions for integer divisions *****************************
1178 On some systems (eg. DEC ALPHA), integer division is not supported by the
1179 CPU. These helper functions implement the missing functionality.
1181 ******************************************************************************/
1183 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1184 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1187 /************** Functions for long arithmetics *******************************
1189 On systems where 64 bit Integers are not supported by the CPU, these
1190 functions are needed.
1192 ******************************************************************************/
1195 s8 builtin_ladd(s8 a, s8 b)
1200 return builtin_i2l(0);
1204 s8 builtin_lsub(s8 a, s8 b)
1209 return builtin_i2l(0);
1213 s8 builtin_lmul(s8 a, s8 b)
1218 return builtin_i2l(0);
1222 s8 builtin_ldiv(s8 a, s8 b)
1227 return builtin_i2l(0);
1231 s8 builtin_lrem(s8 a, s8 b)
1236 return builtin_i2l(0);
1240 s8 builtin_lshl(s8 a, s4 b)
1243 return a << (b & 63);
1245 return builtin_i2l(0);
1249 s8 builtin_lshr(s8 a, s4 b)
1252 return a >> (b & 63);
1254 return builtin_i2l(0);
1258 s8 builtin_lushr(s8 a, s4 b)
1261 return ((u8) a) >> (b & 63);
1263 return builtin_i2l(0);
1267 s8 builtin_land(s8 a, s8 b)
1272 return builtin_i2l(0);
1276 s8 builtin_lor(s8 a, s8 b)
1281 return builtin_i2l(0);
1285 s8 builtin_lxor(s8 a, s8 b)
1290 return builtin_i2l(0);
1294 s8 builtin_lneg(s8 a)
1299 return builtin_i2l(0);
1303 s4 builtin_lcmp(s8 a, s8 b)
1306 if (a < b) return -1;
1307 if (a > b) return 1;
1318 /*********** Functions for floating point operations *************************/
1320 float builtin_fadd(float a, float b)
1322 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1323 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1334 if (copysignf(1.0, a) == copysignf(1.0, b))
1337 return intBitsToFloat(FLT_NAN);
1343 float builtin_fsub(float a, float b)
1345 return builtin_fadd(a, builtin_fneg(b));
1349 float builtin_fmul(float a, float b)
1351 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1352 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1354 if (finitef(b)) return a * b;
1356 if (a == 0) return intBitsToFloat(FLT_NAN);
1357 else return copysignf(b, copysignf(1.0, b)*a);
1362 if (b == 0) return intBitsToFloat(FLT_NAN);
1363 else return copysignf(a, copysignf(1.0, a)*b);
1366 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1372 float builtin_fdiv(float a, float b)
1374 if (finitef(a) && finitef(b)) {
1379 return intBitsToFloat(FLT_POSINF);
1381 return intBitsToFloat(FLT_NEGINF);
1384 return intBitsToFloat(FLT_NAN);
1388 float builtin_frem(float a, float b)
1394 float builtin_fneg(float a)
1396 if (isnanf(a)) return a;
1398 if (finitef(a)) return -a;
1399 else return copysignf(a, -copysignf(1.0, a));
1404 s4 builtin_fcmpl(float a, float b)
1406 if (isnanf(a)) return -1;
1407 if (isnanf(b)) return -1;
1408 if (!finitef(a) || !finitef(b)) {
1409 a = finitef(a) ? 0 : copysignf(1.0, a);
1410 b = finitef(b) ? 0 : copysignf(1.0, b);
1412 if (a > b) return 1;
1413 if (a == b) return 0;
1418 s4 builtin_fcmpg(float a, float b)
1420 if (isnanf(a)) return 1;
1421 if (isnanf(b)) return 1;
1422 if (!finitef(a) || !finitef(b)) {
1423 a = finitef(a) ? 0 : copysignf(1.0, a);
1424 b = finitef(b) ? 0 : copysignf(1.0, b);
1426 if (a > b) return 1;
1427 if (a == b) return 0;
1433 /************************* Functions for doubles ****************************/
1435 double builtin_dadd(double a, double b)
1437 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1438 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1440 if (finite(b)) return a + b;
1444 if (finite(b)) return a;
1446 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1447 else return longBitsToDouble(DBL_NAN);
1453 double builtin_dsub(double a, double b)
1455 return builtin_dadd(a, builtin_dneg(b));
1459 double builtin_dmul(double a, double b)
1461 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1462 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1464 if (finite(b)) return a * b;
1466 if (a == 0) return longBitsToDouble(DBL_NAN);
1467 else return copysign(b, copysign(1.0, b) * a);
1472 if (b == 0) return longBitsToDouble(DBL_NAN);
1473 else return copysign(a, copysign(1.0, a) * b);
1476 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1482 double builtin_ddiv(double a, double b)
1490 return longBitsToDouble(DBL_NAN);
1492 return copysign(0.0, b);
1498 return longBitsToDouble(DBL_POSINF);
1500 return longBitsToDouble(DBL_NEGINF);
1503 return longBitsToDouble(DBL_NAN);
1506 /* if (finite(a) && finite(b)) { */
1511 /* return longBitsToDouble(DBL_POSINF); */
1512 /* else if (a < 0) */
1513 /* return longBitsToDouble(DBL_NEGINF); */
1517 /* keep compiler happy */
1522 double builtin_drem(double a, double b)
1528 double builtin_dneg(double a)
1530 if (isnan(a)) return a;
1532 if (finite(a)) return -a;
1533 else return copysign(a, -copysign(1.0, a));
1538 s4 builtin_dcmpl(double a, double b)
1540 if (isnan(a)) return -1;
1541 if (isnan(b)) return -1;
1542 if (!finite(a) || !finite(b)) {
1543 a = finite(a) ? 0 : copysign(1.0, a);
1544 b = finite(b) ? 0 : copysign(1.0, b);
1546 if (a > b) return 1;
1547 if (a == b) return 0;
1552 s4 builtin_dcmpg(double a, double b)
1554 if (isnan(a)) return 1;
1555 if (isnan(b)) return 1;
1556 if (!finite(a) || !finite(b)) {
1557 a = finite(a) ? 0 : copysign(1.0, a);
1558 b = finite(b) ? 0 : copysign(1.0, b);
1560 if (a > b) return 1;
1561 if (a == b) return 0;
1566 /*********************** Conversion operations ****************************/
1568 s8 builtin_i2l(s4 i)
1581 float builtin_i2f(s4 a)
1583 float f = (float) a;
1588 double builtin_i2d(s4 a)
1590 double d = (double) a;
1595 s4 builtin_l2i(s8 l)
1605 float builtin_l2f(s8 a)
1608 float f = (float) a;
1616 double builtin_l2d(s8 a)
1619 double d = (double) a;
1627 s4 builtin_f2i(float a)
1630 return builtin_d2i((double) a);
1639 if (a < (-2147483648))
1640 return (-2147483648);
1643 f = copysignf((float) 1.0, a);
1646 return (-2147483648); */
1650 s8 builtin_f2l(float a)
1653 return builtin_d2l((double) a);
1658 if (a > 9223372036854775807L)
1659 return 9223372036854775807L;
1660 if (a < (-9223372036854775808L))
1661 return (-9223372036854775808L);
1666 f = copysignf((float) 1.0, a);
1668 return 9223372036854775807L;
1669 return (-9223372036854775808L); */
1673 double builtin_f2d(float a)
1675 if (finitef(a)) return (double) a;
1678 return longBitsToDouble(DBL_NAN);
1680 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1685 s4 builtin_d2i(double a)
1690 if (a >= 2147483647)
1692 if (a <= (-2147483647-1))
1693 return (-2147483647-1);
1698 d = copysign(1.0, a);
1701 return (-2147483647-1);
1705 s8 builtin_d2l(double a)
1710 if (a >= 9223372036854775807LL)
1711 return 9223372036854775807LL;
1712 if (a <= (-9223372036854775807LL-1))
1713 return (-9223372036854775807LL-1);
1718 d = copysign(1.0, a);
1720 return 9223372036854775807LL;
1721 return (-9223372036854775807LL-1);
1725 float builtin_d2f(double a)
1731 return intBitsToFloat(FLT_NAN);
1733 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1738 /* used to convert FLT_xxx defines into float values */
1740 inline float intBitsToFloat(s4 i)
1749 /* used to convert DBL_xxx defines into double values */
1751 inline float longBitsToDouble(s8 l)
1760 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1762 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1767 panic("Internal error: builtin_dummy called (native function is missing)");
1768 return 0; /* for the compiler */
1773 * These are local overrides for various environment variables in Emacs.
1774 * Please do not remove this and leave it at the end of the file, where
1775 * Emacs will automagically detect them.
1776 * ---------------------------------------------------------------------
1779 * indent-tabs-mode: t