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 930 2004-03-02 21:18:23Z jowenn $
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 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
65 THREADSPECIFIC native_stackframeinfo _thread_nativestackframeinfo_bottom={0,0,0,0};
66 THREADSPECIFIC native_stackframeinfo *_thread_nativestackframeinfo=&_thread_nativestackframeinfo_bottom;
68 /*****************************************************************************
70 *****************************************************************************/
74 /*************** internal function: builtin_isanysubclass *********************
76 Checks a subclass relation between two classes. Implemented interfaces
77 are interpreted as super classes.
78 Return value: 1 ... sub is subclass of super
81 *****************************************************************************/
82 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
87 if (super->flags & ACC_INTERFACE)
88 return (sub->vftbl->interfacetablelength > super->index) &&
89 (sub->vftbl->interfacetable[-super->index] != NULL);
102 for (tmp=sub;tmp!=0;tmp=tmp->super) {
104 utf_display(tmp->name);
108 for (tmp=super;tmp!=0;tmp=tmp->super) {
110 utf_display(tmp->name);
115 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
116 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
117 super->vftbl->diffval); */
119 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
123 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
124 (unsigned) (super->vftbl->diffval);
126 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
133 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
138 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
142 if ((base = super->baseval) <= 0)
143 /* super is an interface */
144 res = (sub->interfacetablelength > -base) &&
145 (sub->interfacetable[base] != NULL);
147 res = (unsigned) (sub->baseval - base)
148 <= (unsigned) (super->diffval);
150 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
158 /****************** function: builtin_instanceof *****************************
160 Checks if an object is an instance of some given class (or subclass of
161 that class). If class is an interface, checks if the interface is
163 Return value: 1 ... obj is an instance of class or implements the interface
164 0 ... otherwise or if obj == NULL
166 *****************************************************************************/
168 /* XXX should use vftbl */
169 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
172 log_text ("builtin_instanceof called");
175 return builtin_isanysubclass (obj->vftbl->class, class);
180 /**************** function: builtin_checkcast *******************************
182 The same as builtin_instanceof except that 1 is returned when
185 ****************************************************************************/
187 /* XXX should use vftbl */
188 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
191 log_text("builtin_checkcast called");
196 if (builtin_isanysubclass(obj->vftbl->class, class))
200 printf("#### checkcast failed ");
201 utf_display(obj->vftbl->class->name);
203 utf_display(class->name);
211 /*********** internal function: builtin_descriptorscompatible ******************
213 Checks if two array type descriptors are assignment compatible
214 Return value: 1 ... target = desc is possible
217 ******************************************************************************/
219 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
221 if (desc==target) return 1;
222 if (desc->arraytype != target->arraytype) return 0;
223 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
225 /* {both arrays are arrays of references} */
226 if (desc->dimension == target->dimension) {
227 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
228 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
229 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
231 if (desc->dimension < target->dimension) return 0;
233 /* {desc has higher dimension than target} */
234 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
238 /******************** function: builtin_checkarraycast ***********************
240 Checks if an object is really a subtype of the requested array type.
241 The object has to be an array to begin with. For simple arrays (int, short,
242 double, etc.) the types have to match exactly.
243 For arrays of objects, the type of elements in the array has to be a
244 subtype (or the same type) of the requested element type. For arrays of
245 arrays (which in turn can again be arrays of arrays), the types at the
246 lowest level have to satisfy the corresponding sub class relation.
248 Return value: 1 ... cast is possible
251 ATTENTION: a cast with a NULL pointer is always possible.
253 *****************************************************************************/
255 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
257 arraydescriptor *desc;
260 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
262 return builtin_descriptorscompatible(desc, target->arraydesc);
266 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
269 return builtin_checkarraycast(obj, target);
273 /************************** exception functions *******************************
275 ******************************************************************************/
277 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
280 char logtext[MAXLOGTEXT];
281 sprintf(logtext, "Builtin exception thrown: ");
282 if (local_exceptionptr)
283 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
285 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
286 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
287 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
288 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
289 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
290 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
291 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
292 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
293 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
294 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
295 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
299 *exceptionptr = local_exceptionptr;
300 return local_exceptionptr;
303 void builtin_reset_exceptionptr()
305 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
307 _exceptionptr = NULL;
309 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
312 panic("builtin_reset_exceptionptr should not be used in this configuration");
317 /******************* function: builtin_canstore *******************************
319 Checks, if an object can be stored in an array.
320 Return value: 1 ... possible
323 ******************************************************************************/
325 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
327 arraydescriptor *desc;
328 arraydescriptor *valuedesc;
329 vftbl *componentvftbl;
336 /* The following is guaranteed (by verifier checks):
338 * *) a->...vftbl->arraydesc != NULL
339 * *) a->...vftbl->arraydesc->componentvftbl != NULL
340 * *) o->vftbl is not an interface vftbl
343 desc = a->header.objheader.vftbl->arraydesc;
344 componentvftbl = desc->componentvftbl;
345 valuevftbl = o->vftbl;
347 if ((dim_m1 = desc->dimension - 1) == 0) {
350 /* {a is a one-dimensional array} */
351 /* {a is an array of references} */
353 if (valuevftbl == componentvftbl)
356 if ((base = componentvftbl->baseval) <= 0)
357 /* an array of interface references */
358 return (valuevftbl->interfacetablelength > -base &&
359 valuevftbl->interfacetable[base] != NULL);
361 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
365 res = (unsigned)(valuevftbl->baseval - base)
366 <= (unsigned)(componentvftbl->diffval);
368 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
374 /* {a has dimension > 1} */
375 /* {componentvftbl->arraydesc != NULL} */
377 /* check if o is an array */
378 if ((valuedesc = valuevftbl->arraydesc) == NULL)
380 /* {o is an array} */
382 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
386 /* This is an optimized version where a is guaranteed to be one-dimensional */
387 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
389 arraydescriptor *desc;
397 /* The following is guaranteed (by verifier checks):
399 * *) a->...vftbl->arraydesc != NULL
400 * *) a->...vftbl->arraydesc->elementvftbl != NULL
401 * *) a->...vftbl->arraydesc->dimension == 1
402 * *) o->vftbl is not an interface vftbl
405 desc = a->header.objheader.vftbl->arraydesc;
406 elementvftbl = desc->elementvftbl;
407 valuevftbl = o->vftbl;
409 /* {a is a one-dimensional array} */
411 if (valuevftbl == elementvftbl)
414 if ((base = elementvftbl->baseval) <= 0)
415 /* an array of interface references */
416 return (valuevftbl->interfacetablelength > -base &&
417 valuevftbl->interfacetable[base] != NULL);
419 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
423 res = (unsigned)(valuevftbl->baseval - base)
424 <= (unsigned)(elementvftbl->diffval);
426 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
434 /* This is an optimized version where a is guaranteed to be a
435 * one-dimensional array of a class type */
436 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
444 /* The following is guaranteed (by verifier checks):
446 * *) a->...vftbl->arraydesc != NULL
447 * *) a->...vftbl->arraydesc->elementvftbl != NULL
448 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
449 * *) a->...vftbl->arraydesc->dimension == 1
450 * *) o->vftbl is not an interface vftbl
453 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
454 valuevftbl = o->vftbl;
456 /* {a is a one-dimensional array} */
458 if (valuevftbl == elementvftbl)
461 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
465 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
466 <= (unsigned)(elementvftbl->diffval);
468 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
476 /******************** Function: builtin_new **********************************
478 Creates a new instance of class c on the heap.
479 Return value: pointer to the object or NULL if no memory is
482 *****************************************************************************/
485 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
487 java_objectheader *builtin_new(classinfo *c)
489 java_objectheader *o;
491 if (!c->initialized) {
493 char logtext[MAXLOGTEXT];
494 sprintf(logtext, "Initialize class ");
495 utf_sprint(logtext + strlen(logtext), c->name);
496 sprintf(logtext + strlen(logtext), " (from builtin_new)");
502 #ifdef SIZE_FROM_CLASSINFO
503 c->alignedsize = align_size(c->instancesize);
504 o = heap_allocate(c->alignedsize, true, c->finalizer);
506 o = heap_allocate(c->instancesize, true, c->finalizer);
510 memset(o, 0, c->instancesize);
517 /********************** Function: builtin_newarray **************************
519 Creates an array with the given vftbl on the heap.
521 Return value: pointer to the array or NULL if no memory is available
523 CAUTION: The given vftbl must be the vftbl of the *array* class,
524 not of the element class.
526 *****************************************************************************/
528 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
531 arraydescriptor *desc = arrayvftbl->arraydesc;
532 s4 dataoffset = desc->dataoffset;
533 s4 componentsize = desc->componentsize;
537 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
540 #ifdef SIZE_FROM_CLASSINFO
541 actualsize = align_size(dataoffset + size * componentsize);
543 actualsize = dataoffset + size * componentsize;
546 if (((u4)actualsize)<((u4)size)) { /* overflow */
547 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
550 a = heap_allocate(actualsize,
551 (desc->arraytype == ARRAYTYPE_OBJECT),
555 memset(a, 0, actualsize);
558 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
560 a->objheader.vftbl = arrayvftbl;
562 #ifdef SIZE_FROM_CLASSINFO
563 a->alignedsize = actualsize;
570 /********************** Function: builtin_anewarray *************************
572 Creates an array of references to the given class type on the heap.
574 Return value: pointer to the array or NULL if no memory is available
576 XXX This function does not do The Right Thing, because it uses a
577 classinfo pointer at runtime. builtin_newarray should be used
580 *****************************************************************************/
582 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
585 printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
586 printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
587 utf_display(component->vftbl->class->name);
588 printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
589 utf_display(component->super->name);*/
590 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
594 /******************** Function: builtin_newarray_int ***********************
596 Creates an array of 32 bit Integers on the heap.
598 Return value: pointer to the array or NULL if no memory is available
600 *****************************************************************************/
602 java_intarray *builtin_newarray_int(s4 size)
604 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
608 /******************** Function: builtin_newarray_long ***********************
610 Creates an array of 64 bit Integers on the heap.
612 Return value: pointer to the array or NULL if no memory is available
614 *****************************************************************************/
616 java_longarray *builtin_newarray_long(s4 size)
618 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
622 /******************** function: builtin_newarray_float ***********************
624 Creates an array of 32 bit IEEE floats on the heap.
626 Return value: pointer to the array or NULL if no memory is available
628 *****************************************************************************/
630 java_floatarray *builtin_newarray_float(s4 size)
632 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
636 /******************** function: builtin_newarray_double ***********************
638 Creates an array of 64 bit IEEE floats on the heap.
640 Return value: pointer to the array or NULL if no memory is available
642 *****************************************************************************/
644 java_doublearray *builtin_newarray_double(s4 size)
646 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
650 /******************** function: builtin_newarray_byte ***********************
652 Creates an array of 8 bit Integers on the heap.
654 Return value: pointer to the array or NULL if no memory is available
656 *****************************************************************************/
658 java_bytearray *builtin_newarray_byte(s4 size)
660 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
664 /******************** function: builtin_newarray_char ************************
666 Creates an array of characters on the heap.
668 Return value: pointer to the array or NULL if no memory is available
670 *****************************************************************************/
672 java_chararray *builtin_newarray_char(s4 size)
674 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
678 /******************** function: builtin_newarray_short ***********************
680 Creates an array of 16 bit Integers on the heap.
682 Return value: pointer to the array or NULL if no memory is available
684 *****************************************************************************/
686 java_shortarray *builtin_newarray_short(s4 size)
688 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
692 /******************** function: builtin_newarray_boolean ************************
694 Creates an array of bytes on the heap. The array is designated as an array
695 of booleans (important for casts)
697 Return value: pointer to the array or NULL if no memory is available
699 *****************************************************************************/
701 java_booleanarray *builtin_newarray_boolean(s4 size)
703 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
707 /**************** function: builtin_nmultianewarray ***************************
709 Creates a multi-dimensional array on the heap. The dimensions are passed in
713 n............number of dimensions to create
714 arrayvftbl...vftbl of the array class
715 dims.........array containing the size of each dimension to create
717 Return value: pointer to the array or NULL if no memory is available
719 ******************************************************************************/
721 /* Helper functions */
723 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
727 vftbl *componentvftbl;
729 /* create this dimension */
730 size = (int) dims[0];
731 a = builtin_newarray(size,arrayvftbl);
734 /* if this is the last dimension return */
737 /* get the vftbl of the components to create */
738 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
740 /* The verifier guarantees this. */
741 /* if (!componentvftbl) */
742 /* panic ("multianewarray with too many dimensions"); */
744 /* create the component arrays */
745 for (i = 0; i < size; i++) {
746 java_arrayheader *ea =
747 builtin_nmultianewarray(n,componentvftbl,dims+1);
748 if (!ea) return NULL;
749 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
756 /*****************************************************************************
759 Various functions for printing a message at method entry or exit (for
762 *****************************************************************************/
767 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
768 methodinfo *method, int *pos,
775 log_text("WARNING: unmatched methodindent--");
777 if (verbose || runverbose) {
778 printf("Exception ");
780 utf_display(_exceptionptr->vftbl->class->name);
783 printf("Error: <Nullpointer instead of exception>");
784 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
785 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
786 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
787 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
788 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
789 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
790 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
791 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
792 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
793 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
796 printf(" thrown in ");
799 utf_display(method->class->name);
801 utf_display(method->name);
802 if (method->flags & ACC_SYNCHRONIZED)
806 printf("(%p) at position %p\n", method->entrypoint, pos);
809 printf("call_java_method\n");
813 return _exceptionptr;
817 #ifdef TRACE_ARGS_NUM
818 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
819 #if TRACE_ARGS_NUM > 6
825 char logtext[MAXLOGTEXT];
826 for (i = 0; i < methodindent; i++)
828 sprintf(logtext + methodindent, "called: ");
829 utf_sprint(logtext + strlen(logtext), method->class->name);
830 sprintf(logtext + strlen(logtext), ".");
831 utf_sprint(logtext + strlen(logtext), method->name);
832 utf_sprint(logtext + strlen(logtext), method->descriptor);
834 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
835 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
836 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
837 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
838 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
839 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
840 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
841 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
842 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
843 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
844 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
847 sprintf(logtext + strlen(logtext), "(");
849 switch (method->paramcount) {
853 #if defined(__I386__)
855 sprintf(logtext+strlen(logtext), "%llx", a0);
859 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
863 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
867 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
872 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
877 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
878 a0, a1, a2, a3, a4, a5);
881 #if TRACE_ARGS_NUM > 6
883 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
884 a0, a1, a2, a3, a4, a5, a6);
888 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
889 a0, a1, a2, a3, a4, a5, a6, a7);
893 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
894 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
898 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
899 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
904 sprintf(logtext+strlen(logtext), "%lx", a0);
908 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
912 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
916 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
921 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
926 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
927 a0, a1, a2, a3, a4, a5);
930 #if TRACE_ARGS_NUM > 6
932 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
933 a0, a1, a2, a3, a4, a5, a6);
937 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
938 a0, a1, a2, a3, a4, a5, a6, a7);
942 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
943 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
947 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
948 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
953 sprintf (logtext+strlen(logtext), ")");
961 void builtin_displaymethodstart(methodinfo *method)
963 char logtext[MAXLOGTEXT];
964 sprintf(logtext, " ");
965 sprintf(logtext + methodindent, "called: ");
966 utf_sprint(logtext + strlen(logtext), method->class->name);
967 sprintf(logtext + strlen(logtext), ".");
968 utf_sprint(logtext + strlen(logtext), method->name);
969 utf_sprint(logtext + strlen(logtext), method->descriptor);
971 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
972 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
973 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
974 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
975 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
976 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
977 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
978 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
979 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
980 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
981 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
988 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
991 char logtext[MAXLOGTEXT];
992 for (i = 0; i < methodindent; i++)
997 log_text("WARNING: unmatched methodindent--");
998 sprintf(logtext + methodindent, "finished: ");
999 utf_sprint(logtext + strlen(logtext), method->class->name);
1000 sprintf(logtext + strlen(logtext), ".");
1001 utf_sprint(logtext + strlen(logtext), method->name);
1002 utf_sprint(logtext + strlen(logtext), method->descriptor);
1004 switch (method->returntype) {
1006 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1009 #if defined(__I386__)
1010 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1012 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1016 #if defined(__I386__)
1017 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1019 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1023 sprintf(logtext + strlen(logtext), "->%g", f);
1026 sprintf(logtext + strlen(logtext), "->%g", d);
1033 void builtin_displaymethodexception(methodinfo *method)
1036 char logtext[MAXLOGTEXT];
1037 for (i = 0; i < methodindent; i++)
1039 sprintf(logtext + methodindent, "exception abort: ");
1040 utf_sprint(logtext + strlen(logtext), method->class->name);
1041 sprintf(logtext + strlen(logtext), ".");
1042 utf_sprint(logtext + strlen(logtext), method->name);
1043 utf_sprint(logtext + strlen(logtext), method->descriptor);
1048 /****************************************************************************
1049 SYNCHRONIZATION FUNCTIONS
1050 *****************************************************************************/
1053 * Lock the mutex of an object.
1055 void internal_lock_mutex_for_object(java_objectheader *object)
1057 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1058 mutexHashEntry *entry;
1061 assert(object != 0);
1063 hashValue = MUTEX_HASH_VALUE(object);
1064 entry = &mutexHashTable[hashValue];
1066 if (entry->object != 0) {
1067 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1069 entry->mutex.holder = 0;
1070 entry->mutex.count = 0;
1071 entry->mutex.muxWaiters = 0;
1074 while (entry->next != 0 && entry->object != object)
1075 entry = entry->next;
1077 if (entry->object != object) {
1078 entry->next = firstFreeOverflowEntry;
1079 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1081 entry = entry->next;
1084 assert(entry->conditionCount == 0);
1089 entry->mutex.holder = 0;
1090 entry->mutex.count = 0;
1091 entry->mutex.muxWaiters = 0;
1094 if (entry->object == 0)
1095 entry->object = object;
1097 internal_lock_mutex(&entry->mutex);
1103 * Unlocks the mutex of an object.
1105 void internal_unlock_mutex_for_object (java_objectheader *object)
1107 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1109 mutexHashEntry *entry;
1111 hashValue = MUTEX_HASH_VALUE(object);
1112 entry = &mutexHashTable[hashValue];
1114 if (entry->object == object) {
1115 internal_unlock_mutex(&entry->mutex);
1118 while (entry->next != 0 && entry->next->object != object)
1119 entry = entry->next;
1121 assert(entry->next != 0);
1123 internal_unlock_mutex(&entry->next->mutex);
1125 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1126 mutexHashEntry *unlinked = entry->next;
1128 entry->next = unlinked->next;
1129 unlinked->next = firstFreeOverflowEntry;
1130 firstFreeOverflowEntry = unlinked;
1137 void builtin_monitorenter(java_objectheader *o)
1139 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1142 assert(blockInts == 0);
1146 hashValue = MUTEX_HASH_VALUE(o);
1147 if (mutexHashTable[hashValue].object == o
1148 && mutexHashTable[hashValue].mutex.holder == currentThread)
1149 ++mutexHashTable[hashValue].mutex.count;
1151 internal_lock_mutex_for_object(o);
1155 assert(blockInts == 0);
1160 void builtin_monitorexit (java_objectheader *o)
1162 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1165 assert(blockInts == 0);
1169 hashValue = MUTEX_HASH_VALUE(o);
1170 if (mutexHashTable[hashValue].object == o) {
1171 if (mutexHashTable[hashValue].mutex.count == 1
1172 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1173 internal_unlock_mutex_for_object(o);
1175 --mutexHashTable[hashValue].mutex.count;
1178 internal_unlock_mutex_for_object(o);
1182 assert(blockInts == 0);
1187 /*****************************************************************************
1188 MISCELLANEOUS HELPER FUNCTIONS
1189 *****************************************************************************/
1193 /*********** Functions for integer divisions *****************************
1195 On some systems (eg. DEC ALPHA), integer division is not supported by the
1196 CPU. These helper functions implement the missing functionality.
1198 ******************************************************************************/
1200 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1201 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1204 /************** Functions for long arithmetics *******************************
1206 On systems where 64 bit Integers are not supported by the CPU, these
1207 functions are needed.
1209 ******************************************************************************/
1212 s8 builtin_ladd(s8 a, s8 b)
1217 return builtin_i2l(0);
1221 s8 builtin_lsub(s8 a, s8 b)
1226 return builtin_i2l(0);
1230 s8 builtin_lmul(s8 a, s8 b)
1235 return builtin_i2l(0);
1239 s8 builtin_ldiv(s8 a, s8 b)
1244 return builtin_i2l(0);
1248 s8 builtin_lrem(s8 a, s8 b)
1253 return builtin_i2l(0);
1257 s8 builtin_lshl(s8 a, s4 b)
1260 return a << (b & 63);
1262 return builtin_i2l(0);
1266 s8 builtin_lshr(s8 a, s4 b)
1269 return a >> (b & 63);
1271 return builtin_i2l(0);
1275 s8 builtin_lushr(s8 a, s4 b)
1278 return ((u8) a) >> (b & 63);
1280 return builtin_i2l(0);
1284 s8 builtin_land(s8 a, s8 b)
1289 return builtin_i2l(0);
1293 s8 builtin_lor(s8 a, s8 b)
1298 return builtin_i2l(0);
1302 s8 builtin_lxor(s8 a, s8 b)
1307 return builtin_i2l(0);
1311 s8 builtin_lneg(s8 a)
1316 return builtin_i2l(0);
1320 s4 builtin_lcmp(s8 a, s8 b)
1323 if (a < b) return -1;
1324 if (a > b) return 1;
1335 /*********** Functions for floating point operations *************************/
1337 float builtin_fadd(float a, float b)
1339 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1340 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1351 if (copysignf(1.0, a) == copysignf(1.0, b))
1354 return intBitsToFloat(FLT_NAN);
1360 float builtin_fsub(float a, float b)
1362 return builtin_fadd(a, builtin_fneg(b));
1366 float builtin_fmul(float a, float b)
1368 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1369 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1371 if (finitef(b)) return a * b;
1373 if (a == 0) return intBitsToFloat(FLT_NAN);
1374 else return copysignf(b, copysignf(1.0, b)*a);
1379 if (b == 0) return intBitsToFloat(FLT_NAN);
1380 else return copysignf(a, copysignf(1.0, a)*b);
1383 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1389 float builtin_fdiv(float a, float b)
1391 if (finitef(a) && finitef(b)) {
1396 return intBitsToFloat(FLT_POSINF);
1398 return intBitsToFloat(FLT_NEGINF);
1401 return intBitsToFloat(FLT_NAN);
1405 float builtin_frem(float a, float b)
1411 float builtin_fneg(float a)
1413 if (isnanf(a)) return a;
1415 if (finitef(a)) return -a;
1416 else return copysignf(a, -copysignf(1.0, a));
1421 s4 builtin_fcmpl(float a, float b)
1423 if (isnanf(a)) return -1;
1424 if (isnanf(b)) return -1;
1425 if (!finitef(a) || !finitef(b)) {
1426 a = finitef(a) ? 0 : copysignf(1.0, a);
1427 b = finitef(b) ? 0 : copysignf(1.0, b);
1429 if (a > b) return 1;
1430 if (a == b) return 0;
1435 s4 builtin_fcmpg(float a, float b)
1437 if (isnanf(a)) return 1;
1438 if (isnanf(b)) return 1;
1439 if (!finitef(a) || !finitef(b)) {
1440 a = finitef(a) ? 0 : copysignf(1.0, a);
1441 b = finitef(b) ? 0 : copysignf(1.0, b);
1443 if (a > b) return 1;
1444 if (a == b) return 0;
1450 /************************* Functions for doubles ****************************/
1452 double builtin_dadd(double a, double b)
1454 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1455 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1457 if (finite(b)) return a + b;
1461 if (finite(b)) return a;
1463 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1464 else return longBitsToDouble(DBL_NAN);
1470 double builtin_dsub(double a, double b)
1472 return builtin_dadd(a, builtin_dneg(b));
1476 double builtin_dmul(double a, double b)
1478 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1479 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1481 if (finite(b)) return a * b;
1483 if (a == 0) return longBitsToDouble(DBL_NAN);
1484 else return copysign(b, copysign(1.0, b) * a);
1489 if (b == 0) return longBitsToDouble(DBL_NAN);
1490 else return copysign(a, copysign(1.0, a) * b);
1493 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1499 double builtin_ddiv(double a, double b)
1507 return longBitsToDouble(DBL_NAN);
1509 return copysign(0.0, b);
1515 return longBitsToDouble(DBL_POSINF);
1517 return longBitsToDouble(DBL_NEGINF);
1520 return longBitsToDouble(DBL_NAN);
1523 /* if (finite(a) && finite(b)) { */
1528 /* return longBitsToDouble(DBL_POSINF); */
1529 /* else if (a < 0) */
1530 /* return longBitsToDouble(DBL_NEGINF); */
1534 /* keep compiler happy */
1539 double builtin_drem(double a, double b)
1545 double builtin_dneg(double a)
1547 if (isnan(a)) return a;
1549 if (finite(a)) return -a;
1550 else return copysign(a, -copysign(1.0, a));
1555 s4 builtin_dcmpl(double a, double b)
1557 if (isnan(a)) return -1;
1558 if (isnan(b)) return -1;
1559 if (!finite(a) || !finite(b)) {
1560 a = finite(a) ? 0 : copysign(1.0, a);
1561 b = finite(b) ? 0 : copysign(1.0, b);
1563 if (a > b) return 1;
1564 if (a == b) return 0;
1569 s4 builtin_dcmpg(double a, double b)
1571 if (isnan(a)) return 1;
1572 if (isnan(b)) return 1;
1573 if (!finite(a) || !finite(b)) {
1574 a = finite(a) ? 0 : copysign(1.0, a);
1575 b = finite(b) ? 0 : copysign(1.0, b);
1577 if (a > b) return 1;
1578 if (a == b) return 0;
1583 /*********************** Conversion operations ****************************/
1585 s8 builtin_i2l(s4 i)
1598 float builtin_i2f(s4 a)
1600 float f = (float) a;
1605 double builtin_i2d(s4 a)
1607 double d = (double) a;
1612 s4 builtin_l2i(s8 l)
1622 float builtin_l2f(s8 a)
1625 float f = (float) a;
1633 double builtin_l2d(s8 a)
1636 double d = (double) a;
1644 s4 builtin_f2i(float a)
1647 return builtin_d2i((double) a);
1656 if (a < (-2147483648))
1657 return (-2147483648);
1660 f = copysignf((float) 1.0, a);
1663 return (-2147483648); */
1667 s8 builtin_f2l(float a)
1670 return builtin_d2l((double) a);
1675 if (a > 9223372036854775807L)
1676 return 9223372036854775807L;
1677 if (a < (-9223372036854775808L))
1678 return (-9223372036854775808L);
1683 f = copysignf((float) 1.0, a);
1685 return 9223372036854775807L;
1686 return (-9223372036854775808L); */
1690 double builtin_f2d(float a)
1692 if (finitef(a)) return (double) a;
1695 return longBitsToDouble(DBL_NAN);
1697 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1702 s4 builtin_d2i(double a)
1707 if (a >= 2147483647)
1709 if (a <= (-2147483647-1))
1710 return (-2147483647-1);
1715 d = copysign(1.0, a);
1718 return (-2147483647-1);
1722 s8 builtin_d2l(double a)
1727 if (a >= 9223372036854775807LL)
1728 return 9223372036854775807LL;
1729 if (a <= (-9223372036854775807LL-1))
1730 return (-9223372036854775807LL-1);
1735 d = copysign(1.0, a);
1737 return 9223372036854775807LL;
1738 return (-9223372036854775807LL-1);
1742 float builtin_d2f(double a)
1748 return intBitsToFloat(FLT_NAN);
1750 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1755 /* used to convert FLT_xxx defines into float values */
1757 inline float intBitsToFloat(s4 i)
1766 /* used to convert DBL_xxx defines into double values */
1768 inline float longBitsToDouble(s8 l)
1777 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1779 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1784 panic("Internal error: builtin_dummy called (native function is missing)");
1785 return 0; /* for the compiler */
1789 inline methodinfo *builtin_asm_get_threadrootmethod() {
1790 return *threadrootmethod;
1793 inline native_stackframeinfo **builtin_asm_new_stackframeinfo() {
1794 native_stackframeinfo **infop;
1795 native_stackframeinfo *info;
1796 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1797 #ifdef HAVE___THREAD
1798 /* log_text("native_stackframeinfo **builtin_asm_new_stackframeinfo(): __thread");*/
1799 infop=&_thread_nativestackframeinfo; /*support for __thread attribute*/
1801 /* log_text("native_stackframeinfo **builtin_asm_new_stackframeinfo(): pthread");*/
1802 infop= &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really correct */
1806 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1807 /* log_text("native_stackframeinfo **builtin_asm_new_stackframeinfo(): no thread");*/
1808 infop=&_thread_nativestackframeinfo; /* no threading, at least no native*/
1811 if (!(info->next)) {
1812 info->next=MNEW(native_stackframeinfo,1);
1814 info->next->returnFromNative=0;
1815 info->next->method=0;
1817 info->next->prev=info;
1820 (*infop)=info->next;
1823 native_stackframeinfo *inf;
1825 log_text("returning from: native_stackframeinfo **builtin_asm_new_stackframeinfo()");
1826 for (inf=info;inf;inf=inf->prev) i++;
1828 printf ("current depth: %ld\n",i);
1829 for (inf=info->next;inf;inf=inf->next) i++;
1830 printf ("max depth: %ld\n",i);
1835 inline native_stackframeinfo *builtin_asm_get_framestackinfo(){
1836 native_stackframeinfo **infop;
1837 native_stackframeinfo *info;
1838 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1839 #ifdef HAVE___THREAD
1840 return _thread_nativestackframeinfo; /*support for __thread attribute*/
1842 return ((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that
1847 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1848 printf("blockaddr=%p\n",_thread_nativestackframeinfo);
1849 printf("retaddr=%p\n",_thread_nativestackframeinfo->returnFromNative);
1850 return _thread_nativestackframeinfo; /* no threading, at least no native*/
1855 * These are local overrides for various environment variables in Emacs.
1856 * Please do not remove this and leave it at the end of the file, where
1857 * Emacs will automagically detect them.
1858 * ---------------------------------------------------------------------
1861 * indent-tabs-mode: t