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 1194 2004-06-19 12:59:20Z twisti $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/logging.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)
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 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
120 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
121 (unsigned) classvalues.super_diffval;
126 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
130 castinfo classvalues;
132 asm_getclassvalues_atomic(super, sub, &classvalues);
134 if ((base = classvalues.super_baseval) <= 0)
135 /* super is an interface */
136 res = (sub->interfacetablelength > -base) &&
137 (sub->interfacetable[base] != NULL);
139 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
140 <= (unsigned) classvalues.super_diffval;
146 /****************** function: builtin_instanceof *****************************
148 Checks if an object is an instance of some given class (or subclass of
149 that class). If class is an interface, checks if the interface is
151 Return value: 1 ... obj is an instance of class or implements the interface
152 0 ... otherwise or if obj == NULL
154 *****************************************************************************/
156 /* XXX should use vftbl */
157 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
160 log_text ("builtin_instanceof called");
163 return builtin_isanysubclass (obj->vftbl->class, class);
168 /**************** function: builtin_checkcast *******************************
170 The same as builtin_instanceof except that 1 is returned when
173 ****************************************************************************/
175 /* XXX should use vftbl */
176 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
179 log_text("builtin_checkcast called");
184 if (builtin_isanysubclass(obj->vftbl->class, class))
188 printf("#### checkcast failed ");
189 utf_display(obj->vftbl->class->name);
191 utf_display(class->name);
199 /*********** internal function: builtin_descriptorscompatible ******************
201 Checks if two array type descriptors are assignment compatible
202 Return value: 1 ... target = desc is possible
205 ******************************************************************************/
207 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
209 if (desc==target) return 1;
210 if (desc->arraytype != target->arraytype) return 0;
211 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
213 /* {both arrays are arrays of references} */
214 if (desc->dimension == target->dimension) {
215 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
216 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
217 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
219 if (desc->dimension < target->dimension) return 0;
221 /* {desc has higher dimension than target} */
222 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
226 /******************** function: builtin_checkarraycast ***********************
228 Checks if an object is really a subtype of the requested array type.
229 The object has to be an array to begin with. For simple arrays (int, short,
230 double, etc.) the types have to match exactly.
231 For arrays of objects, the type of elements in the array has to be a
232 subtype (or the same type) of the requested element type. For arrays of
233 arrays (which in turn can again be arrays of arrays), the types at the
234 lowest level have to satisfy the corresponding sub class relation.
236 Return value: 1 ... cast is possible
239 ATTENTION: a cast with a NULL pointer is always possible.
241 *****************************************************************************/
243 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
245 arraydescriptor *desc;
248 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
250 return builtin_descriptorscompatible(desc, target->arraydesc);
254 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
257 return builtin_checkarraycast(obj, target);
261 /************************** exception functions *******************************
263 ******************************************************************************/
265 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
268 char logtext[MAXLOGTEXT];
269 sprintf(logtext, "Builtin exception thrown: ");
270 if (local_exceptionptr) {
271 utf_sprint_classname(logtext + strlen(logtext),
272 local_exceptionptr->vftbl->class->name);
275 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
280 *exceptionptr = local_exceptionptr;
282 return local_exceptionptr;
287 /******************* function: builtin_canstore *******************************
289 Checks, if an object can be stored in an array.
290 Return value: 1 ... possible
293 ******************************************************************************/
295 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
297 arraydescriptor *desc;
298 arraydescriptor *valuedesc;
299 vftbl *componentvftbl;
303 castinfo classvalues;
307 /* The following is guaranteed (by verifier checks):
309 * *) a->...vftbl->arraydesc != NULL
310 * *) a->...vftbl->arraydesc->componentvftbl != NULL
311 * *) o->vftbl is not an interface vftbl
314 desc = a->header.objheader.vftbl->arraydesc;
315 componentvftbl = desc->componentvftbl;
316 valuevftbl = o->vftbl;
318 if ((dim_m1 = desc->dimension - 1) == 0) {
321 /* {a is a one-dimensional array} */
322 /* {a is an array of references} */
324 if (valuevftbl == componentvftbl)
327 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
329 if ((base = classvalues.super_baseval) <= 0)
330 /* an array of interface references */
331 return (valuevftbl->interfacetablelength > -base &&
332 valuevftbl->interfacetable[base] != NULL);
334 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
335 <= (unsigned) classvalues.super_diffval;
339 /* {a has dimension > 1} */
340 /* {componentvftbl->arraydesc != NULL} */
342 /* check if o is an array */
343 if ((valuedesc = valuevftbl->arraydesc) == NULL)
345 /* {o is an array} */
347 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
351 /* This is an optimized version where a is guaranteed to be one-dimensional */
352 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
354 arraydescriptor *desc;
359 castinfo classvalues;
363 /* The following is guaranteed (by verifier checks):
365 * *) a->...vftbl->arraydesc != NULL
366 * *) a->...vftbl->arraydesc->elementvftbl != NULL
367 * *) a->...vftbl->arraydesc->dimension == 1
368 * *) o->vftbl is not an interface vftbl
371 desc = a->header.objheader.vftbl->arraydesc;
372 elementvftbl = desc->elementvftbl;
373 valuevftbl = o->vftbl;
375 /* {a is a one-dimensional array} */
377 if (valuevftbl == elementvftbl)
380 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
382 if ((base = classvalues.super_baseval) <= 0)
383 /* an array of interface references */
384 return (valuevftbl->interfacetablelength > -base &&
385 valuevftbl->interfacetable[base] != NULL);
387 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
388 <= (unsigned) classvalues.super_diffval;
394 /* This is an optimized version where a is guaranteed to be a
395 * one-dimensional array of a class type */
396 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
401 castinfo classvalues;
405 /* The following is guaranteed (by verifier checks):
407 * *) a->...vftbl->arraydesc != NULL
408 * *) a->...vftbl->arraydesc->elementvftbl != NULL
409 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
410 * *) a->...vftbl->arraydesc->dimension == 1
411 * *) o->vftbl is not an interface vftbl
414 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
415 valuevftbl = o->vftbl;
417 /* {a is a one-dimensional array} */
419 if (valuevftbl == elementvftbl)
422 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
424 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
425 <= (unsigned) classvalues.super_diffval;
431 /******************** Function: builtin_new **********************************
433 Creates a new instance of class c on the heap.
434 Return value: pointer to the object or NULL if no memory is
437 *****************************************************************************/
440 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
442 java_objectheader *builtin_new(classinfo *c)
444 java_objectheader *o;
446 /* is the class loaded */
451 /* is the class linked */
456 if (!c->initialized) {
458 log_message_class("Initialize class (from builtin_new): ", c);
464 #ifdef SIZE_FROM_CLASSINFO
465 c->alignedsize = align_size(c->instancesize);
466 o = heap_allocate(c->alignedsize, true, c->finalizer);
468 o = heap_allocate(c->instancesize, true, c->finalizer);
474 memset(o, 0, c->instancesize);
482 /********************** Function: builtin_newarray **************************
484 Creates an array with the given vftbl on the heap.
486 Return value: pointer to the array or NULL if no memory is available
488 CAUTION: The given vftbl must be the vftbl of the *array* class,
489 not of the element class.
491 *****************************************************************************/
493 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
496 arraydescriptor *desc;
501 desc = arrayvftbl->arraydesc;
502 dataoffset = desc->dataoffset;
503 componentsize = desc->componentsize;
507 new_exception(string_java_lang_NegativeArraySizeException);
511 #ifdef SIZE_FROM_CLASSINFO
512 actualsize = align_size(dataoffset + size * componentsize);
513 actualsize = dataoffset + size * componentsize;
516 if (((u4) actualsize) < ((u4) size)) { /* overflow */
517 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
521 a = heap_allocate(actualsize,
522 (desc->arraytype == ARRAYTYPE_OBJECT),
528 memset(a, 0, actualsize);
530 a->objheader.vftbl = arrayvftbl;
532 #ifdef SIZE_FROM_CLASSINFO
533 a->alignedsize = actualsize;
540 /********************** Function: builtin_anewarray *************************
542 Creates an array of references to the given class type on the heap.
544 Return value: pointer to the array or NULL if no memory is available
546 XXX This function does not do The Right Thing, because it uses a
547 classinfo pointer at runtime. builtin_newarray should be used
550 *****************************************************************************/
552 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
554 /* is class loaded */
555 if (!component->loaded)
556 if (!class_load(component))
559 /* is class linked */
560 if (!component->linked)
561 if (!class_link(component))
564 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
568 /******************** Function: builtin_newarray_int ***********************
570 Creates an array of 32 bit Integers on the heap.
572 Return value: pointer to the array or NULL if no memory is available
574 *****************************************************************************/
576 java_intarray *builtin_newarray_int(s4 size)
578 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
582 /******************** Function: builtin_newarray_long ***********************
584 Creates an array of 64 bit Integers on the heap.
586 Return value: pointer to the array or NULL if no memory is available
588 *****************************************************************************/
590 java_longarray *builtin_newarray_long(s4 size)
592 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
596 /******************** function: builtin_newarray_float ***********************
598 Creates an array of 32 bit IEEE floats on the heap.
600 Return value: pointer to the array or NULL if no memory is available
602 *****************************************************************************/
604 java_floatarray *builtin_newarray_float(s4 size)
606 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
610 /******************** function: builtin_newarray_double ***********************
612 Creates an array of 64 bit IEEE floats on the heap.
614 Return value: pointer to the array or NULL if no memory is available
616 *****************************************************************************/
618 java_doublearray *builtin_newarray_double(s4 size)
620 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
624 /******************** function: builtin_newarray_byte ***********************
626 Creates an array of 8 bit Integers on the heap.
628 Return value: pointer to the array or NULL if no memory is available
630 *****************************************************************************/
632 java_bytearray *builtin_newarray_byte(s4 size)
634 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
638 /******************** function: builtin_newarray_char ************************
640 Creates an array of characters on the heap.
642 Return value: pointer to the array or NULL if no memory is available
644 *****************************************************************************/
646 java_chararray *builtin_newarray_char(s4 size)
648 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
652 /******************** function: builtin_newarray_short ***********************
654 Creates an array of 16 bit Integers on the heap.
656 Return value: pointer to the array or NULL if no memory is available
658 *****************************************************************************/
660 java_shortarray *builtin_newarray_short(s4 size)
662 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
666 /******************** function: builtin_newarray_boolean ************************
668 Creates an array of bytes on the heap. The array is designated as an array
669 of booleans (important for casts)
671 Return value: pointer to the array or NULL if no memory is available
673 *****************************************************************************/
675 java_booleanarray *builtin_newarray_boolean(s4 size)
677 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
681 /**************** function: builtin_nmultianewarray ***************************
683 Creates a multi-dimensional array on the heap. The dimensions are passed in
687 n............number of dimensions to create
688 arrayvftbl...vftbl of the array class
689 dims.........array containing the size of each dimension to create
691 Return value: pointer to the array or NULL if no memory is available
693 ******************************************************************************/
695 java_arrayheader *builtin_nmultianewarray(int n, vftbl *arrayvftbl, long *dims)
696 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
700 vftbl *componentvftbl;
702 /* utf_display(arrayclass->name); */
704 /* class_load(arrayclass); */
705 /* class_link(arrayclass); */
707 /* create this dimension */
709 a = builtin_newarray(size, arrayvftbl);
710 /* a = builtin_newarray(size, arrayclass->vftbl); */
715 /* if this is the last dimension return */
719 /* get the vftbl of the components to create */
720 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
721 /* component = arrayclass->vftbl->arraydesc; */
723 /* The verifier guarantees this. */
724 /* if (!componentvftbl) */
725 /* panic ("multianewarray with too many dimensions"); */
727 /* create the component arrays */
728 for (i = 0; i < size; i++) {
729 java_arrayheader *ea =
730 builtin_nmultianewarray(n, componentvftbl, dims + 1);
735 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
742 /*****************************************************************************
745 Various functions for printing a message at method entry or exit (for
748 *****************************************************************************/
752 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
762 log_text("WARNING: unmatched methodindent--");
764 if (verbose || runverbose || verboseexception) {
766 printf("Exception ");
767 utf_display_classname(_exceptionptr->vftbl->class->name);
770 printf("Some Throwable");
772 printf(" thrown in ");
775 utf_display_classname(method->class->name);
777 utf_display(method->name);
778 if (method->flags & ACC_SYNCHRONIZED)
782 if (method->flags & ACC_NATIVE) {
784 printf(")(%p) at position %p\n", method->entrypoint, pos);
786 printf(")(%p) at position %p (",method->entrypoint,pos);
787 if (method->class->sourcefile==NULL)
788 printf("<NO CLASSFILE INFORMATION>");
790 utf_display(method->class->sourcefile);
791 printf(":%d)\n",line);
795 printf("call_java_method\n");
799 return _exceptionptr;
803 #ifdef TRACE_ARGS_NUM
804 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
805 #if TRACE_ARGS_NUM > 6
811 char logtext[MAXLOGTEXT];
812 for (i = 0; i < methodindent; i++)
815 sprintf(logtext + methodindent, "called: ");
816 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
817 sprintf(logtext + strlen(logtext), ".");
818 utf_sprint(logtext + strlen(logtext), method->name);
819 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
821 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
822 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
823 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
824 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
825 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
826 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
827 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
828 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
829 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
830 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
831 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
834 sprintf(logtext + strlen(logtext), "(");
836 switch (method->paramcount) {
840 #if defined(__I386__) || defined(__POWERPC__)
842 sprintf(logtext+strlen(logtext), "%llx", a0);
846 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
850 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
854 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
859 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
864 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
865 a0, a1, a2, a3, a4, a5);
868 #if TRACE_ARGS_NUM > 6
870 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
871 a0, a1, a2, a3, a4, a5, a6);
875 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
876 a0, a1, a2, a3, a4, a5, a6, a7);
880 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
881 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
885 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
886 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
891 sprintf(logtext+strlen(logtext), "%lx", a0);
895 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
899 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
903 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
908 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
913 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
914 a0, a1, a2, a3, a4, a5);
917 #if TRACE_ARGS_NUM > 6
919 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
920 a0, a1, a2, a3, a4, a5, a6);
924 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
925 a0, a1, a2, a3, a4, a5, a6, a7);
929 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
930 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
934 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
935 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
941 sprintf(logtext + strlen(logtext), ")");
949 void builtin_displaymethodstart(methodinfo *method)
951 char logtext[MAXLOGTEXT];
952 sprintf(logtext, " ");
953 sprintf(logtext + methodindent, "called: ");
954 utf_sprint(logtext + strlen(logtext), method->class->name);
955 sprintf(logtext + strlen(logtext), ".");
956 utf_sprint(logtext + strlen(logtext), method->name);
957 utf_sprint(logtext + strlen(logtext), method->descriptor);
959 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
960 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
961 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
962 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
963 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
964 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
965 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
966 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
967 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
968 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
969 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
976 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
979 char logtext[MAXLOGTEXT];
980 for (i = 0; i < methodindent; i++)
985 log_text("WARNING: unmatched methodindent--");
987 sprintf(logtext + methodindent, "finished: ");
988 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
989 sprintf(logtext + strlen(logtext), ".");
990 utf_sprint(logtext + strlen(logtext), method->name);
991 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
993 switch (method->returntype) {
995 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
999 #if defined(__I386__) || defined(__POWERPC__)
1000 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1002 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1007 #if defined(__I386__) || defined(__POWERPC__)
1008 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1010 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1015 sprintf(logtext + strlen(logtext), "->%g", f);
1019 sprintf(logtext + strlen(logtext), "->%g", d);
1026 /****************************************************************************
1027 SYNCHRONIZATION FUNCTIONS
1028 *****************************************************************************/
1031 * Lock the mutex of an object.
1033 void internal_lock_mutex_for_object(java_objectheader *object)
1035 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1036 mutexHashEntry *entry;
1039 assert(object != 0);
1041 hashValue = MUTEX_HASH_VALUE(object);
1042 entry = &mutexHashTable[hashValue];
1044 if (entry->object != 0) {
1045 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1047 entry->mutex.holder = 0;
1048 entry->mutex.count = 0;
1049 entry->mutex.muxWaiters = 0;
1052 while (entry->next != 0 && entry->object != object)
1053 entry = entry->next;
1055 if (entry->object != object) {
1056 entry->next = firstFreeOverflowEntry;
1057 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1059 entry = entry->next;
1062 assert(entry->conditionCount == 0);
1067 entry->mutex.holder = 0;
1068 entry->mutex.count = 0;
1069 entry->mutex.muxWaiters = 0;
1072 if (entry->object == 0)
1073 entry->object = object;
1075 internal_lock_mutex(&entry->mutex);
1081 * Unlocks the mutex of an object.
1083 void internal_unlock_mutex_for_object (java_objectheader *object)
1085 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1087 mutexHashEntry *entry;
1089 hashValue = MUTEX_HASH_VALUE(object);
1090 entry = &mutexHashTable[hashValue];
1092 if (entry->object == object) {
1093 internal_unlock_mutex(&entry->mutex);
1096 while (entry->next != 0 && entry->next->object != object)
1097 entry = entry->next;
1099 assert(entry->next != 0);
1101 internal_unlock_mutex(&entry->next->mutex);
1103 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1104 mutexHashEntry *unlinked = entry->next;
1106 entry->next = unlinked->next;
1107 unlinked->next = firstFreeOverflowEntry;
1108 firstFreeOverflowEntry = unlinked;
1115 void builtin_monitorenter(java_objectheader *o)
1117 #if defined(USE_THREADS)
1118 #if !defined(NATIVE_THREADS)
1123 hashValue = MUTEX_HASH_VALUE(o);
1124 if (mutexHashTable[hashValue].object == o
1125 && mutexHashTable[hashValue].mutex.holder == currentThread)
1126 ++mutexHashTable[hashValue].mutex.count;
1128 internal_lock_mutex_for_object(o);
1132 monitorEnter((threadobject *) THREADOBJECT, o);
1138 void builtin_monitorexit(java_objectheader *o)
1140 #if defined(USE_THREADS)
1141 #if !defined(NATIVE_THREADS)
1146 hashValue = MUTEX_HASH_VALUE(o);
1147 if (mutexHashTable[hashValue].object == o) {
1148 if (mutexHashTable[hashValue].mutex.count == 1
1149 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1150 internal_unlock_mutex_for_object(o);
1152 --mutexHashTable[hashValue].mutex.count;
1155 internal_unlock_mutex_for_object(o);
1159 monitorExit((threadobject *) THREADOBJECT, o);
1165 /*****************************************************************************
1166 MISCELLANEOUS HELPER FUNCTIONS
1167 *****************************************************************************/
1171 /*********** Functions for integer divisions *****************************
1173 On some systems (eg. DEC ALPHA), integer division is not supported by the
1174 CPU. These helper functions implement the missing functionality.
1176 ******************************************************************************/
1178 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1179 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1182 /************** Functions for long arithmetics *******************************
1184 On systems where 64 bit Integers are not supported by the CPU, these
1185 functions are needed.
1187 ******************************************************************************/
1190 s8 builtin_ladd(s8 a, s8 b)
1195 return builtin_i2l(0);
1199 s8 builtin_lsub(s8 a, s8 b)
1204 return builtin_i2l(0);
1208 s8 builtin_lmul(s8 a, s8 b)
1213 return builtin_i2l(0);
1217 s8 builtin_ldiv(s8 a, s8 b)
1222 return builtin_i2l(0);
1226 s8 builtin_lrem(s8 a, s8 b)
1231 return builtin_i2l(0);
1235 s8 builtin_lshl(s8 a, s4 b)
1238 return a << (b & 63);
1240 return builtin_i2l(0);
1244 s8 builtin_lshr(s8 a, s4 b)
1247 return a >> (b & 63);
1249 return builtin_i2l(0);
1253 s8 builtin_lushr(s8 a, s4 b)
1256 return ((u8) a) >> (b & 63);
1258 return builtin_i2l(0);
1262 s8 builtin_land(s8 a, s8 b)
1267 return builtin_i2l(0);
1271 s8 builtin_lor(s8 a, s8 b)
1276 return builtin_i2l(0);
1280 s8 builtin_lxor(s8 a, s8 b)
1285 return builtin_i2l(0);
1289 s8 builtin_lneg(s8 a)
1294 return builtin_i2l(0);
1298 s4 builtin_lcmp(s8 a, s8 b)
1301 if (a < b) return -1;
1302 if (a > b) return 1;
1313 /*********** Functions for floating point operations *************************/
1315 float builtin_fadd(float a, float b)
1317 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1318 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1329 if (copysignf(1.0, a) == copysignf(1.0, b))
1332 return intBitsToFloat(FLT_NAN);
1338 float builtin_fsub(float a, float b)
1340 return builtin_fadd(a, builtin_fneg(b));
1344 float builtin_fmul(float a, float b)
1346 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1347 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1349 if (finitef(b)) return a * b;
1351 if (a == 0) return intBitsToFloat(FLT_NAN);
1352 else return copysignf(b, copysignf(1.0, b)*a);
1357 if (b == 0) return intBitsToFloat(FLT_NAN);
1358 else return copysignf(a, copysignf(1.0, a)*b);
1361 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1367 float builtin_fdiv(float a, float b)
1369 if (finitef(a) && finitef(b)) {
1374 return intBitsToFloat(FLT_POSINF);
1376 return intBitsToFloat(FLT_NEGINF);
1379 return intBitsToFloat(FLT_NAN);
1383 float builtin_frem(float a, float b)
1389 float builtin_fneg(float a)
1391 if (isnanf(a)) return a;
1393 if (finitef(a)) return -a;
1394 else return copysignf(a, -copysignf(1.0, a));
1399 s4 builtin_fcmpl(float a, float b)
1401 if (isnanf(a)) return -1;
1402 if (isnanf(b)) return -1;
1403 if (!finitef(a) || !finitef(b)) {
1404 a = finitef(a) ? 0 : copysignf(1.0, a);
1405 b = finitef(b) ? 0 : copysignf(1.0, b);
1407 if (a > b) return 1;
1408 if (a == b) return 0;
1413 s4 builtin_fcmpg(float a, float b)
1415 if (isnanf(a)) return 1;
1416 if (isnanf(b)) return 1;
1417 if (!finitef(a) || !finitef(b)) {
1418 a = finitef(a) ? 0 : copysignf(1.0, a);
1419 b = finitef(b) ? 0 : copysignf(1.0, b);
1421 if (a > b) return 1;
1422 if (a == b) return 0;
1428 /************************* Functions for doubles ****************************/
1430 double builtin_dadd(double a, double b)
1432 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1433 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1435 if (finite(b)) return a + b;
1439 if (finite(b)) return a;
1441 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1442 else return longBitsToDouble(DBL_NAN);
1448 double builtin_dsub(double a, double b)
1450 return builtin_dadd(a, builtin_dneg(b));
1454 double builtin_dmul(double a, double b)
1456 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1457 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1459 if (finite(b)) return a * b;
1461 if (a == 0) return longBitsToDouble(DBL_NAN);
1462 else return copysign(b, copysign(1.0, b) * a);
1467 if (b == 0) return longBitsToDouble(DBL_NAN);
1468 else return copysign(a, copysign(1.0, a) * b);
1471 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1477 double builtin_ddiv(double a, double b)
1485 return longBitsToDouble(DBL_NAN);
1487 return copysign(0.0, b);
1493 return longBitsToDouble(DBL_POSINF);
1495 return longBitsToDouble(DBL_NEGINF);
1498 return longBitsToDouble(DBL_NAN);
1501 /* if (finite(a) && finite(b)) { */
1506 /* return longBitsToDouble(DBL_POSINF); */
1507 /* else if (a < 0) */
1508 /* return longBitsToDouble(DBL_NEGINF); */
1512 /* keep compiler happy */
1517 double builtin_drem(double a, double b)
1523 double builtin_dneg(double a)
1525 if (isnan(a)) return a;
1527 if (finite(a)) return -a;
1528 else return copysign(a, -copysign(1.0, a));
1533 s4 builtin_dcmpl(double a, double b)
1535 if (isnan(a)) return -1;
1536 if (isnan(b)) return -1;
1537 if (!finite(a) || !finite(b)) {
1538 a = finite(a) ? 0 : copysign(1.0, a);
1539 b = finite(b) ? 0 : copysign(1.0, b);
1541 if (a > b) return 1;
1542 if (a == b) return 0;
1547 s4 builtin_dcmpg(double a, double b)
1549 if (isnan(a)) return 1;
1550 if (isnan(b)) return 1;
1551 if (!finite(a) || !finite(b)) {
1552 a = finite(a) ? 0 : copysign(1.0, a);
1553 b = finite(b) ? 0 : copysign(1.0, b);
1555 if (a > b) return 1;
1556 if (a == b) return 0;
1561 /*********************** Conversion operations ****************************/
1563 s8 builtin_i2l(s4 i)
1576 float builtin_i2f(s4 a)
1578 float f = (float) a;
1583 double builtin_i2d(s4 a)
1585 double d = (double) a;
1590 s4 builtin_l2i(s8 l)
1600 float builtin_l2f(s8 a)
1603 float f = (float) a;
1611 double builtin_l2d(s8 a)
1614 double d = (double) a;
1622 s4 builtin_f2i(float a)
1625 return builtin_d2i((double) a);
1634 if (a < (-2147483648))
1635 return (-2147483648);
1638 f = copysignf((float) 1.0, a);
1641 return (-2147483648); */
1645 s8 builtin_f2l(float a)
1648 return builtin_d2l((double) a);
1653 if (a > 9223372036854775807L)
1654 return 9223372036854775807L;
1655 if (a < (-9223372036854775808L))
1656 return (-9223372036854775808L);
1661 f = copysignf((float) 1.0, a);
1663 return 9223372036854775807L;
1664 return (-9223372036854775808L); */
1668 double builtin_f2d(float a)
1670 if (finitef(a)) return (double) a;
1673 return longBitsToDouble(DBL_NAN);
1675 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1680 s4 builtin_d2i(double a)
1685 if (a >= 2147483647)
1687 if (a <= (-2147483647-1))
1688 return (-2147483647-1);
1693 d = copysign(1.0, a);
1696 return (-2147483647-1);
1700 s8 builtin_d2l(double a)
1705 if (a >= 9223372036854775807LL)
1706 return 9223372036854775807LL;
1707 if (a <= (-9223372036854775807LL-1))
1708 return (-9223372036854775807LL-1);
1713 d = copysign(1.0, a);
1715 return 9223372036854775807LL;
1716 return (-9223372036854775807LL-1);
1720 float builtin_d2f(double a)
1726 return intBitsToFloat(FLT_NAN);
1728 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1733 /* used to convert FLT_xxx defines into float values */
1735 inline float intBitsToFloat(s4 i)
1744 /* used to convert DBL_xxx defines into double values */
1746 inline float longBitsToDouble(s8 l)
1755 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1757 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1763 panic("Internal error: builtin_dummy called (native function is missing)");
1764 return 0; /* for the compiler */
1768 /* builtin_asm_get_exceptionptrptr *********************************************
1770 this is a wrapper for calls from asmpart
1772 *******************************************************************************/
1774 java_objectheader **builtin_asm_get_exceptionptrptr()
1776 return builtin_get_exceptionptrptr();
1780 methodinfo *builtin_asm_get_threadrootmethod()
1782 return *threadrootmethod;
1786 inline void* builtin_asm_get_stackframeinfo()
1788 /*log_text("builtin_asm_get_stackframeinfo()");*/
1789 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1790 return &THREADINFO->_stackframeinfo;
1792 #if defined(__GNUC__)
1793 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1795 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1799 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1800 /* stacktraceelement *el;*/
1803 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1804 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1806 *el=MNEW(stacktraceelement,s+1); /*GC*/
1808 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1810 #if defined(__GNUC__)
1811 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1813 (*el)[s].linenumber=-1; /* -1 can never be reched otherwise, since line numbers are only u2, so it is save to use that as flag */
1818 * These are local overrides for various environment variables in Emacs.
1819 * Please do not remove this and leave it at the end of the file, where
1820 * Emacs will automagically detect them.
1821 * ---------------------------------------------------------------------
1824 * indent-tabs-mode: t