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 1000 2004-03-30 22:42:57Z twisti $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.h"
61 #undef DEBUG /*define DEBUG 1*/
63 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
64 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
66 /*****************************************************************************
68 *****************************************************************************/
72 /*************** internal function: builtin_isanysubclass *********************
74 Checks a subclass relation between two classes. Implemented interfaces
75 are interpreted as super classes.
76 Return value: 1 ... sub is subclass of super
79 *****************************************************************************/
80 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
85 if (super->flags & ACC_INTERFACE)
86 return (sub->vftbl->interfacetablelength > super->index) &&
87 (sub->vftbl->interfacetable[-super->index] != NULL);
100 for (tmp=sub;tmp!=0;tmp=tmp->super) {
102 utf_display(tmp->name);
106 for (tmp=super;tmp!=0;tmp=tmp->super) {
108 utf_display(tmp->name);
113 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
114 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
115 super->vftbl->diffval); */
117 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
121 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
122 (unsigned) (super->vftbl->diffval);
124 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
131 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
136 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
140 if ((base = super->baseval) <= 0)
141 /* super is an interface */
142 res = (sub->interfacetablelength > -base) &&
143 (sub->interfacetable[base] != NULL);
145 res = (unsigned) (sub->baseval - base)
146 <= (unsigned) (super->diffval);
148 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
156 /****************** function: builtin_instanceof *****************************
158 Checks if an object is an instance of some given class (or subclass of
159 that class). If class is an interface, checks if the interface is
161 Return value: 1 ... obj is an instance of class or implements the interface
162 0 ... otherwise or if obj == NULL
164 *****************************************************************************/
166 /* XXX should use vftbl */
167 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
170 log_text ("builtin_instanceof called");
173 return builtin_isanysubclass (obj->vftbl->class, class);
178 /**************** function: builtin_checkcast *******************************
180 The same as builtin_instanceof except that 1 is returned when
183 ****************************************************************************/
185 /* XXX should use vftbl */
186 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
189 log_text("builtin_checkcast called");
194 if (builtin_isanysubclass(obj->vftbl->class, class))
198 printf("#### checkcast failed ");
199 utf_display(obj->vftbl->class->name);
201 utf_display(class->name);
209 /*********** internal function: builtin_descriptorscompatible ******************
211 Checks if two array type descriptors are assignment compatible
212 Return value: 1 ... target = desc is possible
215 ******************************************************************************/
217 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
219 if (desc==target) return 1;
220 if (desc->arraytype != target->arraytype) return 0;
221 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
223 /* {both arrays are arrays of references} */
224 if (desc->dimension == target->dimension) {
225 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
226 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
227 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
229 if (desc->dimension < target->dimension) return 0;
231 /* {desc has higher dimension than target} */
232 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
236 /******************** function: builtin_checkarraycast ***********************
238 Checks if an object is really a subtype of the requested array type.
239 The object has to be an array to begin with. For simple arrays (int, short,
240 double, etc.) the types have to match exactly.
241 For arrays of objects, the type of elements in the array has to be a
242 subtype (or the same type) of the requested element type. For arrays of
243 arrays (which in turn can again be arrays of arrays), the types at the
244 lowest level have to satisfy the corresponding sub class relation.
246 Return value: 1 ... cast is possible
249 ATTENTION: a cast with a NULL pointer is always possible.
251 *****************************************************************************/
253 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
255 arraydescriptor *desc;
258 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
260 return builtin_descriptorscompatible(desc, target->arraydesc);
264 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
267 return builtin_checkarraycast(obj, target);
271 /************************** exception functions *******************************
273 ******************************************************************************/
275 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
278 char logtext[MAXLOGTEXT];
279 sprintf(logtext, "Builtin exception thrown: ");
280 if (local_exceptionptr) {
281 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
284 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
288 *exceptionptr = local_exceptionptr;
289 return local_exceptionptr;
293 void builtin_reset_exceptionptr()
295 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
296 THREADINFO->_exceptionptr = NULL;
298 panic("builtin_reset_exceptionptr should not be used in this configuration");
303 /******************* function: builtin_canstore *******************************
305 Checks, if an object can be stored in an array.
306 Return value: 1 ... possible
309 ******************************************************************************/
311 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
313 arraydescriptor *desc;
314 arraydescriptor *valuedesc;
315 vftbl *componentvftbl;
322 /* The following is guaranteed (by verifier checks):
324 * *) a->...vftbl->arraydesc != NULL
325 * *) a->...vftbl->arraydesc->componentvftbl != NULL
326 * *) o->vftbl is not an interface vftbl
329 desc = a->header.objheader.vftbl->arraydesc;
330 componentvftbl = desc->componentvftbl;
331 valuevftbl = o->vftbl;
333 if ((dim_m1 = desc->dimension - 1) == 0) {
336 /* {a is a one-dimensional array} */
337 /* {a is an array of references} */
339 if (valuevftbl == componentvftbl)
342 if ((base = componentvftbl->baseval) <= 0)
343 /* an array of interface references */
344 return (valuevftbl->interfacetablelength > -base &&
345 valuevftbl->interfacetable[base] != NULL);
347 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
351 res = (unsigned)(valuevftbl->baseval - base)
352 <= (unsigned)(componentvftbl->diffval);
354 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
360 /* {a has dimension > 1} */
361 /* {componentvftbl->arraydesc != NULL} */
363 /* check if o is an array */
364 if ((valuedesc = valuevftbl->arraydesc) == NULL)
366 /* {o is an array} */
368 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
372 /* This is an optimized version where a is guaranteed to be one-dimensional */
373 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
375 arraydescriptor *desc;
383 /* The following is guaranteed (by verifier checks):
385 * *) a->...vftbl->arraydesc != NULL
386 * *) a->...vftbl->arraydesc->elementvftbl != NULL
387 * *) a->...vftbl->arraydesc->dimension == 1
388 * *) o->vftbl is not an interface vftbl
391 desc = a->header.objheader.vftbl->arraydesc;
392 elementvftbl = desc->elementvftbl;
393 valuevftbl = o->vftbl;
395 /* {a is a one-dimensional array} */
397 if (valuevftbl == elementvftbl)
400 if ((base = elementvftbl->baseval) <= 0)
401 /* an array of interface references */
402 return (valuevftbl->interfacetablelength > -base &&
403 valuevftbl->interfacetable[base] != NULL);
405 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
409 res = (unsigned)(valuevftbl->baseval - base)
410 <= (unsigned)(elementvftbl->diffval);
412 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
420 /* This is an optimized version where a is guaranteed to be a
421 * one-dimensional array of a class type */
422 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
430 /* The following is guaranteed (by verifier checks):
432 * *) a->...vftbl->arraydesc != NULL
433 * *) a->...vftbl->arraydesc->elementvftbl != NULL
434 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
435 * *) a->...vftbl->arraydesc->dimension == 1
436 * *) o->vftbl is not an interface vftbl
439 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
440 valuevftbl = o->vftbl;
442 /* {a is a one-dimensional array} */
444 if (valuevftbl == elementvftbl)
447 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
451 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
452 <= (unsigned)(elementvftbl->diffval);
454 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
462 /******************** Function: builtin_new **********************************
464 Creates a new instance of class c on the heap.
465 Return value: pointer to the object or NULL if no memory is
468 *****************************************************************************/
471 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
473 java_objectheader *builtin_new(classinfo *c)
475 java_objectheader *o;
476 /*DEBUGING - NOT THREAD SAFE*/
477 /* static long depth=0;
479 printf("Entering builtin_new:depth(%ld)",depth);*/
481 if (!c->initialized) {
483 char logtext[MAXLOGTEXT];
484 sprintf(logtext, "Initialize class ");
485 utf_sprint(logtext + strlen(logtext), c->name);
486 sprintf(logtext + strlen(logtext), " (from builtin_new)");
492 #ifdef SIZE_FROM_CLASSINFO
493 c->alignedsize = align_size(c->instancesize);
494 o = heap_allocate(c->alignedsize, true, c->finalizer);
496 o = heap_allocate(c->instancesize, true, c->finalizer);
499 /*DEBUGING - NOT THREAD SAFE*/
500 /*printf("Leaving builtin_new: depth(%ld): NULL",depth);
505 memset(o, 0, c->instancesize);
509 /*DEBUGING - NOT THREAD SAFE*/
510 /* printf("Leaving builtin_new: depth(%ld): object",depth);
515 /********************** Function: builtin_newarray **************************
517 Creates an array with the given vftbl on the heap.
519 Return value: pointer to the array or NULL if no memory is available
521 CAUTION: The given vftbl must be the vftbl of the *array* class,
522 not of the element class.
524 *****************************************************************************/
526 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
529 arraydescriptor *desc = arrayvftbl->arraydesc;
530 s4 dataoffset = desc->dataoffset;
531 s4 componentsize = desc->componentsize;
535 *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException);
539 #ifdef SIZE_FROM_CLASSINFO
540 actualsize = align_size(dataoffset + size * componentsize);
541 actualsize = dataoffset + size * componentsize;
544 if (((u4) actualsize) < ((u4) size)) { /* overflow */
545 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
549 a = heap_allocate(actualsize,
550 (desc->arraytype == ARRAYTYPE_OBJECT),
556 memset(a, 0, actualsize);
558 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
560 a->objheader.vftbl = arrayvftbl;
562 #ifdef SIZE_FROM_CLASSINFO
563 a->alignedsize = actualsize;
570 /********************** Function: builtin_anewarray *************************
572 Creates an array of references to the given class type on the heap.
574 Return value: pointer to the array or NULL if no memory is available
576 XXX This function does not do The Right Thing, because it uses a
577 classinfo pointer at runtime. builtin_newarray should be used
580 *****************************************************************************/
582 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
585 printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
586 printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
587 utf_display(component->vftbl->class->name);
588 printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
589 utf_display(component->super->name);*/
590 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
594 /******************** Function: builtin_newarray_int ***********************
596 Creates an array of 32 bit Integers on the heap.
598 Return value: pointer to the array or NULL if no memory is available
600 *****************************************************************************/
602 java_intarray *builtin_newarray_int(s4 size)
604 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
608 /******************** Function: builtin_newarray_long ***********************
610 Creates an array of 64 bit Integers on the heap.
612 Return value: pointer to the array or NULL if no memory is available
614 *****************************************************************************/
616 java_longarray *builtin_newarray_long(s4 size)
618 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
622 /******************** function: builtin_newarray_float ***********************
624 Creates an array of 32 bit IEEE floats on the heap.
626 Return value: pointer to the array or NULL if no memory is available
628 *****************************************************************************/
630 java_floatarray *builtin_newarray_float(s4 size)
632 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
636 /******************** function: builtin_newarray_double ***********************
638 Creates an array of 64 bit IEEE floats on the heap.
640 Return value: pointer to the array or NULL if no memory is available
642 *****************************************************************************/
644 java_doublearray *builtin_newarray_double(s4 size)
646 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
650 /******************** function: builtin_newarray_byte ***********************
652 Creates an array of 8 bit Integers on the heap.
654 Return value: pointer to the array or NULL if no memory is available
656 *****************************************************************************/
658 java_bytearray *builtin_newarray_byte(s4 size)
660 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
664 /******************** function: builtin_newarray_char ************************
666 Creates an array of characters on the heap.
668 Return value: pointer to the array or NULL if no memory is available
670 *****************************************************************************/
672 java_chararray *builtin_newarray_char(s4 size)
674 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
678 /******************** function: builtin_newarray_short ***********************
680 Creates an array of 16 bit Integers on the heap.
682 Return value: pointer to the array or NULL if no memory is available
684 *****************************************************************************/
686 java_shortarray *builtin_newarray_short(s4 size)
688 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
692 /******************** function: builtin_newarray_boolean ************************
694 Creates an array of bytes on the heap. The array is designated as an array
695 of booleans (important for casts)
697 Return value: pointer to the array or NULL if no memory is available
699 *****************************************************************************/
701 java_booleanarray *builtin_newarray_boolean(s4 size)
703 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
707 /**************** function: builtin_nmultianewarray ***************************
709 Creates a multi-dimensional array on the heap. The dimensions are passed in
713 n............number of dimensions to create
714 arrayvftbl...vftbl of the array class
715 dims.........array containing the size of each dimension to create
717 Return value: pointer to the array or NULL if no memory is available
719 ******************************************************************************/
721 /* Helper functions */
723 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
727 vftbl *componentvftbl;
729 /* create this dimension */
730 size = (int) dims[0];
731 a = builtin_newarray(size,arrayvftbl);
734 /* if this is the last dimension return */
737 /* get the vftbl of the components to create */
738 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
740 /* The verifier guarantees this. */
741 /* if (!componentvftbl) */
742 /* panic ("multianewarray with too many dimensions"); */
744 /* create the component arrays */
745 for (i = 0; i < size; i++) {
746 java_arrayheader *ea =
747 builtin_nmultianewarray(n,componentvftbl,dims+1);
748 if (!ea) return NULL;
749 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
756 /*****************************************************************************
759 Various functions for printing a message at method entry or exit (for
762 *****************************************************************************/
766 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
776 log_text("WARNING: unmatched methodindent--");
778 if (verbose || runverbose || verboseexception) {
780 printf("Exception ");
781 utf_display(_exceptionptr->vftbl->class->name);
784 printf("Some Throwable");
786 printf(" thrown in ");
789 utf_display_classname(method->class->name);
791 utf_display(method->name);
792 if (method->flags & ACC_SYNCHRONIZED)
796 if (method->flags & ACC_NATIVE) {
798 printf(")(%p) at position %p\n", method->entrypoint, pos);
800 printf(")(%p) at position %p (",method->entrypoint,pos);
801 if (method->class->sourcefile==NULL)
802 printf("<NO CLASSFILE INFORMATION>");
804 utf_display(method->class->sourcefile);
805 printf(":%d)\n",line);
809 printf("call_java_method\n");
813 return _exceptionptr;
817 #ifdef TRACE_ARGS_NUM
818 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
819 #if TRACE_ARGS_NUM > 6
825 char logtext[MAXLOGTEXT];
826 for (i = 0; i < methodindent; i++)
829 sprintf(logtext + methodindent, "called: ");
830 utf_sprint(logtext + strlen(logtext), method->class->name);
831 sprintf(logtext + strlen(logtext), ".");
832 utf_sprint(logtext + strlen(logtext), method->name);
833 utf_sprint(logtext + strlen(logtext), method->descriptor);
835 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
836 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
837 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
838 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
839 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
840 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
841 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
842 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
843 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
844 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
845 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
848 sprintf(logtext + strlen(logtext), "(");
850 switch (method->paramcount) {
854 #if defined(__I386__) || defined(__POWERPC__)
856 sprintf(logtext+strlen(logtext), "%llx", a0);
860 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
864 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
868 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
873 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
878 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
879 a0, a1, a2, a3, a4, a5);
882 #if TRACE_ARGS_NUM > 6
884 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
885 a0, a1, a2, a3, a4, a5, a6);
889 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
890 a0, a1, a2, a3, a4, a5, a6, a7);
894 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
895 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
899 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
900 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
905 sprintf(logtext+strlen(logtext), "%lx", a0);
909 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
913 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
917 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
922 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
927 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
928 a0, a1, a2, a3, a4, a5);
931 #if TRACE_ARGS_NUM > 6
933 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
934 a0, a1, a2, a3, a4, a5, a6);
938 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
939 a0, a1, a2, a3, a4, a5, a6, a7);
943 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
944 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
948 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
949 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
955 sprintf(logtext + strlen(logtext), ")");
963 void builtin_displaymethodstart(methodinfo *method)
965 char logtext[MAXLOGTEXT];
966 sprintf(logtext, " ");
967 sprintf(logtext + methodindent, "called: ");
968 utf_sprint(logtext + strlen(logtext), method->class->name);
969 sprintf(logtext + strlen(logtext), ".");
970 utf_sprint(logtext + strlen(logtext), method->name);
971 utf_sprint(logtext + strlen(logtext), method->descriptor);
973 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
974 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
975 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
976 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
977 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
978 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
979 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
980 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
981 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
982 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
983 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
990 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
993 char logtext[MAXLOGTEXT];
994 for (i = 0; i < methodindent; i++)
999 log_text("WARNING: unmatched methodindent--");
1001 sprintf(logtext + methodindent, "finished: ");
1002 utf_sprint(logtext + strlen(logtext), method->class->name);
1003 sprintf(logtext + strlen(logtext), ".");
1004 utf_sprint(logtext + strlen(logtext), method->name);
1005 utf_sprint(logtext + strlen(logtext), method->descriptor);
1007 switch (method->returntype) {
1009 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1013 #if defined(__I386__) || defined(__POWERPC__)
1014 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1016 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1021 #if defined(__I386__) || defined(__POWERPC__)
1022 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1024 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1029 sprintf(logtext + strlen(logtext), "->%g", f);
1033 sprintf(logtext + strlen(logtext), "->%g", d);
1040 void builtin_displaymethodexception(methodinfo *method)
1043 char logtext[MAXLOGTEXT];
1044 for (i = 0; i < methodindent; i++)
1046 sprintf(logtext + methodindent, "exception abort: ");
1047 utf_sprint(logtext + strlen(logtext), method->class->name);
1048 sprintf(logtext + strlen(logtext), ".");
1049 utf_sprint(logtext + strlen(logtext), method->name);
1050 utf_sprint(logtext + strlen(logtext), method->descriptor);
1055 /****************************************************************************
1056 SYNCHRONIZATION FUNCTIONS
1057 *****************************************************************************/
1060 * Lock the mutex of an object.
1062 void internal_lock_mutex_for_object(java_objectheader *object)
1064 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1065 mutexHashEntry *entry;
1068 assert(object != 0);
1070 hashValue = MUTEX_HASH_VALUE(object);
1071 entry = &mutexHashTable[hashValue];
1073 if (entry->object != 0) {
1074 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1076 entry->mutex.holder = 0;
1077 entry->mutex.count = 0;
1078 entry->mutex.muxWaiters = 0;
1081 while (entry->next != 0 && entry->object != object)
1082 entry = entry->next;
1084 if (entry->object != object) {
1085 entry->next = firstFreeOverflowEntry;
1086 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1088 entry = entry->next;
1091 assert(entry->conditionCount == 0);
1096 entry->mutex.holder = 0;
1097 entry->mutex.count = 0;
1098 entry->mutex.muxWaiters = 0;
1101 if (entry->object == 0)
1102 entry->object = object;
1104 internal_lock_mutex(&entry->mutex);
1110 * Unlocks the mutex of an object.
1112 void internal_unlock_mutex_for_object (java_objectheader *object)
1114 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1116 mutexHashEntry *entry;
1118 hashValue = MUTEX_HASH_VALUE(object);
1119 entry = &mutexHashTable[hashValue];
1121 if (entry->object == object) {
1122 internal_unlock_mutex(&entry->mutex);
1125 while (entry->next != 0 && entry->next->object != object)
1126 entry = entry->next;
1128 assert(entry->next != 0);
1130 internal_unlock_mutex(&entry->next->mutex);
1132 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1133 mutexHashEntry *unlinked = entry->next;
1135 entry->next = unlinked->next;
1136 unlinked->next = firstFreeOverflowEntry;
1137 firstFreeOverflowEntry = unlinked;
1144 void builtin_monitorenter(java_objectheader *o)
1146 #if defined(USE_THREADS)
1147 #if !defined(NATIVE_THREADS)
1150 /*log_text("Monitor enter");*/
1152 assert(blockInts == 0);
1156 hashValue = MUTEX_HASH_VALUE(o);
1157 if (mutexHashTable[hashValue].object == o
1158 && mutexHashTable[hashValue].mutex.holder == currentThread)
1159 ++mutexHashTable[hashValue].mutex.count;
1161 internal_lock_mutex_for_object(o);
1165 assert(blockInts == 0);
1167 monitorEnter((threadobject*) THREADOBJECT, o);
1173 void builtin_monitorexit (java_objectheader *o)
1176 #if defined(USE_THREADS)
1177 #if !defined(NATIVE_THREADS)
1180 /* log_text("Monitor leave"); */
1182 assert(blockInts == 0);
1186 hashValue = MUTEX_HASH_VALUE(o);
1187 if (mutexHashTable[hashValue].object == o) {
1188 if (mutexHashTable[hashValue].mutex.count == 1
1189 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1190 internal_unlock_mutex_for_object(o);
1192 --mutexHashTable[hashValue].mutex.count;
1195 internal_unlock_mutex_for_object(o);
1199 assert(blockInts == 0);
1201 monitorExit((threadobject*) THREADOBJECT, o);
1207 /*****************************************************************************
1208 MISCELLANEOUS HELPER FUNCTIONS
1209 *****************************************************************************/
1213 /*********** Functions for integer divisions *****************************
1215 On some systems (eg. DEC ALPHA), integer division is not supported by the
1216 CPU. These helper functions implement the missing functionality.
1218 ******************************************************************************/
1220 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1221 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1224 /************** Functions for long arithmetics *******************************
1226 On systems where 64 bit Integers are not supported by the CPU, these
1227 functions are needed.
1229 ******************************************************************************/
1232 s8 builtin_ladd(s8 a, s8 b)
1237 return builtin_i2l(0);
1241 s8 builtin_lsub(s8 a, s8 b)
1246 return builtin_i2l(0);
1250 s8 builtin_lmul(s8 a, s8 b)
1255 return builtin_i2l(0);
1259 s8 builtin_ldiv(s8 a, s8 b)
1264 return builtin_i2l(0);
1268 s8 builtin_lrem(s8 a, s8 b)
1273 return builtin_i2l(0);
1277 s8 builtin_lshl(s8 a, s4 b)
1280 return a << (b & 63);
1282 return builtin_i2l(0);
1286 s8 builtin_lshr(s8 a, s4 b)
1289 return a >> (b & 63);
1291 return builtin_i2l(0);
1295 s8 builtin_lushr(s8 a, s4 b)
1298 return ((u8) a) >> (b & 63);
1300 return builtin_i2l(0);
1304 s8 builtin_land(s8 a, s8 b)
1309 return builtin_i2l(0);
1313 s8 builtin_lor(s8 a, s8 b)
1318 return builtin_i2l(0);
1322 s8 builtin_lxor(s8 a, s8 b)
1327 return builtin_i2l(0);
1331 s8 builtin_lneg(s8 a)
1336 return builtin_i2l(0);
1340 s4 builtin_lcmp(s8 a, s8 b)
1343 if (a < b) return -1;
1344 if (a > b) return 1;
1355 /*********** Functions for floating point operations *************************/
1357 float builtin_fadd(float a, float b)
1359 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1360 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1371 if (copysignf(1.0, a) == copysignf(1.0, b))
1374 return intBitsToFloat(FLT_NAN);
1380 float builtin_fsub(float a, float b)
1382 return builtin_fadd(a, builtin_fneg(b));
1386 float builtin_fmul(float a, float b)
1388 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1389 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1391 if (finitef(b)) return a * b;
1393 if (a == 0) return intBitsToFloat(FLT_NAN);
1394 else return copysignf(b, copysignf(1.0, b)*a);
1399 if (b == 0) return intBitsToFloat(FLT_NAN);
1400 else return copysignf(a, copysignf(1.0, a)*b);
1403 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1409 float builtin_fdiv(float a, float b)
1411 if (finitef(a) && finitef(b)) {
1416 return intBitsToFloat(FLT_POSINF);
1418 return intBitsToFloat(FLT_NEGINF);
1421 return intBitsToFloat(FLT_NAN);
1425 float builtin_frem(float a, float b)
1431 float builtin_fneg(float a)
1433 if (isnanf(a)) return a;
1435 if (finitef(a)) return -a;
1436 else return copysignf(a, -copysignf(1.0, a));
1441 s4 builtin_fcmpl(float a, float b)
1443 if (isnanf(a)) return -1;
1444 if (isnanf(b)) return -1;
1445 if (!finitef(a) || !finitef(b)) {
1446 a = finitef(a) ? 0 : copysignf(1.0, a);
1447 b = finitef(b) ? 0 : copysignf(1.0, b);
1449 if (a > b) return 1;
1450 if (a == b) return 0;
1455 s4 builtin_fcmpg(float a, float b)
1457 if (isnanf(a)) return 1;
1458 if (isnanf(b)) return 1;
1459 if (!finitef(a) || !finitef(b)) {
1460 a = finitef(a) ? 0 : copysignf(1.0, a);
1461 b = finitef(b) ? 0 : copysignf(1.0, b);
1463 if (a > b) return 1;
1464 if (a == b) return 0;
1470 /************************* Functions for doubles ****************************/
1472 double builtin_dadd(double a, double b)
1474 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1475 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1477 if (finite(b)) return a + b;
1481 if (finite(b)) return a;
1483 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1484 else return longBitsToDouble(DBL_NAN);
1490 double builtin_dsub(double a, double b)
1492 return builtin_dadd(a, builtin_dneg(b));
1496 double builtin_dmul(double a, double b)
1498 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1499 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1501 if (finite(b)) return a * b;
1503 if (a == 0) return longBitsToDouble(DBL_NAN);
1504 else return copysign(b, copysign(1.0, b) * a);
1509 if (b == 0) return longBitsToDouble(DBL_NAN);
1510 else return copysign(a, copysign(1.0, a) * b);
1513 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1519 double builtin_ddiv(double a, double b)
1527 return longBitsToDouble(DBL_NAN);
1529 return copysign(0.0, b);
1535 return longBitsToDouble(DBL_POSINF);
1537 return longBitsToDouble(DBL_NEGINF);
1540 return longBitsToDouble(DBL_NAN);
1543 /* if (finite(a) && finite(b)) { */
1548 /* return longBitsToDouble(DBL_POSINF); */
1549 /* else if (a < 0) */
1550 /* return longBitsToDouble(DBL_NEGINF); */
1554 /* keep compiler happy */
1559 double builtin_drem(double a, double b)
1565 double builtin_dneg(double a)
1567 if (isnan(a)) return a;
1569 if (finite(a)) return -a;
1570 else return copysign(a, -copysign(1.0, a));
1575 s4 builtin_dcmpl(double a, double b)
1577 if (isnan(a)) return -1;
1578 if (isnan(b)) return -1;
1579 if (!finite(a) || !finite(b)) {
1580 a = finite(a) ? 0 : copysign(1.0, a);
1581 b = finite(b) ? 0 : copysign(1.0, b);
1583 if (a > b) return 1;
1584 if (a == b) return 0;
1589 s4 builtin_dcmpg(double a, double b)
1591 if (isnan(a)) return 1;
1592 if (isnan(b)) return 1;
1593 if (!finite(a) || !finite(b)) {
1594 a = finite(a) ? 0 : copysign(1.0, a);
1595 b = finite(b) ? 0 : copysign(1.0, b);
1597 if (a > b) return 1;
1598 if (a == b) return 0;
1603 /*********************** Conversion operations ****************************/
1605 s8 builtin_i2l(s4 i)
1618 float builtin_i2f(s4 a)
1620 float f = (float) a;
1625 double builtin_i2d(s4 a)
1627 double d = (double) a;
1632 s4 builtin_l2i(s8 l)
1642 float builtin_l2f(s8 a)
1645 float f = (float) a;
1653 double builtin_l2d(s8 a)
1656 double d = (double) a;
1664 s4 builtin_f2i(float a)
1667 return builtin_d2i((double) a);
1676 if (a < (-2147483648))
1677 return (-2147483648);
1680 f = copysignf((float) 1.0, a);
1683 return (-2147483648); */
1687 s8 builtin_f2l(float a)
1690 return builtin_d2l((double) a);
1695 if (a > 9223372036854775807L)
1696 return 9223372036854775807L;
1697 if (a < (-9223372036854775808L))
1698 return (-9223372036854775808L);
1703 f = copysignf((float) 1.0, a);
1705 return 9223372036854775807L;
1706 return (-9223372036854775808L); */
1710 double builtin_f2d(float a)
1712 if (finitef(a)) return (double) a;
1715 return longBitsToDouble(DBL_NAN);
1717 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1722 s4 builtin_d2i(double a)
1727 if (a >= 2147483647)
1729 if (a <= (-2147483647-1))
1730 return (-2147483647-1);
1735 d = copysign(1.0, a);
1738 return (-2147483647-1);
1742 s8 builtin_d2l(double a)
1747 if (a >= 9223372036854775807LL)
1748 return 9223372036854775807LL;
1749 if (a <= (-9223372036854775807LL-1))
1750 return (-9223372036854775807LL-1);
1755 d = copysign(1.0, a);
1757 return 9223372036854775807LL;
1758 return (-9223372036854775807LL-1);
1762 float builtin_d2f(double a)
1768 return intBitsToFloat(FLT_NAN);
1770 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1775 /* used to convert FLT_xxx defines into float values */
1777 inline float intBitsToFloat(s4 i)
1786 /* used to convert DBL_xxx defines into double values */
1788 inline float longBitsToDouble(s8 l)
1797 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1799 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1805 panic("Internal error: builtin_dummy called (native function is missing)");
1806 return 0; /* for the compiler */
1810 inline methodinfo *builtin_asm_get_threadrootmethod()
1812 return *threadrootmethod;
1816 inline void* builtin_asm_get_stackframeinfo()
1818 /*log_text("builtin_asm_get_stackframeinfo()");*/
1819 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1820 return &THREADINFO->_stackframeinfo;
1822 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1823 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1827 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1828 /* stacktraceelement *el;*/
1831 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1832 *el=GCNEW(stacktraceelement,s+1);
1833 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1835 (*el)[s].linenumber=0;
1840 * These are local overrides for various environment variables in Emacs.
1841 * Please do not remove this and leave it at the end of the file, where
1842 * Emacs will automagically detect them.
1843 * ---------------------------------------------------------------------
1846 * indent-tabs-mode: t