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 1112 2004-05-31 15:47:20Z jowenn $
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)
1121 /*log_text("Monitor enter");*/
1123 assert(blockInts == 0);
1127 hashValue = MUTEX_HASH_VALUE(o);
1128 if (mutexHashTable[hashValue].object == o
1129 && mutexHashTable[hashValue].mutex.holder == currentThread)
1130 ++mutexHashTable[hashValue].mutex.count;
1132 internal_lock_mutex_for_object(o);
1136 assert(blockInts == 0);
1138 monitorEnter((threadobject*) THREADOBJECT, o);
1144 void builtin_monitorexit (java_objectheader *o)
1147 #if defined(USE_THREADS)
1148 #if !defined(NATIVE_THREADS)
1151 /* log_text("Monitor leave"); */
1153 assert(blockInts == 0);
1157 hashValue = MUTEX_HASH_VALUE(o);
1158 if (mutexHashTable[hashValue].object == o) {
1159 if (mutexHashTable[hashValue].mutex.count == 1
1160 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1161 internal_unlock_mutex_for_object(o);
1163 --mutexHashTable[hashValue].mutex.count;
1166 internal_unlock_mutex_for_object(o);
1170 assert(blockInts == 0);
1172 monitorExit((threadobject*) THREADOBJECT, o);
1178 /*****************************************************************************
1179 MISCELLANEOUS HELPER FUNCTIONS
1180 *****************************************************************************/
1184 /*********** Functions for integer divisions *****************************
1186 On some systems (eg. DEC ALPHA), integer division is not supported by the
1187 CPU. These helper functions implement the missing functionality.
1189 ******************************************************************************/
1191 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1192 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1195 /************** Functions for long arithmetics *******************************
1197 On systems where 64 bit Integers are not supported by the CPU, these
1198 functions are needed.
1200 ******************************************************************************/
1203 s8 builtin_ladd(s8 a, s8 b)
1208 return builtin_i2l(0);
1212 s8 builtin_lsub(s8 a, s8 b)
1217 return builtin_i2l(0);
1221 s8 builtin_lmul(s8 a, s8 b)
1226 return builtin_i2l(0);
1230 s8 builtin_ldiv(s8 a, s8 b)
1235 return builtin_i2l(0);
1239 s8 builtin_lrem(s8 a, s8 b)
1244 return builtin_i2l(0);
1248 s8 builtin_lshl(s8 a, s4 b)
1251 return a << (b & 63);
1253 return builtin_i2l(0);
1257 s8 builtin_lshr(s8 a, s4 b)
1260 return a >> (b & 63);
1262 return builtin_i2l(0);
1266 s8 builtin_lushr(s8 a, s4 b)
1269 return ((u8) a) >> (b & 63);
1271 return builtin_i2l(0);
1275 s8 builtin_land(s8 a, s8 b)
1280 return builtin_i2l(0);
1284 s8 builtin_lor(s8 a, s8 b)
1289 return builtin_i2l(0);
1293 s8 builtin_lxor(s8 a, s8 b)
1298 return builtin_i2l(0);
1302 s8 builtin_lneg(s8 a)
1307 return builtin_i2l(0);
1311 s4 builtin_lcmp(s8 a, s8 b)
1314 if (a < b) return -1;
1315 if (a > b) return 1;
1326 /*********** Functions for floating point operations *************************/
1328 float builtin_fadd(float a, float b)
1330 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1331 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1342 if (copysignf(1.0, a) == copysignf(1.0, b))
1345 return intBitsToFloat(FLT_NAN);
1351 float builtin_fsub(float a, float b)
1353 return builtin_fadd(a, builtin_fneg(b));
1357 float builtin_fmul(float a, float b)
1359 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1360 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1362 if (finitef(b)) return a * b;
1364 if (a == 0) return intBitsToFloat(FLT_NAN);
1365 else return copysignf(b, copysignf(1.0, b)*a);
1370 if (b == 0) return intBitsToFloat(FLT_NAN);
1371 else return copysignf(a, copysignf(1.0, a)*b);
1374 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1380 float builtin_fdiv(float a, float b)
1382 if (finitef(a) && finitef(b)) {
1387 return intBitsToFloat(FLT_POSINF);
1389 return intBitsToFloat(FLT_NEGINF);
1392 return intBitsToFloat(FLT_NAN);
1396 float builtin_frem(float a, float b)
1402 float builtin_fneg(float a)
1404 if (isnanf(a)) return a;
1406 if (finitef(a)) return -a;
1407 else return copysignf(a, -copysignf(1.0, a));
1412 s4 builtin_fcmpl(float a, float b)
1414 if (isnanf(a)) return -1;
1415 if (isnanf(b)) return -1;
1416 if (!finitef(a) || !finitef(b)) {
1417 a = finitef(a) ? 0 : copysignf(1.0, a);
1418 b = finitef(b) ? 0 : copysignf(1.0, b);
1420 if (a > b) return 1;
1421 if (a == b) return 0;
1426 s4 builtin_fcmpg(float a, float b)
1428 if (isnanf(a)) return 1;
1429 if (isnanf(b)) return 1;
1430 if (!finitef(a) || !finitef(b)) {
1431 a = finitef(a) ? 0 : copysignf(1.0, a);
1432 b = finitef(b) ? 0 : copysignf(1.0, b);
1434 if (a > b) return 1;
1435 if (a == b) return 0;
1441 /************************* Functions for doubles ****************************/
1443 double builtin_dadd(double a, double b)
1445 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1446 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1448 if (finite(b)) return a + b;
1452 if (finite(b)) return a;
1454 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1455 else return longBitsToDouble(DBL_NAN);
1461 double builtin_dsub(double a, double b)
1463 return builtin_dadd(a, builtin_dneg(b));
1467 double builtin_dmul(double a, double b)
1469 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1470 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1472 if (finite(b)) return a * b;
1474 if (a == 0) return longBitsToDouble(DBL_NAN);
1475 else return copysign(b, copysign(1.0, b) * a);
1480 if (b == 0) return longBitsToDouble(DBL_NAN);
1481 else return copysign(a, copysign(1.0, a) * b);
1484 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1490 double builtin_ddiv(double a, double b)
1498 return longBitsToDouble(DBL_NAN);
1500 return copysign(0.0, b);
1506 return longBitsToDouble(DBL_POSINF);
1508 return longBitsToDouble(DBL_NEGINF);
1511 return longBitsToDouble(DBL_NAN);
1514 /* if (finite(a) && finite(b)) { */
1519 /* return longBitsToDouble(DBL_POSINF); */
1520 /* else if (a < 0) */
1521 /* return longBitsToDouble(DBL_NEGINF); */
1525 /* keep compiler happy */
1530 double builtin_drem(double a, double b)
1536 double builtin_dneg(double a)
1538 if (isnan(a)) return a;
1540 if (finite(a)) return -a;
1541 else return copysign(a, -copysign(1.0, a));
1546 s4 builtin_dcmpl(double a, double b)
1548 if (isnan(a)) return -1;
1549 if (isnan(b)) return -1;
1550 if (!finite(a) || !finite(b)) {
1551 a = finite(a) ? 0 : copysign(1.0, a);
1552 b = finite(b) ? 0 : copysign(1.0, b);
1554 if (a > b) return 1;
1555 if (a == b) return 0;
1560 s4 builtin_dcmpg(double a, double b)
1562 if (isnan(a)) return 1;
1563 if (isnan(b)) return 1;
1564 if (!finite(a) || !finite(b)) {
1565 a = finite(a) ? 0 : copysign(1.0, a);
1566 b = finite(b) ? 0 : copysign(1.0, b);
1568 if (a > b) return 1;
1569 if (a == b) return 0;
1574 /*********************** Conversion operations ****************************/
1576 s8 builtin_i2l(s4 i)
1589 float builtin_i2f(s4 a)
1591 float f = (float) a;
1596 double builtin_i2d(s4 a)
1598 double d = (double) a;
1603 s4 builtin_l2i(s8 l)
1613 float builtin_l2f(s8 a)
1616 float f = (float) a;
1624 double builtin_l2d(s8 a)
1627 double d = (double) a;
1635 s4 builtin_f2i(float a)
1638 return builtin_d2i((double) a);
1647 if (a < (-2147483648))
1648 return (-2147483648);
1651 f = copysignf((float) 1.0, a);
1654 return (-2147483648); */
1658 s8 builtin_f2l(float a)
1661 return builtin_d2l((double) a);
1666 if (a > 9223372036854775807L)
1667 return 9223372036854775807L;
1668 if (a < (-9223372036854775808L))
1669 return (-9223372036854775808L);
1674 f = copysignf((float) 1.0, a);
1676 return 9223372036854775807L;
1677 return (-9223372036854775808L); */
1681 double builtin_f2d(float a)
1683 if (finitef(a)) return (double) a;
1686 return longBitsToDouble(DBL_NAN);
1688 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1693 s4 builtin_d2i(double a)
1698 if (a >= 2147483647)
1700 if (a <= (-2147483647-1))
1701 return (-2147483647-1);
1706 d = copysign(1.0, a);
1709 return (-2147483647-1);
1713 s8 builtin_d2l(double a)
1718 if (a >= 9223372036854775807LL)
1719 return 9223372036854775807LL;
1720 if (a <= (-9223372036854775807LL-1))
1721 return (-9223372036854775807LL-1);
1726 d = copysign(1.0, a);
1728 return 9223372036854775807LL;
1729 return (-9223372036854775807LL-1);
1733 float builtin_d2f(double a)
1739 return intBitsToFloat(FLT_NAN);
1741 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1746 /* used to convert FLT_xxx defines into float values */
1748 inline float intBitsToFloat(s4 i)
1757 /* used to convert DBL_xxx defines into double values */
1759 inline float longBitsToDouble(s8 l)
1768 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1770 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1776 panic("Internal error: builtin_dummy called (native function is missing)");
1777 return 0; /* for the compiler */
1781 /* builtin_asm_get_exceptionptrptr *********************************************
1783 this is a wrapper for calls from asmpart
1785 *******************************************************************************/
1787 java_objectheader **builtin_asm_get_exceptionptrptr()
1789 return builtin_get_exceptionptrptr();
1793 methodinfo *builtin_asm_get_threadrootmethod()
1795 return *threadrootmethod;
1799 inline void* builtin_asm_get_stackframeinfo()
1801 /*log_text("builtin_asm_get_stackframeinfo()");*/
1802 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1803 return &THREADINFO->_stackframeinfo;
1805 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1806 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1810 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1811 /* stacktraceelement *el;*/
1814 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1815 *el=MNEW(stacktraceelement,s+1); /*GC*/
1816 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1818 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1819 (*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 */
1824 * These are local overrides for various environment variables in Emacs.
1825 * Please do not remove this and leave it at the end of the file, where
1826 * Emacs will automagically detect them.
1827 * ---------------------------------------------------------------------
1830 * indent-tabs-mode: t