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 1356 2004-07-28 10:05:07Z twisti $
45 #include "exceptions.h"
54 #include "threads/thread.h"
55 #include "threads/locks.h"
56 #include "toolbox/logging.h"
57 #include "toolbox/memory.h"
58 #include "nat/java_lang_Cloneable.h"
59 #include "nat/java_lang_VMObject.h"
62 #undef DEBUG /*define DEBUG 1*/
64 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
65 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
67 /*****************************************************************************
69 *****************************************************************************/
73 /*************** internal function: builtin_isanysubclass *********************
75 Checks a subclass relation between two classes. Implemented interfaces
76 are interpreted as super classes.
77 Return value: 1 ... sub is subclass of super
80 *****************************************************************************/
81 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
87 if (super->flags & ACC_INTERFACE)
88 return (sub->vftbl->interfacetablelength > super->index) &&
89 (sub->vftbl->interfacetable[-super->index] != NULL);
102 for (tmp=sub;tmp!=0;tmp=tmp->super) {
104 utf_display(tmp->name);
108 for (tmp=super;tmp!=0;tmp=tmp->super) {
110 utf_display(tmp->name);
115 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
116 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
117 super->vftbl->diffval); */
119 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
121 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
122 (unsigned) classvalues.super_diffval;
127 s4 builtin_isanysubclass_vftbl(vftbl_t *sub,vftbl_t *super)
131 castinfo classvalues;
133 asm_getclassvalues_atomic(super, sub, &classvalues);
135 if ((base = classvalues.super_baseval) <= 0)
136 /* super is an interface */
137 res = (sub->interfacetablelength > -base) &&
138 (sub->interfacetable[base] != NULL);
140 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
141 <= (unsigned) classvalues.super_diffval;
147 /****************** function: builtin_instanceof *****************************
149 Checks if an object is an instance of some given class (or subclass of
150 that class). If class is an interface, checks if the interface is
152 Return value: 1 ... obj is an instance of class or implements the interface
153 0 ... otherwise or if obj == NULL
155 *****************************************************************************/
157 /* XXX should use vftbl */
158 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
161 log_text ("builtin_instanceof called");
164 return builtin_isanysubclass (obj->vftbl->class, class);
169 /**************** function: builtin_checkcast *******************************
171 The same as builtin_instanceof except that 1 is returned when
174 ****************************************************************************/
176 /* XXX should use vftbl */
177 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
180 log_text("builtin_checkcast called");
185 if (builtin_isanysubclass(obj->vftbl->class, class))
189 printf("#### checkcast failed ");
190 utf_display(obj->vftbl->class->name);
192 utf_display(class->name);
200 /*********** internal function: builtin_descriptorscompatible ******************
202 Checks if two array type descriptors are assignment compatible
203 Return value: 1 ... target = desc is possible
206 ******************************************************************************/
208 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
210 if (desc==target) return 1;
211 if (desc->arraytype != target->arraytype) return 0;
212 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
214 /* {both arrays are arrays of references} */
215 if (desc->dimension == target->dimension) {
216 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
217 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
218 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
220 if (desc->dimension < target->dimension) return 0;
222 /* {desc has higher dimension than target} */
223 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
227 /******************** function: builtin_checkarraycast ***********************
229 Checks if an object is really a subtype of the requested array type.
230 The object has to be an array to begin with. For simple arrays (int, short,
231 double, etc.) the types have to match exactly.
232 For arrays of objects, the type of elements in the array has to be a
233 subtype (or the same type) of the requested element type. For arrays of
234 arrays (which in turn can again be arrays of arrays), the types at the
235 lowest level have to satisfy the corresponding sub class relation.
237 Return value: 1 ... cast is possible
240 ATTENTION: a cast with a NULL pointer is always possible.
242 *****************************************************************************/
244 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
246 arraydescriptor *desc;
249 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
251 return builtin_descriptorscompatible(desc, target->arraydesc);
255 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
258 return builtin_checkarraycast(obj, target);
262 /************************** exception functions *******************************
264 ******************************************************************************/
266 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
269 char logtext[MAXLOGTEXT];
270 sprintf(logtext, "Builtin exception thrown: ");
272 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
274 utf_sprint_classname(logtext + strlen(logtext),
275 xptr->vftbl->class->name);
277 if (t->detailMessage) {
278 sprintf(logtext + strlen(logtext), ": %s",
279 javastring_tochar(t->detailMessage));
283 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
288 *exceptionptr = xptr;
295 /******************* function: builtin_canstore *******************************
297 Checks, if an object can be stored in an array.
298 Return value: 1 ... possible
301 ******************************************************************************/
303 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
305 arraydescriptor *desc;
306 arraydescriptor *valuedesc;
307 vftbl_t *componentvftbl;
311 castinfo classvalues;
315 /* The following is guaranteed (by verifier checks):
317 * *) a->...vftbl->arraydesc != NULL
318 * *) a->...vftbl->arraydesc->componentvftbl != NULL
319 * *) o->vftbl is not an interface vftbl
322 desc = a->header.objheader.vftbl->arraydesc;
323 componentvftbl = desc->componentvftbl;
324 valuevftbl = o->vftbl;
326 if ((dim_m1 = desc->dimension - 1) == 0) {
329 /* {a is a one-dimensional array} */
330 /* {a is an array of references} */
332 if (valuevftbl == componentvftbl)
335 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
337 if ((base = classvalues.super_baseval) <= 0)
338 /* an array of interface references */
339 return (valuevftbl->interfacetablelength > -base &&
340 valuevftbl->interfacetable[base] != NULL);
342 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
343 <= (unsigned) classvalues.super_diffval;
347 /* {a has dimension > 1} */
348 /* {componentvftbl->arraydesc != NULL} */
350 /* check if o is an array */
351 if ((valuedesc = valuevftbl->arraydesc) == NULL)
353 /* {o is an array} */
355 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
359 /* This is an optimized version where a is guaranteed to be one-dimensional */
360 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
362 arraydescriptor *desc;
363 vftbl_t *elementvftbl;
367 castinfo classvalues;
371 /* The following is guaranteed (by verifier checks):
373 * *) a->...vftbl->arraydesc != NULL
374 * *) a->...vftbl->arraydesc->elementvftbl != NULL
375 * *) a->...vftbl->arraydesc->dimension == 1
376 * *) o->vftbl is not an interface vftbl
379 desc = a->header.objheader.vftbl->arraydesc;
380 elementvftbl = desc->elementvftbl;
381 valuevftbl = o->vftbl;
383 /* {a is a one-dimensional array} */
385 if (valuevftbl == elementvftbl)
388 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
390 if ((base = classvalues.super_baseval) <= 0)
391 /* an array of interface references */
392 return (valuevftbl->interfacetablelength > -base &&
393 valuevftbl->interfacetable[base] != NULL);
395 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
396 <= (unsigned) classvalues.super_diffval;
402 /* This is an optimized version where a is guaranteed to be a
403 * one-dimensional array of a class type */
404 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
406 vftbl_t *elementvftbl;
409 castinfo classvalues;
413 /* The following is guaranteed (by verifier checks):
415 * *) a->...vftbl->arraydesc != NULL
416 * *) a->...vftbl->arraydesc->elementvftbl != NULL
417 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
418 * *) a->...vftbl->arraydesc->dimension == 1
419 * *) o->vftbl is not an interface vftbl
422 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
423 valuevftbl = o->vftbl;
425 /* {a is a one-dimensional array} */
427 if (valuevftbl == elementvftbl)
430 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
432 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
433 <= (unsigned) classvalues.super_diffval;
439 /******************** Function: builtin_new **********************************
441 Creates a new instance of class c on the heap.
442 Return value: pointer to the object or NULL if no memory is
445 *****************************************************************************/
448 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
450 java_objectheader *builtin_new(classinfo *c)
452 java_objectheader *o;
454 /* is the class loaded */
459 /* is the class linked */
464 if (!c->initialized) {
466 log_message_class("Initialize class (from builtin_new): ", c);
472 #ifdef SIZE_FROM_CLASSINFO
473 c->alignedsize = align_size(c->instancesize);
474 o = heap_allocate(c->alignedsize, true, c->finalizer);
476 o = heap_allocate(c->instancesize, true, c->finalizer);
482 memset(o, 0, c->instancesize);
490 /********************** Function: builtin_newarray **************************
492 Creates an array with the given vftbl on the heap.
494 Return value: pointer to the array or NULL if no memory is available
496 CAUTION: The given vftbl must be the vftbl of the *array* class,
497 not of the element class.
499 *****************************************************************************/
501 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
504 arraydescriptor *desc;
509 desc = arrayvftbl->arraydesc;
510 dataoffset = desc->dataoffset;
511 componentsize = desc->componentsize;
515 new_exception(string_java_lang_NegativeArraySizeException);
519 #ifdef SIZE_FROM_CLASSINFO
520 actualsize = align_size(dataoffset + size * componentsize);
521 actualsize = dataoffset + size * componentsize;
526 if (((u4) actualsize) < ((u4) size)) { /* overflow */
527 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
531 a = heap_allocate(actualsize,
532 (desc->arraytype == ARRAYTYPE_OBJECT),
538 memset(a, 0, actualsize);
540 a->objheader.vftbl = arrayvftbl;
542 #ifdef SIZE_FROM_CLASSINFO
543 a->alignedsize = actualsize;
550 /********************** Function: builtin_anewarray *************************
552 Creates an array of references to the given class type on the heap.
554 Return value: pointer to the array or NULL if no memory is available
556 XXX This function does not do The Right Thing, because it uses a
557 classinfo pointer at runtime. builtin_newarray should be used
560 *****************************************************************************/
562 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
564 /* is class loaded */
565 if (!component->loaded)
566 if (!class_load(component))
569 /* is class linked */
570 if (!component->linked)
571 if (!class_link(component))
574 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
578 /******************** Function: builtin_newarray_int ***********************
580 Creates an array of 32 bit Integers on the heap.
582 Return value: pointer to the array or NULL if no memory is available
584 *****************************************************************************/
586 java_intarray *builtin_newarray_int(s4 size)
588 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
592 /******************** Function: builtin_newarray_long ***********************
594 Creates an array of 64 bit Integers on the heap.
596 Return value: pointer to the array or NULL if no memory is available
598 *****************************************************************************/
600 java_longarray *builtin_newarray_long(s4 size)
602 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
606 /******************** function: builtin_newarray_float ***********************
608 Creates an array of 32 bit IEEE floats on the heap.
610 Return value: pointer to the array or NULL if no memory is available
612 *****************************************************************************/
614 java_floatarray *builtin_newarray_float(s4 size)
616 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
620 /******************** function: builtin_newarray_double ***********************
622 Creates an array of 64 bit IEEE floats on the heap.
624 Return value: pointer to the array or NULL if no memory is available
626 *****************************************************************************/
628 java_doublearray *builtin_newarray_double(s4 size)
630 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
634 /******************** function: builtin_newarray_byte ***********************
636 Creates an array of 8 bit Integers on the heap.
638 Return value: pointer to the array or NULL if no memory is available
640 *****************************************************************************/
642 java_bytearray *builtin_newarray_byte(s4 size)
644 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
648 /******************** function: builtin_newarray_char ************************
650 Creates an array of characters on the heap.
652 Return value: pointer to the array or NULL if no memory is available
654 *****************************************************************************/
656 java_chararray *builtin_newarray_char(s4 size)
658 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
662 /******************** function: builtin_newarray_short ***********************
664 Creates an array of 16 bit Integers on the heap.
666 Return value: pointer to the array or NULL if no memory is available
668 *****************************************************************************/
670 java_shortarray *builtin_newarray_short(s4 size)
672 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
676 /******************** function: builtin_newarray_boolean ************************
678 Creates an array of bytes on the heap. The array is designated as an array
679 of booleans (important for casts)
681 Return value: pointer to the array or NULL if no memory is available
683 *****************************************************************************/
685 java_booleanarray *builtin_newarray_boolean(s4 size)
687 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
691 /**************** function: builtin_nmultianewarray ***************************
693 Creates a multi-dimensional array on the heap. The dimensions are passed in
697 n............number of dimensions to create
698 arrayvftbl...vftbl of the array class
699 dims.........array containing the size of each dimension to create
701 Return value: pointer to the array or NULL if no memory is available
703 ******************************************************************************/
705 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
706 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
710 vftbl_t *componentvftbl;
712 /* utf_display(arrayclass->name); */
714 /* class_load(arrayclass); */
715 /* class_link(arrayclass); */
717 /* create this dimension */
719 a = builtin_newarray(size, arrayvftbl);
720 /* a = builtin_newarray(size, arrayclass->vftbl); */
725 /* if this is the last dimension return */
729 /* get the vftbl of the components to create */
730 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
731 /* component = arrayclass->vftbl->arraydesc; */
733 /* The verifier guarantees this. */
734 /* if (!componentvftbl) */
735 /* panic ("multianewarray with too many dimensions"); */
737 /* create the component arrays */
738 for (i = 0; i < size; i++) {
739 java_arrayheader *ea =
740 builtin_nmultianewarray(n, componentvftbl, dims + 1);
745 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
752 /*****************************************************************************
755 Various functions for printing a message at method entry or exit (for
758 *****************************************************************************/
762 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
772 log_text("WARNING: unmatched methodindent--");
774 if (verbose || runverbose || verboseexception) {
776 printf("Exception ");
777 utf_display_classname(xptr->vftbl->class->name);
780 printf("Some Throwable");
782 printf(" thrown in ");
785 utf_display_classname(m->class->name);
787 utf_display(m->name);
788 if (m->flags & ACC_SYNCHRONIZED)
792 if (m->flags & ACC_NATIVE) {
794 printf(")(%p) at position %p\n", m->entrypoint, pos);
796 printf(")(%p) at position %p (", m->entrypoint, pos);
797 if (m->class->sourcefile==NULL)
798 printf("<NO CLASSFILE INFORMATION>");
800 utf_display(m->class->sourcefile);
801 printf(":%d)\n", line);
805 printf("call_java_method\n");
813 #ifdef TRACE_ARGS_NUM
814 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
815 #if TRACE_ARGS_NUM > 6
821 char logtext[MAXLOGTEXT];
822 for (i = 0; i < methodindent; i++)
825 sprintf(logtext + methodindent, "called: ");
826 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
827 sprintf(logtext + strlen(logtext), ".");
828 utf_sprint(logtext + strlen(logtext), m->name);
829 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
831 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
832 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
833 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
834 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
835 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
836 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
837 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
838 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
839 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
840 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
841 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
844 sprintf(logtext + strlen(logtext), "(");
846 switch (m->paramcount) {
850 #if defined(__I386__) || defined(__POWERPC__)
852 sprintf(logtext+strlen(logtext), "%llx", a0);
856 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
860 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
864 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
869 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
874 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
875 a0, a1, a2, a3, a4, a5);
878 #if TRACE_ARGS_NUM > 6
880 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
881 a0, a1, a2, a3, a4, a5, a6);
885 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
886 a0, a1, a2, a3, a4, a5, a6, a7);
890 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
891 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
895 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
896 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
901 sprintf(logtext+strlen(logtext), "%lx", a0);
905 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
909 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
913 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
918 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
923 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
924 a0, a1, a2, a3, a4, a5);
927 #if TRACE_ARGS_NUM > 6
929 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
930 a0, a1, a2, a3, a4, a5, a6);
934 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
935 a0, a1, a2, a3, a4, a5, a6, a7);
939 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
940 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
944 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
945 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
951 sprintf(logtext + strlen(logtext), ")");
959 void builtin_displaymethodstart(methodinfo *m)
961 char logtext[MAXLOGTEXT];
962 sprintf(logtext, " ");
963 sprintf(logtext + methodindent, "called: ");
964 utf_sprint(logtext + strlen(logtext), m->class->name);
965 sprintf(logtext + strlen(logtext), ".");
966 utf_sprint(logtext + strlen(logtext), m->name);
967 utf_sprint(logtext + strlen(logtext), m->descriptor);
969 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
970 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
971 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
972 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
973 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
974 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
975 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
976 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
977 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
978 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
979 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
986 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
989 char logtext[MAXLOGTEXT];
990 for (i = 0; i < methodindent; i++)
995 log_text("WARNING: unmatched methodindent--");
997 sprintf(logtext + methodindent, "finished: ");
998 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
999 sprintf(logtext + strlen(logtext), ".");
1000 utf_sprint(logtext + strlen(logtext), m->name);
1001 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1003 switch (m->returntype) {
1005 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1009 #if defined(__I386__) || defined(__POWERPC__)
1010 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1012 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1017 #if defined(__I386__) || defined(__POWERPC__)
1018 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1020 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1025 sprintf(logtext + strlen(logtext), "->%g", f);
1029 sprintf(logtext + strlen(logtext), "->%g", d);
1036 /****************************************************************************
1037 SYNCHRONIZATION FUNCTIONS
1038 *****************************************************************************/
1041 * Lock the mutex of an object.
1043 void internal_lock_mutex_for_object(java_objectheader *object)
1045 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1046 mutexHashEntry *entry;
1049 assert(object != 0);
1051 hashValue = MUTEX_HASH_VALUE(object);
1052 entry = &mutexHashTable[hashValue];
1054 if (entry->object != 0) {
1055 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1057 entry->mutex.holder = 0;
1058 entry->mutex.count = 0;
1059 entry->mutex.muxWaiters = 0;
1062 while (entry->next != 0 && entry->object != object)
1063 entry = entry->next;
1065 if (entry->object != object) {
1066 entry->next = firstFreeOverflowEntry;
1067 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1069 entry = entry->next;
1072 assert(entry->conditionCount == 0);
1077 entry->mutex.holder = 0;
1078 entry->mutex.count = 0;
1079 entry->mutex.muxWaiters = 0;
1082 if (entry->object == 0)
1083 entry->object = object;
1085 internal_lock_mutex(&entry->mutex);
1091 * Unlocks the mutex of an object.
1093 void internal_unlock_mutex_for_object (java_objectheader *object)
1095 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1097 mutexHashEntry *entry;
1099 hashValue = MUTEX_HASH_VALUE(object);
1100 entry = &mutexHashTable[hashValue];
1102 if (entry->object == object) {
1103 internal_unlock_mutex(&entry->mutex);
1106 while (entry->next != 0 && entry->next->object != object)
1107 entry = entry->next;
1109 assert(entry->next != 0);
1111 internal_unlock_mutex(&entry->next->mutex);
1113 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1114 mutexHashEntry *unlinked = entry->next;
1116 entry->next = unlinked->next;
1117 unlinked->next = firstFreeOverflowEntry;
1118 firstFreeOverflowEntry = unlinked;
1125 void builtin_monitorenter(java_objectheader *o)
1127 #if defined(USE_THREADS)
1128 #if !defined(NATIVE_THREADS)
1133 hashValue = MUTEX_HASH_VALUE(o);
1134 if (mutexHashTable[hashValue].object == o
1135 && mutexHashTable[hashValue].mutex.holder == currentThread)
1136 ++mutexHashTable[hashValue].mutex.count;
1138 internal_lock_mutex_for_object(o);
1142 monitorEnter((threadobject *) THREADOBJECT, o);
1148 * Locks the class object - needed for static synchronized methods.
1149 * The use_class_as_object call is needed in order to circumvent a
1150 * possible deadlock with builtin_monitorenter called by another
1151 * thread calling use_class_as_object.
1153 void builtin_staticmonitorenter(classinfo *c)
1155 use_class_as_object(c);
1156 builtin_monitorenter(&c->header);
1160 void builtin_monitorexit(java_objectheader *o)
1162 #if defined(USE_THREADS)
1163 #if !defined(NATIVE_THREADS)
1168 hashValue = MUTEX_HASH_VALUE(o);
1169 if (mutexHashTable[hashValue].object == o) {
1170 if (mutexHashTable[hashValue].mutex.count == 1
1171 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1172 internal_unlock_mutex_for_object(o);
1174 --mutexHashTable[hashValue].mutex.count;
1177 internal_unlock_mutex_for_object(o);
1181 monitorExit((threadobject *) THREADOBJECT, o);
1187 /*****************************************************************************
1188 MISCELLANEOUS HELPER FUNCTIONS
1189 *****************************************************************************/
1193 /*********** Functions for integer divisions *****************************
1195 On some systems (eg. DEC ALPHA), integer division is not supported by the
1196 CPU. These helper functions implement the missing functionality.
1198 ******************************************************************************/
1200 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1201 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1204 /************** Functions for long arithmetics *******************************
1206 On systems where 64 bit Integers are not supported by the CPU, these
1207 functions are needed.
1209 ******************************************************************************/
1212 s8 builtin_ladd(s8 a, s8 b)
1217 return builtin_i2l(0);
1221 s8 builtin_lsub(s8 a, s8 b)
1226 return builtin_i2l(0);
1230 s8 builtin_lmul(s8 a, s8 b)
1235 return builtin_i2l(0);
1239 s8 builtin_ldiv(s8 a, s8 b)
1244 return builtin_i2l(0);
1248 s8 builtin_lrem(s8 a, s8 b)
1253 return builtin_i2l(0);
1257 s8 builtin_lshl(s8 a, s4 b)
1260 return a << (b & 63);
1262 return builtin_i2l(0);
1266 s8 builtin_lshr(s8 a, s4 b)
1269 return a >> (b & 63);
1271 return builtin_i2l(0);
1275 s8 builtin_lushr(s8 a, s4 b)
1278 return ((u8) a) >> (b & 63);
1280 return builtin_i2l(0);
1284 s8 builtin_land(s8 a, s8 b)
1289 return builtin_i2l(0);
1293 s8 builtin_lor(s8 a, s8 b)
1298 return builtin_i2l(0);
1302 s8 builtin_lxor(s8 a, s8 b)
1307 return builtin_i2l(0);
1311 s8 builtin_lneg(s8 a)
1316 return builtin_i2l(0);
1320 s4 builtin_lcmp(s8 a, s8 b)
1323 if (a < b) return -1;
1324 if (a > b) return 1;
1335 /*********** Functions for floating point operations *************************/
1337 float builtin_fadd(float a, float b)
1339 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1340 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1351 if (copysignf(1.0, a) == copysignf(1.0, b))
1354 return intBitsToFloat(FLT_NAN);
1360 float builtin_fsub(float a, float b)
1362 return builtin_fadd(a, builtin_fneg(b));
1366 float builtin_fmul(float a, float b)
1368 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1369 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1371 if (finitef(b)) return a * b;
1373 if (a == 0) return intBitsToFloat(FLT_NAN);
1374 else return copysignf(b, copysignf(1.0, b)*a);
1379 if (b == 0) return intBitsToFloat(FLT_NAN);
1380 else return copysignf(a, copysignf(1.0, a)*b);
1383 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1389 float builtin_fdiv(float a, float b)
1391 if (finitef(a) && finitef(b)) {
1396 return intBitsToFloat(FLT_POSINF);
1398 return intBitsToFloat(FLT_NEGINF);
1401 return intBitsToFloat(FLT_NAN);
1405 float builtin_frem(float a, float b)
1411 float builtin_fneg(float a)
1413 if (isnanf(a)) return a;
1415 if (finitef(a)) return -a;
1416 else return copysignf(a, -copysignf(1.0, a));
1421 s4 builtin_fcmpl(float a, float b)
1423 if (isnanf(a)) return -1;
1424 if (isnanf(b)) return -1;
1425 if (!finitef(a) || !finitef(b)) {
1426 a = finitef(a) ? 0 : copysignf(1.0, a);
1427 b = finitef(b) ? 0 : copysignf(1.0, b);
1429 if (a > b) return 1;
1430 if (a == b) return 0;
1435 s4 builtin_fcmpg(float a, float b)
1437 if (isnanf(a)) return 1;
1438 if (isnanf(b)) return 1;
1439 if (!finitef(a) || !finitef(b)) {
1440 a = finitef(a) ? 0 : copysignf(1.0, a);
1441 b = finitef(b) ? 0 : copysignf(1.0, b);
1443 if (a > b) return 1;
1444 if (a == b) return 0;
1450 /************************* Functions for doubles ****************************/
1452 double builtin_dadd(double a, double b)
1454 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1455 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1457 if (finite(b)) return a + b;
1461 if (finite(b)) return a;
1463 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1464 else return longBitsToDouble(DBL_NAN);
1470 double builtin_dsub(double a, double b)
1472 return builtin_dadd(a, builtin_dneg(b));
1476 double builtin_dmul(double a, double b)
1478 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1479 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1481 if (finite(b)) return a * b;
1483 if (a == 0) return longBitsToDouble(DBL_NAN);
1484 else return copysign(b, copysign(1.0, b) * a);
1489 if (b == 0) return longBitsToDouble(DBL_NAN);
1490 else return copysign(a, copysign(1.0, a) * b);
1493 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1499 double builtin_ddiv(double a, double b)
1507 return longBitsToDouble(DBL_NAN);
1509 return copysign(0.0, b);
1515 return longBitsToDouble(DBL_POSINF);
1517 return longBitsToDouble(DBL_NEGINF);
1520 return longBitsToDouble(DBL_NAN);
1523 /* if (finite(a) && finite(b)) { */
1528 /* return longBitsToDouble(DBL_POSINF); */
1529 /* else if (a < 0) */
1530 /* return longBitsToDouble(DBL_NEGINF); */
1534 /* keep compiler happy */
1539 double builtin_drem(double a, double b)
1545 double builtin_dneg(double a)
1547 if (isnan(a)) return a;
1549 if (finite(a)) return -a;
1550 else return copysign(a, -copysign(1.0, a));
1555 s4 builtin_dcmpl(double a, double b)
1557 if (isnan(a)) return -1;
1558 if (isnan(b)) return -1;
1559 if (!finite(a) || !finite(b)) {
1560 a = finite(a) ? 0 : copysign(1.0, a);
1561 b = finite(b) ? 0 : copysign(1.0, b);
1563 if (a > b) return 1;
1564 if (a == b) return 0;
1569 s4 builtin_dcmpg(double a, double b)
1571 if (isnan(a)) return 1;
1572 if (isnan(b)) return 1;
1573 if (!finite(a) || !finite(b)) {
1574 a = finite(a) ? 0 : copysign(1.0, a);
1575 b = finite(b) ? 0 : copysign(1.0, b);
1577 if (a > b) return 1;
1578 if (a == b) return 0;
1583 /*********************** Conversion operations ****************************/
1585 s8 builtin_i2l(s4 i)
1598 float builtin_i2f(s4 a)
1600 float f = (float) a;
1605 double builtin_i2d(s4 a)
1607 double d = (double) a;
1612 s4 builtin_l2i(s8 l)
1622 float builtin_l2f(s8 a)
1625 float f = (float) a;
1633 double builtin_l2d(s8 a)
1636 double d = (double) a;
1644 s4 builtin_f2i(float a)
1647 return builtin_d2i((double) a);
1656 if (a < (-2147483648))
1657 return (-2147483648);
1660 f = copysignf((float) 1.0, a);
1663 return (-2147483648); */
1667 s8 builtin_f2l(float a)
1670 return builtin_d2l((double) a);
1675 if (a > 9223372036854775807L)
1676 return 9223372036854775807L;
1677 if (a < (-9223372036854775808L))
1678 return (-9223372036854775808L);
1683 f = copysignf((float) 1.0, a);
1685 return 9223372036854775807L;
1686 return (-9223372036854775808L); */
1690 double builtin_f2d(float a)
1692 if (finitef(a)) return (double) a;
1695 return longBitsToDouble(DBL_NAN);
1697 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1702 s4 builtin_d2i(double a)
1707 if (a >= 2147483647)
1709 if (a <= (-2147483647-1))
1710 return (-2147483647-1);
1715 d = copysign(1.0, a);
1718 return (-2147483647-1);
1722 s8 builtin_d2l(double a)
1727 if (a >= 9223372036854775807LL)
1728 return 9223372036854775807LL;
1729 if (a <= (-9223372036854775807LL-1))
1730 return (-9223372036854775807LL-1);
1735 d = copysign(1.0, a);
1737 return 9223372036854775807LL;
1738 return (-9223372036854775807LL-1);
1742 float builtin_d2f(double a)
1748 return intBitsToFloat(FLT_NAN);
1750 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1755 /* used to convert FLT_xxx defines into float values */
1757 inline float intBitsToFloat(s4 i)
1766 /* used to convert DBL_xxx defines into double values */
1768 inline float longBitsToDouble(s8 l)
1777 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1779 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1785 panic("Internal error: builtin_dummy called (native function is missing)");
1786 return 0; /* for the compiler */
1790 /* builtin_asm_get_exceptionptrptr *********************************************
1792 this is a wrapper for calls from asmpart
1794 *******************************************************************************/
1796 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1797 java_objectheader **builtin_asm_get_exceptionptrptr()
1799 return builtin_get_exceptionptrptr();
1804 methodinfo *builtin_asm_get_threadrootmethod()
1806 return *threadrootmethod;
1810 inline void* builtin_asm_get_stackframeinfo()
1812 /*log_text("builtin_asm_get_stackframeinfo()");*/
1813 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1814 return &THREADINFO->_stackframeinfo;
1816 #if defined(__GNUC__)
1817 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1819 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1823 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1824 /* stacktraceelement *el;*/
1827 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1828 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1830 *el=MNEW(stacktraceelement,s+1); /*GC*/
1832 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1834 #if defined(__GNUC__)
1835 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1837 (*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 */
1842 * These are local overrides for various environment variables in Emacs.
1843 * Please do not remove this and leave it at the end of the file, where
1844 * Emacs will automagically detect them.
1845 * ---------------------------------------------------------------------
1848 * indent-tabs-mode: t