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 963 2004-03-15 07:37:49Z 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 assert(blockInts == 0);
1176 hashValue = MUTEX_HASH_VALUE(o);
1177 if (mutexHashTable[hashValue].object == o
1178 && mutexHashTable[hashValue].mutex.holder == currentThread)
1179 ++mutexHashTable[hashValue].mutex.count;
1181 internal_lock_mutex_for_object(o);
1185 assert(blockInts == 0);
1190 void builtin_monitorexit (java_objectheader *o)
1192 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1195 assert(blockInts == 0);
1199 hashValue = MUTEX_HASH_VALUE(o);
1200 if (mutexHashTable[hashValue].object == o) {
1201 if (mutexHashTable[hashValue].mutex.count == 1
1202 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1203 internal_unlock_mutex_for_object(o);
1205 --mutexHashTable[hashValue].mutex.count;
1208 internal_unlock_mutex_for_object(o);
1212 assert(blockInts == 0);
1217 /*****************************************************************************
1218 MISCELLANEOUS HELPER FUNCTIONS
1219 *****************************************************************************/
1223 /*********** Functions for integer divisions *****************************
1225 On some systems (eg. DEC ALPHA), integer division is not supported by the
1226 CPU. These helper functions implement the missing functionality.
1228 ******************************************************************************/
1230 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1231 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1234 /************** Functions for long arithmetics *******************************
1236 On systems where 64 bit Integers are not supported by the CPU, these
1237 functions are needed.
1239 ******************************************************************************/
1242 s8 builtin_ladd(s8 a, s8 b)
1247 return builtin_i2l(0);
1251 s8 builtin_lsub(s8 a, s8 b)
1256 return builtin_i2l(0);
1260 s8 builtin_lmul(s8 a, s8 b)
1265 return builtin_i2l(0);
1269 s8 builtin_ldiv(s8 a, s8 b)
1274 return builtin_i2l(0);
1278 s8 builtin_lrem(s8 a, s8 b)
1283 return builtin_i2l(0);
1287 s8 builtin_lshl(s8 a, s4 b)
1290 return a << (b & 63);
1292 return builtin_i2l(0);
1296 s8 builtin_lshr(s8 a, s4 b)
1299 return a >> (b & 63);
1301 return builtin_i2l(0);
1305 s8 builtin_lushr(s8 a, s4 b)
1308 return ((u8) a) >> (b & 63);
1310 return builtin_i2l(0);
1314 s8 builtin_land(s8 a, s8 b)
1319 return builtin_i2l(0);
1323 s8 builtin_lor(s8 a, s8 b)
1328 return builtin_i2l(0);
1332 s8 builtin_lxor(s8 a, s8 b)
1337 return builtin_i2l(0);
1341 s8 builtin_lneg(s8 a)
1346 return builtin_i2l(0);
1350 s4 builtin_lcmp(s8 a, s8 b)
1353 if (a < b) return -1;
1354 if (a > b) return 1;
1365 /*********** Functions for floating point operations *************************/
1367 float builtin_fadd(float a, float b)
1369 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1370 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1381 if (copysignf(1.0, a) == copysignf(1.0, b))
1384 return intBitsToFloat(FLT_NAN);
1390 float builtin_fsub(float a, float b)
1392 return builtin_fadd(a, builtin_fneg(b));
1396 float builtin_fmul(float a, float b)
1398 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1399 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1401 if (finitef(b)) return a * b;
1403 if (a == 0) return intBitsToFloat(FLT_NAN);
1404 else return copysignf(b, copysignf(1.0, b)*a);
1409 if (b == 0) return intBitsToFloat(FLT_NAN);
1410 else return copysignf(a, copysignf(1.0, a)*b);
1413 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1419 float builtin_fdiv(float a, float b)
1421 if (finitef(a) && finitef(b)) {
1426 return intBitsToFloat(FLT_POSINF);
1428 return intBitsToFloat(FLT_NEGINF);
1431 return intBitsToFloat(FLT_NAN);
1435 float builtin_frem(float a, float b)
1441 float builtin_fneg(float a)
1443 if (isnanf(a)) return a;
1445 if (finitef(a)) return -a;
1446 else return copysignf(a, -copysignf(1.0, a));
1451 s4 builtin_fcmpl(float a, float b)
1453 if (isnanf(a)) return -1;
1454 if (isnanf(b)) return -1;
1455 if (!finitef(a) || !finitef(b)) {
1456 a = finitef(a) ? 0 : copysignf(1.0, a);
1457 b = finitef(b) ? 0 : copysignf(1.0, b);
1459 if (a > b) return 1;
1460 if (a == b) return 0;
1465 s4 builtin_fcmpg(float a, float b)
1467 if (isnanf(a)) return 1;
1468 if (isnanf(b)) return 1;
1469 if (!finitef(a) || !finitef(b)) {
1470 a = finitef(a) ? 0 : copysignf(1.0, a);
1471 b = finitef(b) ? 0 : copysignf(1.0, b);
1473 if (a > b) return 1;
1474 if (a == b) return 0;
1480 /************************* Functions for doubles ****************************/
1482 double builtin_dadd(double a, double b)
1484 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1485 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1487 if (finite(b)) return a + b;
1491 if (finite(b)) return a;
1493 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1494 else return longBitsToDouble(DBL_NAN);
1500 double builtin_dsub(double a, double b)
1502 return builtin_dadd(a, builtin_dneg(b));
1506 double builtin_dmul(double a, double b)
1508 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1509 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1511 if (finite(b)) return a * b;
1513 if (a == 0) return longBitsToDouble(DBL_NAN);
1514 else return copysign(b, copysign(1.0, b) * a);
1519 if (b == 0) return longBitsToDouble(DBL_NAN);
1520 else return copysign(a, copysign(1.0, a) * b);
1523 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1529 double builtin_ddiv(double a, double b)
1537 return longBitsToDouble(DBL_NAN);
1539 return copysign(0.0, b);
1545 return longBitsToDouble(DBL_POSINF);
1547 return longBitsToDouble(DBL_NEGINF);
1550 return longBitsToDouble(DBL_NAN);
1553 /* if (finite(a) && finite(b)) { */
1558 /* return longBitsToDouble(DBL_POSINF); */
1559 /* else if (a < 0) */
1560 /* return longBitsToDouble(DBL_NEGINF); */
1564 /* keep compiler happy */
1569 double builtin_drem(double a, double b)
1575 double builtin_dneg(double a)
1577 if (isnan(a)) return a;
1579 if (finite(a)) return -a;
1580 else return copysign(a, -copysign(1.0, a));
1585 s4 builtin_dcmpl(double a, double b)
1587 if (isnan(a)) return -1;
1588 if (isnan(b)) return -1;
1589 if (!finite(a) || !finite(b)) {
1590 a = finite(a) ? 0 : copysign(1.0, a);
1591 b = finite(b) ? 0 : copysign(1.0, b);
1593 if (a > b) return 1;
1594 if (a == b) return 0;
1599 s4 builtin_dcmpg(double a, double b)
1601 if (isnan(a)) return 1;
1602 if (isnan(b)) return 1;
1603 if (!finite(a) || !finite(b)) {
1604 a = finite(a) ? 0 : copysign(1.0, a);
1605 b = finite(b) ? 0 : copysign(1.0, b);
1607 if (a > b) return 1;
1608 if (a == b) return 0;
1613 /*********************** Conversion operations ****************************/
1615 s8 builtin_i2l(s4 i)
1628 float builtin_i2f(s4 a)
1630 float f = (float) a;
1635 double builtin_i2d(s4 a)
1637 double d = (double) a;
1642 s4 builtin_l2i(s8 l)
1652 float builtin_l2f(s8 a)
1655 float f = (float) a;
1663 double builtin_l2d(s8 a)
1666 double d = (double) a;
1674 s4 builtin_f2i(float a)
1677 return builtin_d2i((double) a);
1686 if (a < (-2147483648))
1687 return (-2147483648);
1690 f = copysignf((float) 1.0, a);
1693 return (-2147483648); */
1697 s8 builtin_f2l(float a)
1700 return builtin_d2l((double) a);
1705 if (a > 9223372036854775807L)
1706 return 9223372036854775807L;
1707 if (a < (-9223372036854775808L))
1708 return (-9223372036854775808L);
1713 f = copysignf((float) 1.0, a);
1715 return 9223372036854775807L;
1716 return (-9223372036854775808L); */
1720 double builtin_f2d(float a)
1722 if (finitef(a)) return (double) a;
1725 return longBitsToDouble(DBL_NAN);
1727 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1732 s4 builtin_d2i(double a)
1737 if (a >= 2147483647)
1739 if (a <= (-2147483647-1))
1740 return (-2147483647-1);
1745 d = copysign(1.0, a);
1748 return (-2147483647-1);
1752 s8 builtin_d2l(double a)
1757 if (a >= 9223372036854775807LL)
1758 return 9223372036854775807LL;
1759 if (a <= (-9223372036854775807LL-1))
1760 return (-9223372036854775807LL-1);
1765 d = copysign(1.0, a);
1767 return 9223372036854775807LL;
1768 return (-9223372036854775807LL-1);
1772 float builtin_d2f(double a)
1778 return intBitsToFloat(FLT_NAN);
1780 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1785 /* used to convert FLT_xxx defines into float values */
1787 inline float intBitsToFloat(s4 i)
1796 /* used to convert DBL_xxx defines into double values */
1798 inline float longBitsToDouble(s8 l)
1807 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1809 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1814 panic("Internal error: builtin_dummy called (native function is missing)");
1815 return 0; /* for the compiler */
1819 inline methodinfo *builtin_asm_get_threadrootmethod() {
1820 return *threadrootmethod;
1825 builtin_asm_get_stackframeinfo(){
1826 /*log_text("builtin_asm_get_stackframeinfo()");*/
1827 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1828 #ifdef HAVE___THREAD
1829 return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1831 return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1835 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1836 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1840 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1841 /* stacktraceelement *el;*/
1844 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1845 *el=GCNEW(stacktraceelement,s+1);
1846 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1848 (*el)[s].linenumber=0;
1853 * These are local overrides for various environment variables in Emacs.
1854 * Please do not remove this and leave it at the end of the file, where
1855 * Emacs will automagically detect them.
1856 * ---------------------------------------------------------------------
1859 * indent-tabs-mode: t