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 957 2004-03-14 21:01:12Z twisti $
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 void *_thread_nativestackframeinfo=NULL;
67 /*****************************************************************************
69 *****************************************************************************/
73 /*************** internal function: builtin_isanysubclass *********************
75 Checks a subclass relation between two classes. Implemented interfaces
76 are interpreted as super classes.
77 Return value: 1 ... sub is subclass of super
80 *****************************************************************************/
81 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
86 if (super->flags & ACC_INTERFACE)
87 return (sub->vftbl->interfacetablelength > super->index) &&
88 (sub->vftbl->interfacetable[-super->index] != NULL);
101 for (tmp=sub;tmp!=0;tmp=tmp->super) {
103 utf_display(tmp->name);
107 for (tmp=super;tmp!=0;tmp=tmp->super) {
109 utf_display(tmp->name);
114 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
115 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
116 super->vftbl->diffval); */
118 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
122 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
123 (unsigned) (super->vftbl->diffval);
125 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
132 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
141 if ((base = super->baseval) <= 0)
142 /* super is an interface */
143 res = (sub->interfacetablelength > -base) &&
144 (sub->interfacetable[base] != NULL);
146 res = (unsigned) (sub->baseval - base)
147 <= (unsigned) (super->diffval);
149 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
157 /****************** function: builtin_instanceof *****************************
159 Checks if an object is an instance of some given class (or subclass of
160 that class). If class is an interface, checks if the interface is
162 Return value: 1 ... obj is an instance of class or implements the interface
163 0 ... otherwise or if obj == NULL
165 *****************************************************************************/
167 /* XXX should use vftbl */
168 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
171 log_text ("builtin_instanceof called");
174 return builtin_isanysubclass (obj->vftbl->class, class);
179 /**************** function: builtin_checkcast *******************************
181 The same as builtin_instanceof except that 1 is returned when
184 ****************************************************************************/
186 /* XXX should use vftbl */
187 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
190 log_text("builtin_checkcast called");
195 if (builtin_isanysubclass(obj->vftbl->class, class))
199 printf("#### checkcast failed ");
200 utf_display(obj->vftbl->class->name);
202 utf_display(class->name);
210 /*********** internal function: builtin_descriptorscompatible ******************
212 Checks if two array type descriptors are assignment compatible
213 Return value: 1 ... target = desc is possible
216 ******************************************************************************/
218 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
220 if (desc==target) return 1;
221 if (desc->arraytype != target->arraytype) return 0;
222 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
224 /* {both arrays are arrays of references} */
225 if (desc->dimension == target->dimension) {
226 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
227 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
228 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
230 if (desc->dimension < target->dimension) return 0;
232 /* {desc has higher dimension than target} */
233 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
237 /******************** function: builtin_checkarraycast ***********************
239 Checks if an object is really a subtype of the requested array type.
240 The object has to be an array to begin with. For simple arrays (int, short,
241 double, etc.) the types have to match exactly.
242 For arrays of objects, the type of elements in the array has to be a
243 subtype (or the same type) of the requested element type. For arrays of
244 arrays (which in turn can again be arrays of arrays), the types at the
245 lowest level have to satisfy the corresponding sub class relation.
247 Return value: 1 ... cast is possible
250 ATTENTION: a cast with a NULL pointer is always possible.
252 *****************************************************************************/
254 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
256 arraydescriptor *desc;
259 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
261 return builtin_descriptorscompatible(desc, target->arraydesc);
265 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
268 return builtin_checkarraycast(obj, target);
272 /************************** exception functions *******************************
274 ******************************************************************************/
276 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
279 char logtext[MAXLOGTEXT];
280 sprintf(logtext, "Builtin exception thrown: ");
281 if (local_exceptionptr)
282 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
284 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
285 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
286 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
287 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
288 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
289 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
290 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
291 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
292 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
293 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
294 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
298 *exceptionptr = local_exceptionptr;
299 return local_exceptionptr;
302 void builtin_reset_exceptionptr()
304 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
306 _exceptionptr = NULL;
308 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
311 panic("builtin_reset_exceptionptr should not be used in this configuration");
316 /******************* function: builtin_canstore *******************************
318 Checks, if an object can be stored in an array.
319 Return value: 1 ... possible
322 ******************************************************************************/
324 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
326 arraydescriptor *desc;
327 arraydescriptor *valuedesc;
328 vftbl *componentvftbl;
335 /* The following is guaranteed (by verifier checks):
337 * *) a->...vftbl->arraydesc != NULL
338 * *) a->...vftbl->arraydesc->componentvftbl != NULL
339 * *) o->vftbl is not an interface vftbl
342 desc = a->header.objheader.vftbl->arraydesc;
343 componentvftbl = desc->componentvftbl;
344 valuevftbl = o->vftbl;
346 if ((dim_m1 = desc->dimension - 1) == 0) {
349 /* {a is a one-dimensional array} */
350 /* {a is an array of references} */
352 if (valuevftbl == componentvftbl)
355 if ((base = componentvftbl->baseval) <= 0)
356 /* an array of interface references */
357 return (valuevftbl->interfacetablelength > -base &&
358 valuevftbl->interfacetable[base] != NULL);
360 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
364 res = (unsigned)(valuevftbl->baseval - base)
365 <= (unsigned)(componentvftbl->diffval);
367 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
373 /* {a has dimension > 1} */
374 /* {componentvftbl->arraydesc != NULL} */
376 /* check if o is an array */
377 if ((valuedesc = valuevftbl->arraydesc) == NULL)
379 /* {o is an array} */
381 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
385 /* This is an optimized version where a is guaranteed to be one-dimensional */
386 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
388 arraydescriptor *desc;
396 /* The following is guaranteed (by verifier checks):
398 * *) a->...vftbl->arraydesc != NULL
399 * *) a->...vftbl->arraydesc->elementvftbl != NULL
400 * *) a->...vftbl->arraydesc->dimension == 1
401 * *) o->vftbl is not an interface vftbl
404 desc = a->header.objheader.vftbl->arraydesc;
405 elementvftbl = desc->elementvftbl;
406 valuevftbl = o->vftbl;
408 /* {a is a one-dimensional array} */
410 if (valuevftbl == elementvftbl)
413 if ((base = elementvftbl->baseval) <= 0)
414 /* an array of interface references */
415 return (valuevftbl->interfacetablelength > -base &&
416 valuevftbl->interfacetable[base] != NULL);
418 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
422 res = (unsigned)(valuevftbl->baseval - base)
423 <= (unsigned)(elementvftbl->diffval);
425 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
433 /* This is an optimized version where a is guaranteed to be a
434 * one-dimensional array of a class type */
435 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
443 /* The following is guaranteed (by verifier checks):
445 * *) a->...vftbl->arraydesc != NULL
446 * *) a->...vftbl->arraydesc->elementvftbl != NULL
447 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
448 * *) a->...vftbl->arraydesc->dimension == 1
449 * *) o->vftbl is not an interface vftbl
452 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
453 valuevftbl = o->vftbl;
455 /* {a is a one-dimensional array} */
457 if (valuevftbl == elementvftbl)
460 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
464 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
465 <= (unsigned)(elementvftbl->diffval);
467 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
475 /******************** Function: builtin_new **********************************
477 Creates a new instance of class c on the heap.
478 Return value: pointer to the object or NULL if no memory is
481 *****************************************************************************/
484 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
486 java_objectheader *builtin_new(classinfo *c)
488 java_objectheader *o;
489 /*DEBUGING - NOT THREAD SAFE*/
490 /* static long depth=0;
492 printf("Entering builtin_new:depth(%ld)",depth);*/
494 if (!c->initialized) {
496 char logtext[MAXLOGTEXT];
497 sprintf(logtext, "Initialize class ");
498 utf_sprint(logtext + strlen(logtext), c->name);
499 sprintf(logtext + strlen(logtext), " (from builtin_new)");
505 #ifdef SIZE_FROM_CLASSINFO
506 c->alignedsize = align_size(c->instancesize);
507 o = heap_allocate(c->alignedsize, true, c->finalizer);
509 o = heap_allocate(c->instancesize, true, c->finalizer);
512 /*DEBUGING - NOT THREAD SAFE*/
513 /*printf("Leaving builtin_new: depth(%ld): NULL",depth);
518 memset(o, 0, c->instancesize);
522 /*DEBUGING - NOT THREAD SAFE*/
523 /* printf("Leaving builtin_new: depth(%ld): object",depth);
528 /********************** Function: builtin_newarray **************************
530 Creates an array with the given vftbl on the heap.
532 Return value: pointer to the array or NULL if no memory is available
534 CAUTION: The given vftbl must be the vftbl of the *array* class,
535 not of the element class.
537 *****************************************************************************/
539 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
542 arraydescriptor *desc = arrayvftbl->arraydesc;
543 s4 dataoffset = desc->dataoffset;
544 s4 componentsize = desc->componentsize;
548 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
551 #ifdef SIZE_FROM_CLASSINFO
552 actualsize = align_size(dataoffset + size * componentsize);
554 actualsize = dataoffset + size * componentsize;
557 if (((u4)actualsize)<((u4)size)) { /* overflow */
558 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
561 a = heap_allocate(actualsize,
562 (desc->arraytype == ARRAYTYPE_OBJECT),
566 memset(a, 0, actualsize);
569 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
571 a->objheader.vftbl = arrayvftbl;
573 #ifdef SIZE_FROM_CLASSINFO
574 a->alignedsize = actualsize;
581 /********************** Function: builtin_anewarray *************************
583 Creates an array of references to the given class type on the heap.
585 Return value: pointer to the array or NULL if no memory is available
587 XXX This function does not do The Right Thing, because it uses a
588 classinfo pointer at runtime. builtin_newarray should be used
591 *****************************************************************************/
593 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
596 printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
597 printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
598 utf_display(component->vftbl->class->name);
599 printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
600 utf_display(component->super->name);*/
601 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
605 /******************** Function: builtin_newarray_int ***********************
607 Creates an array of 32 bit Integers on the heap.
609 Return value: pointer to the array or NULL if no memory is available
611 *****************************************************************************/
613 java_intarray *builtin_newarray_int(s4 size)
615 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
619 /******************** Function: builtin_newarray_long ***********************
621 Creates an array of 64 bit Integers on the heap.
623 Return value: pointer to the array or NULL if no memory is available
625 *****************************************************************************/
627 java_longarray *builtin_newarray_long(s4 size)
629 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
633 /******************** function: builtin_newarray_float ***********************
635 Creates an array of 32 bit IEEE floats on the heap.
637 Return value: pointer to the array or NULL if no memory is available
639 *****************************************************************************/
641 java_floatarray *builtin_newarray_float(s4 size)
643 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
647 /******************** function: builtin_newarray_double ***********************
649 Creates an array of 64 bit IEEE floats on the heap.
651 Return value: pointer to the array or NULL if no memory is available
653 *****************************************************************************/
655 java_doublearray *builtin_newarray_double(s4 size)
657 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
661 /******************** function: builtin_newarray_byte ***********************
663 Creates an array of 8 bit Integers on the heap.
665 Return value: pointer to the array or NULL if no memory is available
667 *****************************************************************************/
669 java_bytearray *builtin_newarray_byte(s4 size)
671 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
675 /******************** function: builtin_newarray_char ************************
677 Creates an array of characters on the heap.
679 Return value: pointer to the array or NULL if no memory is available
681 *****************************************************************************/
683 java_chararray *builtin_newarray_char(s4 size)
685 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
689 /******************** function: builtin_newarray_short ***********************
691 Creates an array of 16 bit Integers on the heap.
693 Return value: pointer to the array or NULL if no memory is available
695 *****************************************************************************/
697 java_shortarray *builtin_newarray_short(s4 size)
699 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
703 /******************** function: builtin_newarray_boolean ************************
705 Creates an array of bytes on the heap. The array is designated as an array
706 of booleans (important for casts)
708 Return value: pointer to the array or NULL if no memory is available
710 *****************************************************************************/
712 java_booleanarray *builtin_newarray_boolean(s4 size)
714 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
718 /**************** function: builtin_nmultianewarray ***************************
720 Creates a multi-dimensional array on the heap. The dimensions are passed in
724 n............number of dimensions to create
725 arrayvftbl...vftbl of the array class
726 dims.........array containing the size of each dimension to create
728 Return value: pointer to the array or NULL if no memory is available
730 ******************************************************************************/
732 /* Helper functions */
734 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
738 vftbl *componentvftbl;
740 /* create this dimension */
741 size = (int) dims[0];
742 a = builtin_newarray(size,arrayvftbl);
745 /* if this is the last dimension return */
748 /* get the vftbl of the components to create */
749 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
751 /* The verifier guarantees this. */
752 /* if (!componentvftbl) */
753 /* panic ("multianewarray with too many dimensions"); */
755 /* create the component arrays */
756 for (i = 0; i < size; i++) {
757 java_arrayheader *ea =
758 builtin_nmultianewarray(n,componentvftbl,dims+1);
759 if (!ea) return NULL;
760 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
767 /*****************************************************************************
770 Various functions for printing a message at method entry or exit (for
773 *****************************************************************************/
777 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
786 log_text("WARNING: unmatched methodindent--");
788 if (verbose || runverbose) {
789 printf("Exception ");
791 utf_display_classname(_exceptionptr->vftbl->class->name);
794 printf("Error: <Nullpointer instead of exception>");
795 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
796 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
797 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
798 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
799 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
800 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
801 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
802 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
803 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
804 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
807 printf(" thrown in ");
810 utf_display_classname(method->class->name);
812 utf_display(method->name);
813 if (method->flags & ACC_SYNCHRONIZED)
817 printf("(%p) at position %p\n", method->entrypoint, pos);
820 printf("call_java_method\n");
824 return _exceptionptr;
828 #ifdef TRACE_ARGS_NUM
829 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
830 #if TRACE_ARGS_NUM > 6
836 char logtext[MAXLOGTEXT];
837 for (i = 0; i < methodindent; i++)
840 sprintf(logtext + methodindent, "called: ");
841 utf_sprint(logtext + strlen(logtext), method->class->name);
842 sprintf(logtext + strlen(logtext), ".");
843 utf_sprint(logtext + strlen(logtext), method->name);
844 utf_sprint(logtext + strlen(logtext), method->descriptor);
846 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
847 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
848 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
849 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
850 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
851 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
852 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
853 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
854 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
855 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
856 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
859 sprintf(logtext + strlen(logtext), "(");
861 switch (method->paramcount) {
865 #if defined(__I386__) || defined(__POWERPC__)
867 sprintf(logtext+strlen(logtext), "%llx", a0);
871 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
875 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
879 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
884 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
889 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
890 a0, a1, a2, a3, a4, a5);
893 #if TRACE_ARGS_NUM > 6
895 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
896 a0, a1, a2, a3, a4, a5, a6);
900 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
901 a0, a1, a2, a3, a4, a5, a6, a7);
905 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
906 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
910 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
911 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
916 sprintf(logtext+strlen(logtext), "%lx", a0);
920 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
924 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
928 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
933 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
938 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
939 a0, a1, a2, a3, a4, a5);
942 #if TRACE_ARGS_NUM > 6
944 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
945 a0, a1, a2, a3, a4, a5, a6);
949 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
950 a0, a1, a2, a3, a4, a5, a6, a7);
954 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
955 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
959 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
960 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
966 sprintf(logtext + strlen(logtext), ")");
974 void builtin_displaymethodstart(methodinfo *method)
976 char logtext[MAXLOGTEXT];
977 sprintf(logtext, " ");
978 sprintf(logtext + methodindent, "called: ");
979 utf_sprint(logtext + strlen(logtext), method->class->name);
980 sprintf(logtext + strlen(logtext), ".");
981 utf_sprint(logtext + strlen(logtext), method->name);
982 utf_sprint(logtext + strlen(logtext), method->descriptor);
984 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
985 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
986 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
987 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
988 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
989 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
990 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
991 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
992 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
993 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
994 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
1001 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1004 char logtext[MAXLOGTEXT];
1005 for (i = 0; i < methodindent; i++)
1010 log_text("WARNING: unmatched methodindent--");
1012 sprintf(logtext + methodindent, "finished: ");
1013 utf_sprint(logtext + strlen(logtext), method->class->name);
1014 sprintf(logtext + strlen(logtext), ".");
1015 utf_sprint(logtext + strlen(logtext), method->name);
1016 utf_sprint(logtext + strlen(logtext), method->descriptor);
1018 switch (method->returntype) {
1020 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1024 #if defined(__I386__) || defined(__POWERPC__)
1025 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1027 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1032 #if defined(__I386__) || defined(__POWERPC__)
1033 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1035 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1040 sprintf(logtext + strlen(logtext), "->%g", f);
1044 sprintf(logtext + strlen(logtext), "->%g", d);
1051 void builtin_displaymethodexception(methodinfo *method)
1054 char logtext[MAXLOGTEXT];
1055 for (i = 0; i < methodindent; i++)
1057 sprintf(logtext + methodindent, "exception abort: ");
1058 utf_sprint(logtext + strlen(logtext), method->class->name);
1059 sprintf(logtext + strlen(logtext), ".");
1060 utf_sprint(logtext + strlen(logtext), method->name);
1061 utf_sprint(logtext + strlen(logtext), method->descriptor);
1066 /****************************************************************************
1067 SYNCHRONIZATION FUNCTIONS
1068 *****************************************************************************/
1071 * Lock the mutex of an object.
1073 void internal_lock_mutex_for_object(java_objectheader *object)
1075 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1076 mutexHashEntry *entry;
1079 assert(object != 0);
1081 hashValue = MUTEX_HASH_VALUE(object);
1082 entry = &mutexHashTable[hashValue];
1084 if (entry->object != 0) {
1085 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1087 entry->mutex.holder = 0;
1088 entry->mutex.count = 0;
1089 entry->mutex.muxWaiters = 0;
1092 while (entry->next != 0 && entry->object != object)
1093 entry = entry->next;
1095 if (entry->object != object) {
1096 entry->next = firstFreeOverflowEntry;
1097 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1099 entry = entry->next;
1102 assert(entry->conditionCount == 0);
1107 entry->mutex.holder = 0;
1108 entry->mutex.count = 0;
1109 entry->mutex.muxWaiters = 0;
1112 if (entry->object == 0)
1113 entry->object = object;
1115 internal_lock_mutex(&entry->mutex);
1121 * Unlocks the mutex of an object.
1123 void internal_unlock_mutex_for_object (java_objectheader *object)
1125 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1127 mutexHashEntry *entry;
1129 hashValue = MUTEX_HASH_VALUE(object);
1130 entry = &mutexHashTable[hashValue];
1132 if (entry->object == object) {
1133 internal_unlock_mutex(&entry->mutex);
1136 while (entry->next != 0 && entry->next->object != object)
1137 entry = entry->next;
1139 assert(entry->next != 0);
1141 internal_unlock_mutex(&entry->next->mutex);
1143 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1144 mutexHashEntry *unlinked = entry->next;
1146 entry->next = unlinked->next;
1147 unlinked->next = firstFreeOverflowEntry;
1148 firstFreeOverflowEntry = unlinked;
1155 void builtin_monitorenter(java_objectheader *o)
1157 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1160 assert(blockInts == 0);
1164 hashValue = MUTEX_HASH_VALUE(o);
1165 if (mutexHashTable[hashValue].object == o
1166 && mutexHashTable[hashValue].mutex.holder == currentThread)
1167 ++mutexHashTable[hashValue].mutex.count;
1169 internal_lock_mutex_for_object(o);
1173 assert(blockInts == 0);
1178 void builtin_monitorexit (java_objectheader *o)
1180 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1183 assert(blockInts == 0);
1187 hashValue = MUTEX_HASH_VALUE(o);
1188 if (mutexHashTable[hashValue].object == o) {
1189 if (mutexHashTable[hashValue].mutex.count == 1
1190 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1191 internal_unlock_mutex_for_object(o);
1193 --mutexHashTable[hashValue].mutex.count;
1196 internal_unlock_mutex_for_object(o);
1200 assert(blockInts == 0);
1205 /*****************************************************************************
1206 MISCELLANEOUS HELPER FUNCTIONS
1207 *****************************************************************************/
1211 /*********** Functions for integer divisions *****************************
1213 On some systems (eg. DEC ALPHA), integer division is not supported by the
1214 CPU. These helper functions implement the missing functionality.
1216 ******************************************************************************/
1218 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1219 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1222 /************** Functions for long arithmetics *******************************
1224 On systems where 64 bit Integers are not supported by the CPU, these
1225 functions are needed.
1227 ******************************************************************************/
1230 s8 builtin_ladd(s8 a, s8 b)
1235 return builtin_i2l(0);
1239 s8 builtin_lsub(s8 a, s8 b)
1244 return builtin_i2l(0);
1248 s8 builtin_lmul(s8 a, s8 b)
1253 return builtin_i2l(0);
1257 s8 builtin_ldiv(s8 a, s8 b)
1262 return builtin_i2l(0);
1266 s8 builtin_lrem(s8 a, s8 b)
1271 return builtin_i2l(0);
1275 s8 builtin_lshl(s8 a, s4 b)
1278 return a << (b & 63);
1280 return builtin_i2l(0);
1284 s8 builtin_lshr(s8 a, s4 b)
1287 return a >> (b & 63);
1289 return builtin_i2l(0);
1293 s8 builtin_lushr(s8 a, s4 b)
1296 return ((u8) a) >> (b & 63);
1298 return builtin_i2l(0);
1302 s8 builtin_land(s8 a, s8 b)
1307 return builtin_i2l(0);
1311 s8 builtin_lor(s8 a, s8 b)
1316 return builtin_i2l(0);
1320 s8 builtin_lxor(s8 a, s8 b)
1325 return builtin_i2l(0);
1329 s8 builtin_lneg(s8 a)
1334 return builtin_i2l(0);
1338 s4 builtin_lcmp(s8 a, s8 b)
1341 if (a < b) return -1;
1342 if (a > b) return 1;
1353 /*********** Functions for floating point operations *************************/
1355 float builtin_fadd(float a, float b)
1357 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1358 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1369 if (copysignf(1.0, a) == copysignf(1.0, b))
1372 return intBitsToFloat(FLT_NAN);
1378 float builtin_fsub(float a, float b)
1380 return builtin_fadd(a, builtin_fneg(b));
1384 float builtin_fmul(float a, float b)
1386 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1387 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1389 if (finitef(b)) return a * b;
1391 if (a == 0) return intBitsToFloat(FLT_NAN);
1392 else return copysignf(b, copysignf(1.0, b)*a);
1397 if (b == 0) return intBitsToFloat(FLT_NAN);
1398 else return copysignf(a, copysignf(1.0, a)*b);
1401 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1407 float builtin_fdiv(float a, float b)
1409 if (finitef(a) && finitef(b)) {
1414 return intBitsToFloat(FLT_POSINF);
1416 return intBitsToFloat(FLT_NEGINF);
1419 return intBitsToFloat(FLT_NAN);
1423 float builtin_frem(float a, float b)
1429 float builtin_fneg(float a)
1431 if (isnanf(a)) return a;
1433 if (finitef(a)) return -a;
1434 else return copysignf(a, -copysignf(1.0, a));
1439 s4 builtin_fcmpl(float a, float b)
1441 if (isnanf(a)) return -1;
1442 if (isnanf(b)) return -1;
1443 if (!finitef(a) || !finitef(b)) {
1444 a = finitef(a) ? 0 : copysignf(1.0, a);
1445 b = finitef(b) ? 0 : copysignf(1.0, b);
1447 if (a > b) return 1;
1448 if (a == b) return 0;
1453 s4 builtin_fcmpg(float a, float b)
1455 if (isnanf(a)) return 1;
1456 if (isnanf(b)) return 1;
1457 if (!finitef(a) || !finitef(b)) {
1458 a = finitef(a) ? 0 : copysignf(1.0, a);
1459 b = finitef(b) ? 0 : copysignf(1.0, b);
1461 if (a > b) return 1;
1462 if (a == b) return 0;
1468 /************************* Functions for doubles ****************************/
1470 double builtin_dadd(double a, double b)
1472 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1473 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1475 if (finite(b)) return a + b;
1479 if (finite(b)) return a;
1481 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1482 else return longBitsToDouble(DBL_NAN);
1488 double builtin_dsub(double a, double b)
1490 return builtin_dadd(a, builtin_dneg(b));
1494 double builtin_dmul(double a, double b)
1496 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1497 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1499 if (finite(b)) return a * b;
1501 if (a == 0) return longBitsToDouble(DBL_NAN);
1502 else return copysign(b, copysign(1.0, b) * a);
1507 if (b == 0) return longBitsToDouble(DBL_NAN);
1508 else return copysign(a, copysign(1.0, a) * b);
1511 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1517 double builtin_ddiv(double a, double b)
1525 return longBitsToDouble(DBL_NAN);
1527 return copysign(0.0, b);
1533 return longBitsToDouble(DBL_POSINF);
1535 return longBitsToDouble(DBL_NEGINF);
1538 return longBitsToDouble(DBL_NAN);
1541 /* if (finite(a) && finite(b)) { */
1546 /* return longBitsToDouble(DBL_POSINF); */
1547 /* else if (a < 0) */
1548 /* return longBitsToDouble(DBL_NEGINF); */
1552 /* keep compiler happy */
1557 double builtin_drem(double a, double b)
1563 double builtin_dneg(double a)
1565 if (isnan(a)) return a;
1567 if (finite(a)) return -a;
1568 else return copysign(a, -copysign(1.0, a));
1573 s4 builtin_dcmpl(double a, double b)
1575 if (isnan(a)) return -1;
1576 if (isnan(b)) return -1;
1577 if (!finite(a) || !finite(b)) {
1578 a = finite(a) ? 0 : copysign(1.0, a);
1579 b = finite(b) ? 0 : copysign(1.0, b);
1581 if (a > b) return 1;
1582 if (a == b) return 0;
1587 s4 builtin_dcmpg(double a, double b)
1589 if (isnan(a)) return 1;
1590 if (isnan(b)) return 1;
1591 if (!finite(a) || !finite(b)) {
1592 a = finite(a) ? 0 : copysign(1.0, a);
1593 b = finite(b) ? 0 : copysign(1.0, b);
1595 if (a > b) return 1;
1596 if (a == b) return 0;
1601 /*********************** Conversion operations ****************************/
1603 s8 builtin_i2l(s4 i)
1616 float builtin_i2f(s4 a)
1618 float f = (float) a;
1623 double builtin_i2d(s4 a)
1625 double d = (double) a;
1630 s4 builtin_l2i(s8 l)
1640 float builtin_l2f(s8 a)
1643 float f = (float) a;
1651 double builtin_l2d(s8 a)
1654 double d = (double) a;
1662 s4 builtin_f2i(float a)
1665 return builtin_d2i((double) a);
1674 if (a < (-2147483648))
1675 return (-2147483648);
1678 f = copysignf((float) 1.0, a);
1681 return (-2147483648); */
1685 s8 builtin_f2l(float a)
1688 return builtin_d2l((double) a);
1693 if (a > 9223372036854775807L)
1694 return 9223372036854775807L;
1695 if (a < (-9223372036854775808L))
1696 return (-9223372036854775808L);
1701 f = copysignf((float) 1.0, a);
1703 return 9223372036854775807L;
1704 return (-9223372036854775808L); */
1708 double builtin_f2d(float a)
1710 if (finitef(a)) return (double) a;
1713 return longBitsToDouble(DBL_NAN);
1715 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1720 s4 builtin_d2i(double a)
1725 if (a >= 2147483647)
1727 if (a <= (-2147483647-1))
1728 return (-2147483647-1);
1733 d = copysign(1.0, a);
1736 return (-2147483647-1);
1740 s8 builtin_d2l(double a)
1745 if (a >= 9223372036854775807LL)
1746 return 9223372036854775807LL;
1747 if (a <= (-9223372036854775807LL-1))
1748 return (-9223372036854775807LL-1);
1753 d = copysign(1.0, a);
1755 return 9223372036854775807LL;
1756 return (-9223372036854775807LL-1);
1760 float builtin_d2f(double a)
1766 return intBitsToFloat(FLT_NAN);
1768 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1773 /* used to convert FLT_xxx defines into float values */
1775 inline float intBitsToFloat(s4 i)
1784 /* used to convert DBL_xxx defines into double values */
1786 inline float longBitsToDouble(s8 l)
1795 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1797 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1802 panic("Internal error: builtin_dummy called (native function is missing)");
1803 return 0; /* for the compiler */
1807 inline methodinfo *builtin_asm_get_threadrootmethod() {
1808 return *threadrootmethod;
1813 builtin_asm_get_stackframeinfo(){
1814 /*log_text("builtin_asm_get_stackframeinfo()");*/
1815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1816 #ifdef HAVE___THREAD
1817 return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1819 return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1823 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1824 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1829 * These are local overrides for various environment variables in Emacs.
1830 * Please do not remove this and leave it at the end of the file, where
1831 * Emacs will automagically detect them.
1832 * ---------------------------------------------------------------------
1835 * indent-tabs-mode: t