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 897 2004-01-21 00:49:42Z stefan $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.h"
61 #undef DEBUG /*define DEBUG 1*/
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);
816 sprintf(logtext + strlen(logtext), "(");
818 switch (method->paramcount) {
822 #if defined(__I386__)
824 sprintf(logtext+strlen(logtext), "%llx", a0);
828 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
832 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
836 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
841 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
846 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
847 a0, a1, a2, a3, a4, a5);
850 #if TRACE_ARGS_NUM > 6
852 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
853 a0, a1, a2, a3, a4, a5, a6);
857 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
858 a0, a1, a2, a3, a4, a5, a6, a7);
862 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
863 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
867 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
868 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
873 sprintf(logtext+strlen(logtext), "%lx", a0);
877 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
881 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
885 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
890 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
895 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
896 a0, a1, a2, a3, a4, a5);
899 #if TRACE_ARGS_NUM > 6
901 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
902 a0, a1, a2, a3, a4, a5, a6);
906 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
907 a0, a1, a2, a3, a4, a5, a6, a7);
911 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
912 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
916 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
917 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
922 sprintf (logtext+strlen(logtext), ")");
930 void builtin_displaymethodstart(methodinfo *method)
932 char logtext[MAXLOGTEXT];
933 sprintf(logtext, " ");
934 sprintf(logtext + methodindent, "called: ");
935 utf_sprint(logtext + strlen(logtext), method->class->name);
936 sprintf(logtext + strlen(logtext), ".");
937 utf_sprint(logtext + strlen(logtext), method->name);
938 utf_sprint(logtext + strlen(logtext), method->descriptor);
944 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
947 char logtext[MAXLOGTEXT];
948 for (i = 0; i < methodindent; i++)
953 log_text("WARNING: unmatched methodindent--");
954 sprintf(logtext + methodindent, "finished: ");
955 utf_sprint(logtext + strlen(logtext), method->class->name);
956 sprintf(logtext + strlen(logtext), ".");
957 utf_sprint(logtext + strlen(logtext), method->name);
958 utf_sprint(logtext + strlen(logtext), method->descriptor);
960 switch (method->returntype) {
962 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
965 #if defined(__I386__)
966 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
968 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
972 #if defined(__I386__)
973 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
975 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
979 sprintf(logtext + strlen(logtext), "->%g", f);
982 sprintf(logtext + strlen(logtext), "->%g", d);
989 void builtin_displaymethodexception(methodinfo *method)
992 char logtext[MAXLOGTEXT];
993 for (i = 0; i < methodindent; i++)
995 sprintf(logtext + methodindent, "exception abort: ");
996 utf_sprint(logtext + strlen(logtext), method->class->name);
997 sprintf(logtext + strlen(logtext), ".");
998 utf_sprint(logtext + strlen(logtext), method->name);
999 utf_sprint(logtext + strlen(logtext), method->descriptor);
1004 /****************************************************************************
1005 SYNCHRONIZATION FUNCTIONS
1006 *****************************************************************************/
1009 * Lock the mutex of an object.
1011 void internal_lock_mutex_for_object(java_objectheader *object)
1013 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1014 mutexHashEntry *entry;
1017 assert(object != 0);
1019 hashValue = MUTEX_HASH_VALUE(object);
1020 entry = &mutexHashTable[hashValue];
1022 if (entry->object != 0) {
1023 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1025 entry->mutex.holder = 0;
1026 entry->mutex.count = 0;
1027 entry->mutex.muxWaiters = 0;
1030 while (entry->next != 0 && entry->object != object)
1031 entry = entry->next;
1033 if (entry->object != object) {
1034 entry->next = firstFreeOverflowEntry;
1035 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1037 entry = entry->next;
1040 assert(entry->conditionCount == 0);
1045 entry->mutex.holder = 0;
1046 entry->mutex.count = 0;
1047 entry->mutex.muxWaiters = 0;
1050 if (entry->object == 0)
1051 entry->object = object;
1053 internal_lock_mutex(&entry->mutex);
1059 * Unlocks the mutex of an object.
1061 void internal_unlock_mutex_for_object (java_objectheader *object)
1063 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1065 mutexHashEntry *entry;
1067 hashValue = MUTEX_HASH_VALUE(object);
1068 entry = &mutexHashTable[hashValue];
1070 if (entry->object == object) {
1071 internal_unlock_mutex(&entry->mutex);
1074 while (entry->next != 0 && entry->next->object != object)
1075 entry = entry->next;
1077 assert(entry->next != 0);
1079 internal_unlock_mutex(&entry->next->mutex);
1081 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1082 mutexHashEntry *unlinked = entry->next;
1084 entry->next = unlinked->next;
1085 unlinked->next = firstFreeOverflowEntry;
1086 firstFreeOverflowEntry = unlinked;
1093 void builtin_monitorenter(java_objectheader *o)
1095 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1098 assert(blockInts == 0);
1102 hashValue = MUTEX_HASH_VALUE(o);
1103 if (mutexHashTable[hashValue].object == o
1104 && mutexHashTable[hashValue].mutex.holder == currentThread)
1105 ++mutexHashTable[hashValue].mutex.count;
1107 internal_lock_mutex_for_object(o);
1111 assert(blockInts == 0);
1116 void builtin_monitorexit (java_objectheader *o)
1118 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1121 assert(blockInts == 0);
1125 hashValue = MUTEX_HASH_VALUE(o);
1126 if (mutexHashTable[hashValue].object == o) {
1127 if (mutexHashTable[hashValue].mutex.count == 1
1128 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1129 internal_unlock_mutex_for_object(o);
1131 --mutexHashTable[hashValue].mutex.count;
1134 internal_unlock_mutex_for_object(o);
1138 assert(blockInts == 0);
1143 /*****************************************************************************
1144 MISCELLANEOUS HELPER FUNCTIONS
1145 *****************************************************************************/
1149 /*********** Functions for integer divisions *****************************
1151 On some systems (eg. DEC ALPHA), integer division is not supported by the
1152 CPU. These helper functions implement the missing functionality.
1154 ******************************************************************************/
1156 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1157 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1160 /************** Functions for long arithmetics *******************************
1162 On systems where 64 bit Integers are not supported by the CPU, these
1163 functions are needed.
1165 ******************************************************************************/
1168 s8 builtin_ladd(s8 a, s8 b)
1173 return builtin_i2l(0);
1177 s8 builtin_lsub(s8 a, s8 b)
1182 return builtin_i2l(0);
1186 s8 builtin_lmul(s8 a, s8 b)
1191 return builtin_i2l(0);
1195 s8 builtin_ldiv(s8 a, s8 b)
1200 return builtin_i2l(0);
1204 s8 builtin_lrem(s8 a, s8 b)
1209 return builtin_i2l(0);
1213 s8 builtin_lshl(s8 a, s4 b)
1216 return a << (b & 63);
1218 return builtin_i2l(0);
1222 s8 builtin_lshr(s8 a, s4 b)
1225 return a >> (b & 63);
1227 return builtin_i2l(0);
1231 s8 builtin_lushr(s8 a, s4 b)
1234 return ((u8) a) >> (b & 63);
1236 return builtin_i2l(0);
1240 s8 builtin_land(s8 a, s8 b)
1245 return builtin_i2l(0);
1249 s8 builtin_lor(s8 a, s8 b)
1254 return builtin_i2l(0);
1258 s8 builtin_lxor(s8 a, s8 b)
1263 return builtin_i2l(0);
1267 s8 builtin_lneg(s8 a)
1272 return builtin_i2l(0);
1276 s4 builtin_lcmp(s8 a, s8 b)
1279 if (a < b) return -1;
1280 if (a > b) return 1;
1291 /*********** Functions for floating point operations *************************/
1293 float builtin_fadd(float a, float b)
1295 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1296 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1307 if (copysignf(1.0, a) == copysignf(1.0, b))
1310 return intBitsToFloat(FLT_NAN);
1316 float builtin_fsub(float a, float b)
1318 return builtin_fadd(a, builtin_fneg(b));
1322 float builtin_fmul(float a, float b)
1324 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1325 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1327 if (finitef(b)) return a * b;
1329 if (a == 0) return intBitsToFloat(FLT_NAN);
1330 else return copysignf(b, copysignf(1.0, b)*a);
1335 if (b == 0) return intBitsToFloat(FLT_NAN);
1336 else return copysignf(a, copysignf(1.0, a)*b);
1339 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1345 float builtin_fdiv(float a, float b)
1347 if (finitef(a) && finitef(b)) {
1352 return intBitsToFloat(FLT_POSINF);
1354 return intBitsToFloat(FLT_NEGINF);
1357 return intBitsToFloat(FLT_NAN);
1361 float builtin_frem(float a, float b)
1367 float builtin_fneg(float a)
1369 if (isnanf(a)) return a;
1371 if (finitef(a)) return -a;
1372 else return copysignf(a, -copysignf(1.0, a));
1377 s4 builtin_fcmpl(float a, float b)
1379 if (isnanf(a)) return -1;
1380 if (isnanf(b)) return -1;
1381 if (!finitef(a) || !finitef(b)) {
1382 a = finitef(a) ? 0 : copysignf(1.0, a);
1383 b = finitef(b) ? 0 : copysignf(1.0, b);
1385 if (a > b) return 1;
1386 if (a == b) return 0;
1391 s4 builtin_fcmpg(float a, float b)
1393 if (isnanf(a)) return 1;
1394 if (isnanf(b)) return 1;
1395 if (!finitef(a) || !finitef(b)) {
1396 a = finitef(a) ? 0 : copysignf(1.0, a);
1397 b = finitef(b) ? 0 : copysignf(1.0, b);
1399 if (a > b) return 1;
1400 if (a == b) return 0;
1406 /************************* Functions for doubles ****************************/
1408 double builtin_dadd(double a, double b)
1410 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1411 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1413 if (finite(b)) return a + b;
1417 if (finite(b)) return a;
1419 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1420 else return longBitsToDouble(DBL_NAN);
1426 double builtin_dsub(double a, double b)
1428 return builtin_dadd(a, builtin_dneg(b));
1432 double builtin_dmul(double a, double b)
1434 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1435 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1437 if (finite(b)) return a * b;
1439 if (a == 0) return longBitsToDouble(DBL_NAN);
1440 else return copysign(b, copysign(1.0, b) * a);
1445 if (b == 0) return longBitsToDouble(DBL_NAN);
1446 else return copysign(a, copysign(1.0, a) * b);
1449 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1455 double builtin_ddiv(double a, double b)
1463 return longBitsToDouble(DBL_NAN);
1465 return copysign(0.0, b);
1471 return longBitsToDouble(DBL_POSINF);
1473 return longBitsToDouble(DBL_NEGINF);
1476 return longBitsToDouble(DBL_NAN);
1479 /* if (finite(a) && finite(b)) { */
1484 /* return longBitsToDouble(DBL_POSINF); */
1485 /* else if (a < 0) */
1486 /* return longBitsToDouble(DBL_NEGINF); */
1490 /* keep compiler happy */
1495 double builtin_drem(double a, double b)
1501 double builtin_dneg(double a)
1503 if (isnan(a)) return a;
1505 if (finite(a)) return -a;
1506 else return copysign(a, -copysign(1.0, a));
1511 s4 builtin_dcmpl(double a, double b)
1513 if (isnan(a)) return -1;
1514 if (isnan(b)) return -1;
1515 if (!finite(a) || !finite(b)) {
1516 a = finite(a) ? 0 : copysign(1.0, a);
1517 b = finite(b) ? 0 : copysign(1.0, b);
1519 if (a > b) return 1;
1520 if (a == b) return 0;
1525 s4 builtin_dcmpg(double a, double b)
1527 if (isnan(a)) return 1;
1528 if (isnan(b)) return 1;
1529 if (!finite(a) || !finite(b)) {
1530 a = finite(a) ? 0 : copysign(1.0, a);
1531 b = finite(b) ? 0 : copysign(1.0, b);
1533 if (a > b) return 1;
1534 if (a == b) return 0;
1539 /*********************** Conversion operations ****************************/
1541 s8 builtin_i2l(s4 i)
1554 float builtin_i2f(s4 a)
1556 float f = (float) a;
1561 double builtin_i2d(s4 a)
1563 double d = (double) a;
1568 s4 builtin_l2i(s8 l)
1578 float builtin_l2f(s8 a)
1581 float f = (float) a;
1589 double builtin_l2d(s8 a)
1592 double d = (double) a;
1600 s4 builtin_f2i(float a)
1603 return builtin_d2i((double) a);
1612 if (a < (-2147483648))
1613 return (-2147483648);
1616 f = copysignf((float) 1.0, a);
1619 return (-2147483648); */
1623 s8 builtin_f2l(float a)
1626 return builtin_d2l((double) a);
1631 if (a > 9223372036854775807L)
1632 return 9223372036854775807L;
1633 if (a < (-9223372036854775808L))
1634 return (-9223372036854775808L);
1639 f = copysignf((float) 1.0, a);
1641 return 9223372036854775807L;
1642 return (-9223372036854775808L); */
1646 double builtin_f2d(float a)
1648 if (finitef(a)) return (double) a;
1651 return longBitsToDouble(DBL_NAN);
1653 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1658 s4 builtin_d2i(double a)
1663 if (a >= 2147483647)
1665 if (a <= (-2147483647-1))
1666 return (-2147483647-1);
1671 d = copysign(1.0, a);
1674 return (-2147483647-1);
1678 s8 builtin_d2l(double a)
1683 if (a >= 9223372036854775807LL)
1684 return 9223372036854775807LL;
1685 if (a <= (-9223372036854775807LL-1))
1686 return (-9223372036854775807LL-1);
1691 d = copysign(1.0, a);
1693 return 9223372036854775807LL;
1694 return (-9223372036854775807LL-1);
1698 float builtin_d2f(double a)
1704 return intBitsToFloat(FLT_NAN);
1706 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1711 /* used to convert FLT_xxx defines into float values */
1713 inline float intBitsToFloat(s4 i)
1722 /* used to convert DBL_xxx defines into double values */
1724 inline float longBitsToDouble(s8 l)
1733 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1735 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1740 panic("Internal error: builtin_dummy called (native function is missing)");
1741 return 0; /* for the compiler */
1746 * These are local overrides for various environment variables in Emacs.
1747 * Please do not remove this and leave it at the end of the file, where
1748 * Emacs will automagically detect them.
1749 * ---------------------------------------------------------------------
1752 * indent-tabs-mode: t