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 951 2004-03-11 17:30:03Z 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 *****************************************************************************/
778 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
779 methodinfo *method, int *pos,
786 log_text("WARNING: unmatched methodindent--");
788 if (verbose || runverbose) {
789 printf("Exception ");
791 utf_display(_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(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++)
839 sprintf(logtext + methodindent, "called: ");
840 utf_sprint(logtext + strlen(logtext), method->class->name);
841 sprintf(logtext + strlen(logtext), ".");
842 utf_sprint(logtext + strlen(logtext), method->name);
843 utf_sprint(logtext + strlen(logtext), method->descriptor);
845 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
846 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
847 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
848 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
849 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
850 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
851 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
852 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
853 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
854 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
855 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
858 sprintf(logtext + strlen(logtext), "(");
860 switch (method->paramcount) {
864 #if defined(__I386__)
866 sprintf(logtext+strlen(logtext), "%llx", a0);
870 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
874 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
878 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
883 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
888 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
889 a0, a1, a2, a3, a4, a5);
892 #if TRACE_ARGS_NUM > 6
894 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
895 a0, a1, a2, a3, a4, a5, a6);
899 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
900 a0, a1, a2, a3, a4, a5, a6, a7);
904 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
905 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
909 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
910 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
915 sprintf(logtext+strlen(logtext), "%lx", a0);
919 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
923 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
927 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
932 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
937 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
938 a0, a1, a2, a3, a4, a5);
941 #if TRACE_ARGS_NUM > 6
943 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
944 a0, a1, a2, a3, a4, a5, a6);
948 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
949 a0, a1, a2, a3, a4, a5, a6, a7);
953 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
954 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
958 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
959 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
964 sprintf (logtext+strlen(logtext), ")");
972 void builtin_displaymethodstart(methodinfo *method)
974 char logtext[MAXLOGTEXT];
975 sprintf(logtext, " ");
976 sprintf(logtext + methodindent, "called: ");
977 utf_sprint(logtext + strlen(logtext), method->class->name);
978 sprintf(logtext + strlen(logtext), ".");
979 utf_sprint(logtext + strlen(logtext), method->name);
980 utf_sprint(logtext + strlen(logtext), method->descriptor);
982 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
983 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
984 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
985 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
986 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
987 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
988 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
989 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
990 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
991 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
992 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
999 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1002 char logtext[MAXLOGTEXT];
1003 for (i = 0; i < methodindent; i++)
1008 log_text("WARNING: unmatched methodindent--");
1009 sprintf(logtext + methodindent, "finished: ");
1010 utf_sprint(logtext + strlen(logtext), method->class->name);
1011 sprintf(logtext + strlen(logtext), ".");
1012 utf_sprint(logtext + strlen(logtext), method->name);
1013 utf_sprint(logtext + strlen(logtext), method->descriptor);
1015 switch (method->returntype) {
1017 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1020 #if defined(__I386__)
1021 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1023 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1027 #if defined(__I386__)
1028 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1030 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1034 sprintf(logtext + strlen(logtext), "->%g", f);
1037 sprintf(logtext + strlen(logtext), "->%g", d);
1044 void builtin_displaymethodexception(methodinfo *method)
1047 char logtext[MAXLOGTEXT];
1048 for (i = 0; i < methodindent; i++)
1050 sprintf(logtext + methodindent, "exception abort: ");
1051 utf_sprint(logtext + strlen(logtext), method->class->name);
1052 sprintf(logtext + strlen(logtext), ".");
1053 utf_sprint(logtext + strlen(logtext), method->name);
1054 utf_sprint(logtext + strlen(logtext), method->descriptor);
1059 /****************************************************************************
1060 SYNCHRONIZATION FUNCTIONS
1061 *****************************************************************************/
1064 * Lock the mutex of an object.
1066 void internal_lock_mutex_for_object(java_objectheader *object)
1068 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1069 mutexHashEntry *entry;
1072 assert(object != 0);
1074 hashValue = MUTEX_HASH_VALUE(object);
1075 entry = &mutexHashTable[hashValue];
1077 if (entry->object != 0) {
1078 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1080 entry->mutex.holder = 0;
1081 entry->mutex.count = 0;
1082 entry->mutex.muxWaiters = 0;
1085 while (entry->next != 0 && entry->object != object)
1086 entry = entry->next;
1088 if (entry->object != object) {
1089 entry->next = firstFreeOverflowEntry;
1090 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1092 entry = entry->next;
1095 assert(entry->conditionCount == 0);
1100 entry->mutex.holder = 0;
1101 entry->mutex.count = 0;
1102 entry->mutex.muxWaiters = 0;
1105 if (entry->object == 0)
1106 entry->object = object;
1108 internal_lock_mutex(&entry->mutex);
1114 * Unlocks the mutex of an object.
1116 void internal_unlock_mutex_for_object (java_objectheader *object)
1118 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1120 mutexHashEntry *entry;
1122 hashValue = MUTEX_HASH_VALUE(object);
1123 entry = &mutexHashTable[hashValue];
1125 if (entry->object == object) {
1126 internal_unlock_mutex(&entry->mutex);
1129 while (entry->next != 0 && entry->next->object != object)
1130 entry = entry->next;
1132 assert(entry->next != 0);
1134 internal_unlock_mutex(&entry->next->mutex);
1136 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1137 mutexHashEntry *unlinked = entry->next;
1139 entry->next = unlinked->next;
1140 unlinked->next = firstFreeOverflowEntry;
1141 firstFreeOverflowEntry = unlinked;
1148 void builtin_monitorenter(java_objectheader *o)
1150 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1153 assert(blockInts == 0);
1157 hashValue = MUTEX_HASH_VALUE(o);
1158 if (mutexHashTable[hashValue].object == o
1159 && mutexHashTable[hashValue].mutex.holder == currentThread)
1160 ++mutexHashTable[hashValue].mutex.count;
1162 internal_lock_mutex_for_object(o);
1166 assert(blockInts == 0);
1171 void builtin_monitorexit (java_objectheader *o)
1173 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1176 assert(blockInts == 0);
1180 hashValue = MUTEX_HASH_VALUE(o);
1181 if (mutexHashTable[hashValue].object == o) {
1182 if (mutexHashTable[hashValue].mutex.count == 1
1183 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1184 internal_unlock_mutex_for_object(o);
1186 --mutexHashTable[hashValue].mutex.count;
1189 internal_unlock_mutex_for_object(o);
1193 assert(blockInts == 0);
1198 /*****************************************************************************
1199 MISCELLANEOUS HELPER FUNCTIONS
1200 *****************************************************************************/
1204 /*********** Functions for integer divisions *****************************
1206 On some systems (eg. DEC ALPHA), integer division is not supported by the
1207 CPU. These helper functions implement the missing functionality.
1209 ******************************************************************************/
1211 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1212 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1215 /************** Functions for long arithmetics *******************************
1217 On systems where 64 bit Integers are not supported by the CPU, these
1218 functions are needed.
1220 ******************************************************************************/
1223 s8 builtin_ladd(s8 a, s8 b)
1228 return builtin_i2l(0);
1232 s8 builtin_lsub(s8 a, s8 b)
1237 return builtin_i2l(0);
1241 s8 builtin_lmul(s8 a, s8 b)
1246 return builtin_i2l(0);
1250 s8 builtin_ldiv(s8 a, s8 b)
1255 return builtin_i2l(0);
1259 s8 builtin_lrem(s8 a, s8 b)
1264 return builtin_i2l(0);
1268 s8 builtin_lshl(s8 a, s4 b)
1271 return a << (b & 63);
1273 return builtin_i2l(0);
1277 s8 builtin_lshr(s8 a, s4 b)
1280 return a >> (b & 63);
1282 return builtin_i2l(0);
1286 s8 builtin_lushr(s8 a, s4 b)
1289 return ((u8) a) >> (b & 63);
1291 return builtin_i2l(0);
1295 s8 builtin_land(s8 a, s8 b)
1300 return builtin_i2l(0);
1304 s8 builtin_lor(s8 a, s8 b)
1309 return builtin_i2l(0);
1313 s8 builtin_lxor(s8 a, s8 b)
1318 return builtin_i2l(0);
1322 s8 builtin_lneg(s8 a)
1327 return builtin_i2l(0);
1331 s4 builtin_lcmp(s8 a, s8 b)
1334 if (a < b) return -1;
1335 if (a > b) return 1;
1346 /*********** Functions for floating point operations *************************/
1348 float builtin_fadd(float a, float b)
1350 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1351 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1362 if (copysignf(1.0, a) == copysignf(1.0, b))
1365 return intBitsToFloat(FLT_NAN);
1371 float builtin_fsub(float a, float b)
1373 return builtin_fadd(a, builtin_fneg(b));
1377 float builtin_fmul(float a, float b)
1379 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1380 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1382 if (finitef(b)) return a * b;
1384 if (a == 0) return intBitsToFloat(FLT_NAN);
1385 else return copysignf(b, copysignf(1.0, b)*a);
1390 if (b == 0) return intBitsToFloat(FLT_NAN);
1391 else return copysignf(a, copysignf(1.0, a)*b);
1394 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1400 float builtin_fdiv(float a, float b)
1402 if (finitef(a) && finitef(b)) {
1407 return intBitsToFloat(FLT_POSINF);
1409 return intBitsToFloat(FLT_NEGINF);
1412 return intBitsToFloat(FLT_NAN);
1416 float builtin_frem(float a, float b)
1422 float builtin_fneg(float a)
1424 if (isnanf(a)) return a;
1426 if (finitef(a)) return -a;
1427 else return copysignf(a, -copysignf(1.0, a));
1432 s4 builtin_fcmpl(float a, float b)
1434 if (isnanf(a)) return -1;
1435 if (isnanf(b)) return -1;
1436 if (!finitef(a) || !finitef(b)) {
1437 a = finitef(a) ? 0 : copysignf(1.0, a);
1438 b = finitef(b) ? 0 : copysignf(1.0, b);
1440 if (a > b) return 1;
1441 if (a == b) return 0;
1446 s4 builtin_fcmpg(float a, float b)
1448 if (isnanf(a)) return 1;
1449 if (isnanf(b)) return 1;
1450 if (!finitef(a) || !finitef(b)) {
1451 a = finitef(a) ? 0 : copysignf(1.0, a);
1452 b = finitef(b) ? 0 : copysignf(1.0, b);
1454 if (a > b) return 1;
1455 if (a == b) return 0;
1461 /************************* Functions for doubles ****************************/
1463 double builtin_dadd(double a, double b)
1465 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1466 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1468 if (finite(b)) return a + b;
1472 if (finite(b)) return a;
1474 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1475 else return longBitsToDouble(DBL_NAN);
1481 double builtin_dsub(double a, double b)
1483 return builtin_dadd(a, builtin_dneg(b));
1487 double builtin_dmul(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;
1494 if (a == 0) return longBitsToDouble(DBL_NAN);
1495 else return copysign(b, copysign(1.0, b) * a);
1500 if (b == 0) return longBitsToDouble(DBL_NAN);
1501 else return copysign(a, copysign(1.0, a) * b);
1504 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1510 double builtin_ddiv(double a, double b)
1518 return longBitsToDouble(DBL_NAN);
1520 return copysign(0.0, b);
1526 return longBitsToDouble(DBL_POSINF);
1528 return longBitsToDouble(DBL_NEGINF);
1531 return longBitsToDouble(DBL_NAN);
1534 /* if (finite(a) && finite(b)) { */
1539 /* return longBitsToDouble(DBL_POSINF); */
1540 /* else if (a < 0) */
1541 /* return longBitsToDouble(DBL_NEGINF); */
1545 /* keep compiler happy */
1550 double builtin_drem(double a, double b)
1556 double builtin_dneg(double a)
1558 if (isnan(a)) return a;
1560 if (finite(a)) return -a;
1561 else return copysign(a, -copysign(1.0, a));
1566 s4 builtin_dcmpl(double a, double b)
1568 if (isnan(a)) return -1;
1569 if (isnan(b)) return -1;
1570 if (!finite(a) || !finite(b)) {
1571 a = finite(a) ? 0 : copysign(1.0, a);
1572 b = finite(b) ? 0 : copysign(1.0, b);
1574 if (a > b) return 1;
1575 if (a == b) return 0;
1580 s4 builtin_dcmpg(double a, double b)
1582 if (isnan(a)) return 1;
1583 if (isnan(b)) return 1;
1584 if (!finite(a) || !finite(b)) {
1585 a = finite(a) ? 0 : copysign(1.0, a);
1586 b = finite(b) ? 0 : copysign(1.0, b);
1588 if (a > b) return 1;
1589 if (a == b) return 0;
1594 /*********************** Conversion operations ****************************/
1596 s8 builtin_i2l(s4 i)
1609 float builtin_i2f(s4 a)
1611 float f = (float) a;
1616 double builtin_i2d(s4 a)
1618 double d = (double) a;
1623 s4 builtin_l2i(s8 l)
1633 float builtin_l2f(s8 a)
1636 float f = (float) a;
1644 double builtin_l2d(s8 a)
1647 double d = (double) a;
1655 s4 builtin_f2i(float a)
1658 return builtin_d2i((double) a);
1667 if (a < (-2147483648))
1668 return (-2147483648);
1671 f = copysignf((float) 1.0, a);
1674 return (-2147483648); */
1678 s8 builtin_f2l(float a)
1681 return builtin_d2l((double) a);
1686 if (a > 9223372036854775807L)
1687 return 9223372036854775807L;
1688 if (a < (-9223372036854775808L))
1689 return (-9223372036854775808L);
1694 f = copysignf((float) 1.0, a);
1696 return 9223372036854775807L;
1697 return (-9223372036854775808L); */
1701 double builtin_f2d(float a)
1703 if (finitef(a)) return (double) a;
1706 return longBitsToDouble(DBL_NAN);
1708 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1713 s4 builtin_d2i(double a)
1718 if (a >= 2147483647)
1720 if (a <= (-2147483647-1))
1721 return (-2147483647-1);
1726 d = copysign(1.0, a);
1729 return (-2147483647-1);
1733 s8 builtin_d2l(double a)
1738 if (a >= 9223372036854775807LL)
1739 return 9223372036854775807LL;
1740 if (a <= (-9223372036854775807LL-1))
1741 return (-9223372036854775807LL-1);
1746 d = copysign(1.0, a);
1748 return 9223372036854775807LL;
1749 return (-9223372036854775807LL-1);
1753 float builtin_d2f(double a)
1759 return intBitsToFloat(FLT_NAN);
1761 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1766 /* used to convert FLT_xxx defines into float values */
1768 inline float intBitsToFloat(s4 i)
1777 /* used to convert DBL_xxx defines into double values */
1779 inline float longBitsToDouble(s8 l)
1788 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1790 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1795 panic("Internal error: builtin_dummy called (native function is missing)");
1796 return 0; /* for the compiler */
1800 inline methodinfo *builtin_asm_get_threadrootmethod() {
1801 return *threadrootmethod;
1806 builtin_asm_get_stackframeinfo(){
1807 /*log_text("builtin_asm_get_stackframeinfo()");*/
1808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1809 #ifdef HAVE___THREAD
1810 return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1812 return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1816 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1817 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1822 * These are local overrides for various environment variables in Emacs.
1823 * Please do not remove this and leave it at the end of the file, where
1824 * Emacs will automagically detect them.
1825 * ---------------------------------------------------------------------
1828 * indent-tabs-mode: t