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 964 2004-03-15 14:52:43Z 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 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,
778 methodinfo *method, int *pos,
786 log_text("WARNING: unmatched methodindent--");
788 if (verbose || runverbose || verboseexception) {
790 printf("Exception ");
791 utf_display(_exceptionptr->vftbl->class->name);
794 printf("Some Throwable");
796 printf("Error: <Nullpointer instead of exception>");
797 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
798 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
799 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
800 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
801 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
802 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
803 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
804 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
805 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
806 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
809 printf(" thrown in ");
812 utf_display_classname(method->class->name);
814 utf_display(method->name);
815 if (method->flags & ACC_SYNCHRONIZED)
819 if (method->flags & ACC_NATIVE) {
821 printf(")(%p) at position %p\n", method->entrypoint, pos);
823 printf(")(%p) at position %p (",method->entrypoint,pos);
824 if (method->class->sourcefile==NULL)
825 printf("<NO CLASSFILE INFORMATION>");
827 utf_display(method->class->sourcefile);
828 printf(":%d)\n",line);
832 printf("call_java_method\n");
836 return _exceptionptr;
840 #ifdef TRACE_ARGS_NUM
841 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
842 #if TRACE_ARGS_NUM > 6
848 char logtext[MAXLOGTEXT];
849 for (i = 0; i < methodindent; i++)
852 sprintf(logtext + methodindent, "called: ");
853 utf_sprint(logtext + strlen(logtext), method->class->name);
854 sprintf(logtext + strlen(logtext), ".");
855 utf_sprint(logtext + strlen(logtext), method->name);
856 utf_sprint(logtext + strlen(logtext), method->descriptor);
858 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
859 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
860 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
861 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
862 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
863 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
864 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
865 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
866 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
867 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
868 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
871 sprintf(logtext + strlen(logtext), "(");
873 switch (method->paramcount) {
877 #if defined(__I386__) || defined(__POWERPC__)
879 sprintf(logtext+strlen(logtext), "%llx", a0);
883 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
887 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
891 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
896 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
901 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
902 a0, a1, a2, a3, a4, a5);
905 #if TRACE_ARGS_NUM > 6
907 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
908 a0, a1, a2, a3, a4, a5, a6);
912 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
913 a0, a1, a2, a3, a4, a5, a6, a7);
917 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
918 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
922 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
923 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
928 sprintf(logtext+strlen(logtext), "%lx", a0);
932 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
936 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
940 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
945 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
950 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
951 a0, a1, a2, a3, a4, a5);
954 #if TRACE_ARGS_NUM > 6
956 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
957 a0, a1, a2, a3, a4, a5, a6);
961 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
962 a0, a1, a2, a3, a4, a5, a6, a7);
966 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
967 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
971 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
972 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
978 sprintf(logtext + strlen(logtext), ")");
986 void builtin_displaymethodstart(methodinfo *method)
988 char logtext[MAXLOGTEXT];
989 sprintf(logtext, " ");
990 sprintf(logtext + methodindent, "called: ");
991 utf_sprint(logtext + strlen(logtext), method->class->name);
992 sprintf(logtext + strlen(logtext), ".");
993 utf_sprint(logtext + strlen(logtext), method->name);
994 utf_sprint(logtext + strlen(logtext), method->descriptor);
996 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
997 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
998 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
999 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
1000 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
1001 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
1002 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
1003 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
1004 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
1005 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
1006 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
1013 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1016 char logtext[MAXLOGTEXT];
1017 for (i = 0; i < methodindent; i++)
1022 log_text("WARNING: unmatched methodindent--");
1024 sprintf(logtext + methodindent, "finished: ");
1025 utf_sprint(logtext + strlen(logtext), method->class->name);
1026 sprintf(logtext + strlen(logtext), ".");
1027 utf_sprint(logtext + strlen(logtext), method->name);
1028 utf_sprint(logtext + strlen(logtext), method->descriptor);
1030 switch (method->returntype) {
1032 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1036 #if defined(__I386__) || defined(__POWERPC__)
1037 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1039 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1044 #if defined(__I386__) || defined(__POWERPC__)
1045 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1047 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1052 sprintf(logtext + strlen(logtext), "->%g", f);
1056 sprintf(logtext + strlen(logtext), "->%g", d);
1063 void builtin_displaymethodexception(methodinfo *method)
1066 char logtext[MAXLOGTEXT];
1067 for (i = 0; i < methodindent; i++)
1069 sprintf(logtext + methodindent, "exception abort: ");
1070 utf_sprint(logtext + strlen(logtext), method->class->name);
1071 sprintf(logtext + strlen(logtext), ".");
1072 utf_sprint(logtext + strlen(logtext), method->name);
1073 utf_sprint(logtext + strlen(logtext), method->descriptor);
1078 /****************************************************************************
1079 SYNCHRONIZATION FUNCTIONS
1080 *****************************************************************************/
1083 * Lock the mutex of an object.
1085 void internal_lock_mutex_for_object(java_objectheader *object)
1087 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1088 mutexHashEntry *entry;
1091 assert(object != 0);
1093 hashValue = MUTEX_HASH_VALUE(object);
1094 entry = &mutexHashTable[hashValue];
1096 if (entry->object != 0) {
1097 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1099 entry->mutex.holder = 0;
1100 entry->mutex.count = 0;
1101 entry->mutex.muxWaiters = 0;
1104 while (entry->next != 0 && entry->object != object)
1105 entry = entry->next;
1107 if (entry->object != object) {
1108 entry->next = firstFreeOverflowEntry;
1109 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1111 entry = entry->next;
1114 assert(entry->conditionCount == 0);
1119 entry->mutex.holder = 0;
1120 entry->mutex.count = 0;
1121 entry->mutex.muxWaiters = 0;
1124 if (entry->object == 0)
1125 entry->object = object;
1127 internal_lock_mutex(&entry->mutex);
1133 * Unlocks the mutex of an object.
1135 void internal_unlock_mutex_for_object (java_objectheader *object)
1137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1139 mutexHashEntry *entry;
1141 hashValue = MUTEX_HASH_VALUE(object);
1142 entry = &mutexHashTable[hashValue];
1144 if (entry->object == object) {
1145 internal_unlock_mutex(&entry->mutex);
1148 while (entry->next != 0 && entry->next->object != object)
1149 entry = entry->next;
1151 assert(entry->next != 0);
1153 internal_unlock_mutex(&entry->next->mutex);
1155 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1156 mutexHashEntry *unlinked = entry->next;
1158 entry->next = unlinked->next;
1159 unlinked->next = firstFreeOverflowEntry;
1160 firstFreeOverflowEntry = unlinked;
1167 void builtin_monitorenter(java_objectheader *o)
1169 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1172 log_text("Monitor enter");
1174 assert(blockInts == 0);
1178 hashValue = MUTEX_HASH_VALUE(o);
1179 if (mutexHashTable[hashValue].object == o
1180 && mutexHashTable[hashValue].mutex.holder == currentThread)
1181 ++mutexHashTable[hashValue].mutex.count;
1183 internal_lock_mutex_for_object(o);
1187 assert(blockInts == 0);
1192 void builtin_monitorexit (java_objectheader *o)
1195 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1198 log_text("Monitor leave");
1200 assert(blockInts == 0);
1204 hashValue = MUTEX_HASH_VALUE(o);
1205 if (mutexHashTable[hashValue].object == o) {
1206 if (mutexHashTable[hashValue].mutex.count == 1
1207 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1208 internal_unlock_mutex_for_object(o);
1210 --mutexHashTable[hashValue].mutex.count;
1213 internal_unlock_mutex_for_object(o);
1217 assert(blockInts == 0);
1222 /*****************************************************************************
1223 MISCELLANEOUS HELPER FUNCTIONS
1224 *****************************************************************************/
1228 /*********** Functions for integer divisions *****************************
1230 On some systems (eg. DEC ALPHA), integer division is not supported by the
1231 CPU. These helper functions implement the missing functionality.
1233 ******************************************************************************/
1235 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1236 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1239 /************** Functions for long arithmetics *******************************
1241 On systems where 64 bit Integers are not supported by the CPU, these
1242 functions are needed.
1244 ******************************************************************************/
1247 s8 builtin_ladd(s8 a, s8 b)
1252 return builtin_i2l(0);
1256 s8 builtin_lsub(s8 a, s8 b)
1261 return builtin_i2l(0);
1265 s8 builtin_lmul(s8 a, s8 b)
1270 return builtin_i2l(0);
1274 s8 builtin_ldiv(s8 a, s8 b)
1279 return builtin_i2l(0);
1283 s8 builtin_lrem(s8 a, s8 b)
1288 return builtin_i2l(0);
1292 s8 builtin_lshl(s8 a, s4 b)
1295 return a << (b & 63);
1297 return builtin_i2l(0);
1301 s8 builtin_lshr(s8 a, s4 b)
1304 return a >> (b & 63);
1306 return builtin_i2l(0);
1310 s8 builtin_lushr(s8 a, s4 b)
1313 return ((u8) a) >> (b & 63);
1315 return builtin_i2l(0);
1319 s8 builtin_land(s8 a, s8 b)
1324 return builtin_i2l(0);
1328 s8 builtin_lor(s8 a, s8 b)
1333 return builtin_i2l(0);
1337 s8 builtin_lxor(s8 a, s8 b)
1342 return builtin_i2l(0);
1346 s8 builtin_lneg(s8 a)
1351 return builtin_i2l(0);
1355 s4 builtin_lcmp(s8 a, s8 b)
1358 if (a < b) return -1;
1359 if (a > b) return 1;
1370 /*********** Functions for floating point operations *************************/
1372 float builtin_fadd(float a, float b)
1374 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1375 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1386 if (copysignf(1.0, a) == copysignf(1.0, b))
1389 return intBitsToFloat(FLT_NAN);
1395 float builtin_fsub(float a, float b)
1397 return builtin_fadd(a, builtin_fneg(b));
1401 float builtin_fmul(float a, float b)
1403 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1404 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1406 if (finitef(b)) return a * b;
1408 if (a == 0) return intBitsToFloat(FLT_NAN);
1409 else return copysignf(b, copysignf(1.0, b)*a);
1414 if (b == 0) return intBitsToFloat(FLT_NAN);
1415 else return copysignf(a, copysignf(1.0, a)*b);
1418 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1424 float builtin_fdiv(float a, float b)
1426 if (finitef(a) && finitef(b)) {
1431 return intBitsToFloat(FLT_POSINF);
1433 return intBitsToFloat(FLT_NEGINF);
1436 return intBitsToFloat(FLT_NAN);
1440 float builtin_frem(float a, float b)
1446 float builtin_fneg(float a)
1448 if (isnanf(a)) return a;
1450 if (finitef(a)) return -a;
1451 else return copysignf(a, -copysignf(1.0, a));
1456 s4 builtin_fcmpl(float a, float b)
1458 if (isnanf(a)) return -1;
1459 if (isnanf(b)) return -1;
1460 if (!finitef(a) || !finitef(b)) {
1461 a = finitef(a) ? 0 : copysignf(1.0, a);
1462 b = finitef(b) ? 0 : copysignf(1.0, b);
1464 if (a > b) return 1;
1465 if (a == b) return 0;
1470 s4 builtin_fcmpg(float a, float b)
1472 if (isnanf(a)) return 1;
1473 if (isnanf(b)) return 1;
1474 if (!finitef(a) || !finitef(b)) {
1475 a = finitef(a) ? 0 : copysignf(1.0, a);
1476 b = finitef(b) ? 0 : copysignf(1.0, b);
1478 if (a > b) return 1;
1479 if (a == b) return 0;
1485 /************************* Functions for doubles ****************************/
1487 double builtin_dadd(double a, double b)
1489 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1490 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1492 if (finite(b)) return a + b;
1496 if (finite(b)) return a;
1498 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1499 else return longBitsToDouble(DBL_NAN);
1505 double builtin_dsub(double a, double b)
1507 return builtin_dadd(a, builtin_dneg(b));
1511 double builtin_dmul(double a, double b)
1513 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1514 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1516 if (finite(b)) return a * b;
1518 if (a == 0) return longBitsToDouble(DBL_NAN);
1519 else return copysign(b, copysign(1.0, b) * a);
1524 if (b == 0) return longBitsToDouble(DBL_NAN);
1525 else return copysign(a, copysign(1.0, a) * b);
1528 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1534 double builtin_ddiv(double a, double b)
1542 return longBitsToDouble(DBL_NAN);
1544 return copysign(0.0, b);
1550 return longBitsToDouble(DBL_POSINF);
1552 return longBitsToDouble(DBL_NEGINF);
1555 return longBitsToDouble(DBL_NAN);
1558 /* if (finite(a) && finite(b)) { */
1563 /* return longBitsToDouble(DBL_POSINF); */
1564 /* else if (a < 0) */
1565 /* return longBitsToDouble(DBL_NEGINF); */
1569 /* keep compiler happy */
1574 double builtin_drem(double a, double b)
1580 double builtin_dneg(double a)
1582 if (isnan(a)) return a;
1584 if (finite(a)) return -a;
1585 else return copysign(a, -copysign(1.0, a));
1590 s4 builtin_dcmpl(double a, double b)
1592 if (isnan(a)) return -1;
1593 if (isnan(b)) return -1;
1594 if (!finite(a) || !finite(b)) {
1595 a = finite(a) ? 0 : copysign(1.0, a);
1596 b = finite(b) ? 0 : copysign(1.0, b);
1598 if (a > b) return 1;
1599 if (a == b) return 0;
1604 s4 builtin_dcmpg(double a, double b)
1606 if (isnan(a)) return 1;
1607 if (isnan(b)) return 1;
1608 if (!finite(a) || !finite(b)) {
1609 a = finite(a) ? 0 : copysign(1.0, a);
1610 b = finite(b) ? 0 : copysign(1.0, b);
1612 if (a > b) return 1;
1613 if (a == b) return 0;
1618 /*********************** Conversion operations ****************************/
1620 s8 builtin_i2l(s4 i)
1633 float builtin_i2f(s4 a)
1635 float f = (float) a;
1640 double builtin_i2d(s4 a)
1642 double d = (double) a;
1647 s4 builtin_l2i(s8 l)
1657 float builtin_l2f(s8 a)
1660 float f = (float) a;
1668 double builtin_l2d(s8 a)
1671 double d = (double) a;
1679 s4 builtin_f2i(float a)
1682 return builtin_d2i((double) a);
1691 if (a < (-2147483648))
1692 return (-2147483648);
1695 f = copysignf((float) 1.0, a);
1698 return (-2147483648); */
1702 s8 builtin_f2l(float a)
1705 return builtin_d2l((double) a);
1710 if (a > 9223372036854775807L)
1711 return 9223372036854775807L;
1712 if (a < (-9223372036854775808L))
1713 return (-9223372036854775808L);
1718 f = copysignf((float) 1.0, a);
1720 return 9223372036854775807L;
1721 return (-9223372036854775808L); */
1725 double builtin_f2d(float a)
1727 if (finitef(a)) return (double) a;
1730 return longBitsToDouble(DBL_NAN);
1732 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1737 s4 builtin_d2i(double a)
1742 if (a >= 2147483647)
1744 if (a <= (-2147483647-1))
1745 return (-2147483647-1);
1750 d = copysign(1.0, a);
1753 return (-2147483647-1);
1757 s8 builtin_d2l(double a)
1762 if (a >= 9223372036854775807LL)
1763 return 9223372036854775807LL;
1764 if (a <= (-9223372036854775807LL-1))
1765 return (-9223372036854775807LL-1);
1770 d = copysign(1.0, a);
1772 return 9223372036854775807LL;
1773 return (-9223372036854775807LL-1);
1777 float builtin_d2f(double a)
1783 return intBitsToFloat(FLT_NAN);
1785 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1790 /* used to convert FLT_xxx defines into float values */
1792 inline float intBitsToFloat(s4 i)
1801 /* used to convert DBL_xxx defines into double values */
1803 inline float longBitsToDouble(s8 l)
1812 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1814 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1819 panic("Internal error: builtin_dummy called (native function is missing)");
1820 return 0; /* for the compiler */
1824 inline methodinfo *builtin_asm_get_threadrootmethod() {
1825 return *threadrootmethod;
1830 builtin_asm_get_stackframeinfo(){
1831 /*log_text("builtin_asm_get_stackframeinfo()");*/
1832 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1833 #ifdef HAVE___THREAD
1834 return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1836 return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1840 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1841 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1845 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1846 /* stacktraceelement *el;*/
1849 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1850 *el=GCNEW(stacktraceelement,s+1);
1851 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1853 (*el)[s].linenumber=0;
1858 * These are local overrides for various environment variables in Emacs.
1859 * Please do not remove this and leave it at the end of the file, where
1860 * Emacs will automagically detect them.
1861 * ---------------------------------------------------------------------
1864 * indent-tabs-mode: t