1 /* vm/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 1621 2004-11-30 13:06:55Z twisti $
47 #include "mm/memory.h"
48 #include "native/native.h"
49 #include "native/include/java_lang_Cloneable.h"
50 #include "native/include/java_lang_VMObject.h"
52 #if defined(USE_THREADS)
53 # if defined(NATIVE_THREADS)
54 # include "threads/native/threads.h"
56 # include "threads/green/threads.h"
57 # include "threads/green/locks.h"
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/exceptions.h"
64 #include "vm/global.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/tables.h"
68 #include "vm/jit/asmpart.h"
71 #undef DEBUG /*define DEBUG 1*/
73 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
74 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
76 /*****************************************************************************
78 *****************************************************************************/
82 /*************** internal function: builtin_isanysubclass *********************
84 Checks a subclass relation between two classes. Implemented interfaces
85 are interpreted as super classes.
86 Return value: 1 ... sub is subclass of super
89 *****************************************************************************/
90 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
96 if (super->flags & ACC_INTERFACE)
97 return (sub->vftbl->interfacetablelength > super->index) &&
98 (sub->vftbl->interfacetable[-super->index] != NULL);
111 for (tmp=sub;tmp!=0;tmp=tmp->super) {
113 utf_display(tmp->name);
117 for (tmp=super;tmp!=0;tmp=tmp->super) {
119 utf_display(tmp->name);
124 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
125 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
126 super->vftbl->diffval); */
128 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
130 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
131 (unsigned) classvalues.super_diffval;
136 s4 builtin_isanysubclass_vftbl(vftbl_t *sub,vftbl_t *super)
140 castinfo classvalues;
142 asm_getclassvalues_atomic(super, sub, &classvalues);
144 if ((base = classvalues.super_baseval) <= 0)
145 /* super is an interface */
146 res = (sub->interfacetablelength > -base) &&
147 (sub->interfacetable[base] != NULL);
149 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
150 <= (unsigned) classvalues.super_diffval;
156 /****************** function: builtin_instanceof *****************************
158 Checks if an object is an instance of some given class (or subclass of
159 that class). If class is an interface, checks if the interface is
161 Return value: 1 ... obj is an instance of class or implements the interface
162 0 ... otherwise or if obj == NULL
164 *****************************************************************************/
166 /* XXX should use vftbl */
167 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
170 log_text ("builtin_instanceof called");
173 return builtin_isanysubclass (obj->vftbl->class, class);
178 /**************** function: builtin_checkcast *******************************
180 The same as builtin_instanceof except that 1 is returned when
183 ****************************************************************************/
185 /* XXX should use vftbl */
186 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
189 log_text("builtin_checkcast called");
194 if (builtin_isanysubclass(obj->vftbl->class, class))
198 printf("#### checkcast failed ");
199 utf_display(obj->vftbl->class->name);
201 utf_display(class->name);
209 /*********** internal function: builtin_descriptorscompatible ******************
211 Checks if two array type descriptors are assignment compatible
212 Return value: 1 ... target = desc is possible
215 ******************************************************************************/
217 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
219 if (desc==target) return 1;
220 if (desc->arraytype != target->arraytype) return 0;
221 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
223 /* {both arrays are arrays of references} */
224 if (desc->dimension == target->dimension) {
225 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
226 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
227 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
229 if (desc->dimension < target->dimension) return 0;
231 /* {desc has higher dimension than target} */
232 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
236 /******************** function: builtin_checkarraycast ***********************
238 Checks if an object is really a subtype of the requested array type.
239 The object has to be an array to begin with. For simple arrays (int, short,
240 double, etc.) the types have to match exactly.
241 For arrays of objects, the type of elements in the array has to be a
242 subtype (or the same type) of the requested element type. For arrays of
243 arrays (which in turn can again be arrays of arrays), the types at the
244 lowest level have to satisfy the corresponding sub class relation.
246 Return value: 1 ... cast is possible
249 ATTENTION: a cast with a NULL pointer is always possible.
251 *****************************************************************************/
253 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
255 arraydescriptor *desc;
258 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
260 return builtin_descriptorscompatible(desc, target->arraydesc);
264 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
267 return builtin_checkarraycast(obj, target);
271 /************************** exception functions *******************************
273 ******************************************************************************/
275 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
278 char logtext[MAXLOGTEXT];
279 sprintf(logtext, "Builtin exception thrown: ");
281 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
283 utf_sprint_classname(logtext + strlen(logtext),
284 xptr->vftbl->class->name);
286 if (t->detailMessage) {
287 sprintf(logtext + strlen(logtext), ": %s",
288 javastring_tochar((java_objectheader *) t->detailMessage));
292 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
297 *exceptionptr = xptr;
304 /******************* function: builtin_canstore *******************************
306 Checks, if an object can be stored in an array.
307 Return value: 1 ... possible
310 ******************************************************************************/
312 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
314 arraydescriptor *desc;
315 arraydescriptor *valuedesc;
316 vftbl_t *componentvftbl;
320 castinfo classvalues;
324 /* The following is guaranteed (by verifier checks):
326 * *) a->...vftbl->arraydesc != NULL
327 * *) a->...vftbl->arraydesc->componentvftbl != NULL
328 * *) o->vftbl is not an interface vftbl
331 desc = a->header.objheader.vftbl->arraydesc;
332 componentvftbl = desc->componentvftbl;
333 valuevftbl = o->vftbl;
335 if ((dim_m1 = desc->dimension - 1) == 0) {
338 /* {a is a one-dimensional array} */
339 /* {a is an array of references} */
341 if (valuevftbl == componentvftbl)
344 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
346 if ((base = classvalues.super_baseval) <= 0)
347 /* an array of interface references */
348 return (valuevftbl->interfacetablelength > -base &&
349 valuevftbl->interfacetable[base] != NULL);
351 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
352 <= (unsigned) classvalues.super_diffval;
356 /* {a has dimension > 1} */
357 /* {componentvftbl->arraydesc != NULL} */
359 /* check if o is an array */
360 if ((valuedesc = valuevftbl->arraydesc) == NULL)
362 /* {o is an array} */
364 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
368 /* This is an optimized version where a is guaranteed to be one-dimensional */
369 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
371 arraydescriptor *desc;
372 vftbl_t *elementvftbl;
376 castinfo classvalues;
380 /* The following is guaranteed (by verifier checks):
382 * *) a->...vftbl->arraydesc != NULL
383 * *) a->...vftbl->arraydesc->elementvftbl != NULL
384 * *) a->...vftbl->arraydesc->dimension == 1
385 * *) o->vftbl is not an interface vftbl
388 desc = a->header.objheader.vftbl->arraydesc;
389 elementvftbl = desc->elementvftbl;
390 valuevftbl = o->vftbl;
392 /* {a is a one-dimensional array} */
394 if (valuevftbl == elementvftbl)
397 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
399 if ((base = classvalues.super_baseval) <= 0)
400 /* an array of interface references */
401 return (valuevftbl->interfacetablelength > -base &&
402 valuevftbl->interfacetable[base] != NULL);
404 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
405 <= (unsigned) classvalues.super_diffval;
411 /* This is an optimized version where a is guaranteed to be a
412 * one-dimensional array of a class type */
413 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
415 vftbl_t *elementvftbl;
418 castinfo classvalues;
422 /* The following is guaranteed (by verifier checks):
424 * *) a->...vftbl->arraydesc != NULL
425 * *) a->...vftbl->arraydesc->elementvftbl != NULL
426 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
427 * *) a->...vftbl->arraydesc->dimension == 1
428 * *) o->vftbl is not an interface vftbl
431 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
432 valuevftbl = o->vftbl;
434 /* {a is a one-dimensional array} */
436 if (valuevftbl == elementvftbl)
439 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
441 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
442 <= (unsigned) classvalues.super_diffval;
448 /******************** Function: builtin_new **********************************
450 Creates a new instance of class c on the heap.
451 Return value: pointer to the object or NULL if no memory is
454 *****************************************************************************/
457 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
459 java_objectheader *builtin_new(classinfo *c)
461 java_objectheader *o;
463 /* is the class loaded */
468 /* is the class linked */
473 if (!c->initialized) {
475 log_message_class("Initialize class (from builtin_new): ", c);
481 #ifdef SIZE_FROM_CLASSINFO
482 c->alignedsize = align_size(c->instancesize);
483 o = heap_allocate(c->alignedsize, true, c->finalizer);
485 o = heap_allocate(c->instancesize, true, c->finalizer);
491 memset(o, 0, c->instancesize);
494 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
502 /********************** Function: builtin_newarray **************************
504 Creates an array with the given vftbl on the heap.
506 Return value: pointer to the array or NULL if no memory is available
508 CAUTION: The given vftbl must be the vftbl of the *array* class,
509 not of the element class.
511 *****************************************************************************/
513 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
516 arraydescriptor *desc;
521 desc = arrayvftbl->arraydesc;
522 dataoffset = desc->dataoffset;
523 componentsize = desc->componentsize;
527 new_exception(string_java_lang_NegativeArraySizeException);
531 #ifdef SIZE_FROM_CLASSINFO
532 actualsize = align_size(dataoffset + size * componentsize);
533 actualsize = dataoffset + size * componentsize;
538 if (((u4) actualsize) < ((u4) size)) { /* overflow */
539 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
543 a = heap_allocate(actualsize,
544 (desc->arraytype == ARRAYTYPE_OBJECT),
550 memset(a, 0, actualsize);
552 a->objheader.vftbl = arrayvftbl;
553 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
554 initObjectLock(&a->objheader);
557 #ifdef SIZE_FROM_CLASSINFO
558 a->alignedsize = actualsize;
565 /********************** Function: builtin_anewarray *************************
567 Creates an array of references to the given class type on the heap.
569 Return value: pointer to the array or NULL if no memory is available
571 XXX This function does not do The Right Thing, because it uses a
572 classinfo pointer at runtime. builtin_newarray should be used
575 *****************************************************************************/
577 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
579 /* is class loaded */
580 if (!component->loaded)
581 if (!class_load(component))
584 /* is class linked */
585 if (!component->linked)
586 if (!class_link(component))
589 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
593 /******************** Function: builtin_newarray_int ***********************
595 Creates an array of 32 bit Integers on the heap.
597 Return value: pointer to the array or NULL if no memory is available
599 *****************************************************************************/
601 java_intarray *builtin_newarray_int(s4 size)
603 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
607 /******************** Function: builtin_newarray_long ***********************
609 Creates an array of 64 bit Integers on the heap.
611 Return value: pointer to the array or NULL if no memory is available
613 *****************************************************************************/
615 java_longarray *builtin_newarray_long(s4 size)
617 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
621 /******************** function: builtin_newarray_float ***********************
623 Creates an array of 32 bit IEEE floats on the heap.
625 Return value: pointer to the array or NULL if no memory is available
627 *****************************************************************************/
629 java_floatarray *builtin_newarray_float(s4 size)
631 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
635 /******************** function: builtin_newarray_double ***********************
637 Creates an array of 64 bit IEEE floats on the heap.
639 Return value: pointer to the array or NULL if no memory is available
641 *****************************************************************************/
643 java_doublearray *builtin_newarray_double(s4 size)
645 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
649 /******************** function: builtin_newarray_byte ***********************
651 Creates an array of 8 bit Integers on the heap.
653 Return value: pointer to the array or NULL if no memory is available
655 *****************************************************************************/
657 java_bytearray *builtin_newarray_byte(s4 size)
659 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
663 /******************** function: builtin_newarray_char ************************
665 Creates an array of characters on the heap.
667 Return value: pointer to the array or NULL if no memory is available
669 *****************************************************************************/
671 java_chararray *builtin_newarray_char(s4 size)
673 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
677 /******************** function: builtin_newarray_short ***********************
679 Creates an array of 16 bit Integers on the heap.
681 Return value: pointer to the array or NULL if no memory is available
683 *****************************************************************************/
685 java_shortarray *builtin_newarray_short(s4 size)
687 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
691 /******************** function: builtin_newarray_boolean ************************
693 Creates an array of bytes on the heap. The array is designated as an array
694 of booleans (important for casts)
696 Return value: pointer to the array or NULL if no memory is available
698 *****************************************************************************/
700 java_booleanarray *builtin_newarray_boolean(s4 size)
702 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
706 /**************** function: builtin_nmultianewarray ***************************
708 Creates a multi-dimensional array on the heap. The dimensions are passed in
712 n............number of dimensions to create
713 arrayvftbl...vftbl of the array class
714 dims.........array containing the size of each dimension to create
716 Return value: pointer to the array or NULL if no memory is available
718 ******************************************************************************/
720 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
721 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
725 vftbl_t *componentvftbl;
727 /* utf_display(arrayclass->name); */
729 /* class_load(arrayclass); */
730 /* class_link(arrayclass); */
732 /* create this dimension */
734 a = builtin_newarray(size, arrayvftbl);
735 /* a = builtin_newarray(size, arrayclass->vftbl); */
740 /* if this is the last dimension return */
744 /* get the vftbl of the components to create */
745 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
746 /* component = arrayclass->vftbl->arraydesc; */
748 /* The verifier guarantees this. */
749 /* if (!componentvftbl) */
750 /* panic ("multianewarray with too many dimensions"); */
752 /* create the component arrays */
753 for (i = 0; i < size; i++) {
754 java_arrayheader *ea =
755 builtin_nmultianewarray(n, componentvftbl, dims + 1);
760 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
767 /*****************************************************************************
770 Various functions for printing a message at method entry or exit (for
773 *****************************************************************************/
777 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
787 log_text("WARNING: unmatched methodindent--");
789 if (opt_verbose || runverbose || verboseexception) {
791 printf("Exception ");
792 utf_display_classname(xptr->vftbl->class->name);
795 printf("Some Throwable");
797 printf(" thrown in ");
800 utf_display_classname(m->class->name);
802 utf_display(m->name);
803 if (m->flags & ACC_SYNCHRONIZED) {
810 if (m->flags & ACC_NATIVE) {
813 printf(")(0x%016lx) at position %p\n", (s8) m->entrypoint, pos);
815 printf(")(0x%08lx) at position %p\n", (s4) m->entrypoint, pos);
820 printf(")(0x%016lx) at position %p (", (s8) m->entrypoint, pos);
822 printf(")(0x%08lx) at position %p (", (s4) m->entrypoint, pos);
824 if (m->class->sourcefile == NULL) {
825 printf("<NO CLASSFILE INFORMATION>");
828 utf_display(m->class->sourcefile);
830 printf(":%d)\n", line);
834 printf("call_java_method\n");
842 #ifdef TRACE_ARGS_NUM
843 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
844 #if TRACE_ARGS_NUM > 6
850 char logtext[MAXLOGTEXT];
851 for (i = 0; i < methodindent; i++)
854 sprintf(logtext + methodindent, "called: ");
855 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
856 sprintf(logtext + strlen(logtext), ".");
857 utf_sprint(logtext + strlen(logtext), m->name);
858 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
860 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
861 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
862 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
863 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
864 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
865 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
866 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
867 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
868 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
869 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
870 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
873 sprintf(logtext + strlen(logtext), "(");
875 switch (m->paramcount) {
879 #if defined(__I386__) || defined(__POWERPC__)
881 sprintf(logtext+strlen(logtext), "%llx", a0);
885 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
889 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
893 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
898 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
903 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
904 a0, a1, a2, a3, a4, a5);
907 #if TRACE_ARGS_NUM > 6
909 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
910 a0, a1, a2, a3, a4, a5, a6);
914 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
915 a0, a1, a2, a3, a4, a5, a6, a7);
919 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
920 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
924 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
925 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
930 sprintf(logtext+strlen(logtext), "%lx", a0);
934 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
938 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
942 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
947 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
952 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
953 a0, a1, a2, a3, a4, a5);
956 #if TRACE_ARGS_NUM > 6
958 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
959 a0, a1, a2, a3, a4, a5, a6);
963 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
964 a0, a1, a2, a3, a4, a5, a6, a7);
968 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
969 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
973 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
974 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
980 sprintf(logtext + strlen(logtext), ")");
988 void builtin_displaymethodstart(methodinfo *m)
990 char logtext[MAXLOGTEXT];
991 sprintf(logtext, " ");
992 sprintf(logtext + methodindent, "called: ");
993 utf_sprint(logtext + strlen(logtext), m->class->name);
994 sprintf(logtext + strlen(logtext), ".");
995 utf_sprint(logtext + strlen(logtext), m->name);
996 utf_sprint(logtext + strlen(logtext), m->descriptor);
998 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
999 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1000 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1001 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1002 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1003 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1004 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1005 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1006 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1007 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1008 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1015 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1018 char logtext[MAXLOGTEXT];
1019 for (i = 0; i < methodindent; i++)
1024 log_text("WARNING: unmatched methodindent--");
1026 sprintf(logtext + methodindent, "finished: ");
1027 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1028 sprintf(logtext + strlen(logtext), ".");
1029 utf_sprint(logtext + strlen(logtext), m->name);
1030 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1032 switch (m->returntype) {
1034 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1038 #if defined(__I386__) || defined(__POWERPC__)
1039 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1041 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1046 #if defined(__I386__) || defined(__POWERPC__)
1047 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1049 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1054 sprintf(logtext + strlen(logtext), "->%g", f);
1058 sprintf(logtext + strlen(logtext), "->%g", d);
1065 /****************************************************************************
1066 SYNCHRONIZATION FUNCTIONS
1067 *****************************************************************************/
1070 * Lock the mutex of an object.
1072 void internal_lock_mutex_for_object(java_objectheader *object)
1074 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1075 mutexHashEntry *entry;
1078 assert(object != 0);
1080 hashValue = MUTEX_HASH_VALUE(object);
1081 entry = &mutexHashTable[hashValue];
1083 if (entry->object != 0) {
1084 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1086 entry->mutex.holder = 0;
1087 entry->mutex.count = 0;
1088 entry->mutex.muxWaiters = 0;
1091 while (entry->next != 0 && entry->object != object)
1092 entry = entry->next;
1094 if (entry->object != object) {
1095 entry->next = firstFreeOverflowEntry;
1096 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1098 entry = entry->next;
1101 assert(entry->conditionCount == 0);
1106 entry->mutex.holder = 0;
1107 entry->mutex.count = 0;
1108 entry->mutex.muxWaiters = 0;
1111 if (entry->object == 0)
1112 entry->object = object;
1114 internal_lock_mutex(&entry->mutex);
1120 * Unlocks the mutex of an object.
1122 void internal_unlock_mutex_for_object (java_objectheader *object)
1124 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1126 mutexHashEntry *entry;
1128 hashValue = MUTEX_HASH_VALUE(object);
1129 entry = &mutexHashTable[hashValue];
1131 if (entry->object == object) {
1132 internal_unlock_mutex(&entry->mutex);
1135 while (entry->next != 0 && entry->next->object != object)
1136 entry = entry->next;
1138 assert(entry->next != 0);
1140 internal_unlock_mutex(&entry->next->mutex);
1142 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1143 mutexHashEntry *unlinked = entry->next;
1145 entry->next = unlinked->next;
1146 unlinked->next = firstFreeOverflowEntry;
1147 firstFreeOverflowEntry = unlinked;
1154 void builtin_monitorenter(java_objectheader *o)
1156 #if defined(USE_THREADS)
1157 #if !defined(NATIVE_THREADS)
1162 hashValue = MUTEX_HASH_VALUE(o);
1163 if (mutexHashTable[hashValue].object == o
1164 && mutexHashTable[hashValue].mutex.holder == currentThread)
1165 ++mutexHashTable[hashValue].mutex.count;
1167 internal_lock_mutex_for_object(o);
1171 monitorEnter((threadobject *) THREADOBJECT, o);
1178 * Locks the class object - needed for static synchronized methods.
1179 * The use_class_as_object call is needed in order to circumvent a
1180 * possible deadlock with builtin_monitorenter called by another
1181 * thread calling use_class_as_object.
1183 void builtin_staticmonitorenter(classinfo *c)
1185 use_class_as_object(c);
1186 builtin_monitorenter(&c->header);
1190 void *builtin_monitorexit(java_objectheader *o)
1192 #if defined(USE_THREADS)
1193 #if !defined(NATIVE_THREADS)
1198 hashValue = MUTEX_HASH_VALUE(o);
1199 if (mutexHashTable[hashValue].object == o) {
1200 if (mutexHashTable[hashValue].mutex.count == 1
1201 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1202 internal_unlock_mutex_for_object(o);
1204 --mutexHashTable[hashValue].mutex.count;
1207 internal_unlock_mutex_for_object(o);
1212 monitorExit((threadobject *) THREADOBJECT, o);
1219 /*****************************************************************************
1220 MISCELLANEOUS HELPER FUNCTIONS
1221 *****************************************************************************/
1225 /*********** Functions for integer divisions *****************************
1227 On some systems (eg. DEC ALPHA), integer division is not supported by the
1228 CPU. These helper functions implement the missing functionality.
1230 ******************************************************************************/
1232 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1233 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1236 /************** Functions for long arithmetics *******************************
1238 On systems where 64 bit Integers are not supported by the CPU, these
1239 functions are needed.
1241 ******************************************************************************/
1244 s8 builtin_ladd(s8 a, s8 b)
1249 return builtin_i2l(0);
1253 s8 builtin_lsub(s8 a, s8 b)
1258 return builtin_i2l(0);
1262 s8 builtin_lmul(s8 a, s8 b)
1267 return builtin_i2l(0);
1271 s8 builtin_ldiv(s8 a, s8 b)
1276 return builtin_i2l(0);
1280 s8 builtin_lrem(s8 a, s8 b)
1285 return builtin_i2l(0);
1289 s8 builtin_lshl(s8 a, s4 b)
1292 return a << (b & 63);
1294 return builtin_i2l(0);
1298 s8 builtin_lshr(s8 a, s4 b)
1301 return a >> (b & 63);
1303 return builtin_i2l(0);
1307 s8 builtin_lushr(s8 a, s4 b)
1310 return ((u8) a) >> (b & 63);
1312 return builtin_i2l(0);
1316 s8 builtin_land(s8 a, s8 b)
1321 return builtin_i2l(0);
1325 s8 builtin_lor(s8 a, s8 b)
1330 return builtin_i2l(0);
1334 s8 builtin_lxor(s8 a, s8 b)
1339 return builtin_i2l(0);
1343 s8 builtin_lneg(s8 a)
1348 return builtin_i2l(0);
1352 s4 builtin_lcmp(s8 a, s8 b)
1355 if (a < b) return -1;
1356 if (a > b) return 1;
1367 /*********** Functions for floating point operations *************************/
1369 float builtin_fadd(float a, float b)
1371 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1372 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1383 if (copysignf(1.0, a) == copysignf(1.0, b))
1386 return intBitsToFloat(FLT_NAN);
1392 float builtin_fsub(float a, float b)
1394 return builtin_fadd(a, builtin_fneg(b));
1398 float builtin_fmul(float a, float b)
1400 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1401 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1403 if (finitef(b)) return a * b;
1405 if (a == 0) return intBitsToFloat(FLT_NAN);
1406 else return copysignf(b, copysignf(1.0, b)*a);
1411 if (b == 0) return intBitsToFloat(FLT_NAN);
1412 else return copysignf(a, copysignf(1.0, a)*b);
1415 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1421 float builtin_fdiv(float a, float b)
1423 if (finitef(a) && finitef(b)) {
1428 return intBitsToFloat(FLT_POSINF);
1430 return intBitsToFloat(FLT_NEGINF);
1433 return intBitsToFloat(FLT_NAN);
1437 float builtin_frem(float a, float b)
1443 float builtin_fneg(float a)
1445 if (isnanf(a)) return a;
1447 if (finitef(a)) return -a;
1448 else return copysignf(a, -copysignf(1.0, a));
1453 s4 builtin_fcmpl(float a, float b)
1455 if (isnanf(a)) return -1;
1456 if (isnanf(b)) return -1;
1457 if (!finitef(a) || !finitef(b)) {
1458 a = finitef(a) ? 0 : copysignf(1.0, a);
1459 b = finitef(b) ? 0 : copysignf(1.0, b);
1461 if (a > b) return 1;
1462 if (a == b) return 0;
1467 s4 builtin_fcmpg(float a, float b)
1469 if (isnanf(a)) return 1;
1470 if (isnanf(b)) return 1;
1471 if (!finitef(a) || !finitef(b)) {
1472 a = finitef(a) ? 0 : copysignf(1.0, a);
1473 b = finitef(b) ? 0 : copysignf(1.0, b);
1475 if (a > b) return 1;
1476 if (a == b) return 0;
1482 /************************* Functions for doubles ****************************/
1484 double builtin_dadd(double a, double b)
1486 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1487 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1489 if (finite(b)) return a + b;
1493 if (finite(b)) return a;
1495 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1496 else return longBitsToDouble(DBL_NAN);
1502 double builtin_dsub(double a, double b)
1504 return builtin_dadd(a, builtin_dneg(b));
1508 double builtin_dmul(double a, double b)
1510 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1511 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1513 if (finite(b)) return a * b;
1515 if (a == 0) return longBitsToDouble(DBL_NAN);
1516 else return copysign(b, copysign(1.0, b) * a);
1521 if (b == 0) return longBitsToDouble(DBL_NAN);
1522 else return copysign(a, copysign(1.0, a) * b);
1525 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1531 double builtin_ddiv(double a, double b)
1539 return longBitsToDouble(DBL_NAN);
1541 return copysign(0.0, b);
1547 return longBitsToDouble(DBL_POSINF);
1549 return longBitsToDouble(DBL_NEGINF);
1552 return longBitsToDouble(DBL_NAN);
1555 /* if (finite(a) && finite(b)) { */
1560 /* return longBitsToDouble(DBL_POSINF); */
1561 /* else if (a < 0) */
1562 /* return longBitsToDouble(DBL_NEGINF); */
1566 /* keep compiler happy */
1571 double builtin_drem(double a, double b)
1577 double builtin_dneg(double a)
1579 if (isnan(a)) return a;
1581 if (finite(a)) return -a;
1582 else return copysign(a, -copysign(1.0, a));
1587 s4 builtin_dcmpl(double a, double b)
1589 if (isnan(a)) return -1;
1590 if (isnan(b)) return -1;
1591 if (!finite(a) || !finite(b)) {
1592 a = finite(a) ? 0 : copysign(1.0, a);
1593 b = finite(b) ? 0 : copysign(1.0, b);
1595 if (a > b) return 1;
1596 if (a == b) return 0;
1601 s4 builtin_dcmpg(double a, double b)
1603 if (isnan(a)) return 1;
1604 if (isnan(b)) return 1;
1605 if (!finite(a) || !finite(b)) {
1606 a = finite(a) ? 0 : copysign(1.0, a);
1607 b = finite(b) ? 0 : copysign(1.0, b);
1609 if (a > b) return 1;
1610 if (a == b) return 0;
1615 /*********************** Conversion operations ****************************/
1617 s8 builtin_i2l(s4 i)
1630 float builtin_i2f(s4 a)
1632 float f = (float) a;
1637 double builtin_i2d(s4 a)
1639 double d = (double) a;
1644 s4 builtin_l2i(s8 l)
1654 float builtin_l2f(s8 a)
1657 float f = (float) a;
1665 double builtin_l2d(s8 a)
1668 double d = (double) a;
1676 s4 builtin_f2i(float a)
1679 return builtin_d2i((double) a);
1688 if (a < (-2147483648))
1689 return (-2147483648);
1692 f = copysignf((float) 1.0, a);
1695 return (-2147483648); */
1699 s8 builtin_f2l(float a)
1702 return builtin_d2l((double) a);
1707 if (a > 9223372036854775807L)
1708 return 9223372036854775807L;
1709 if (a < (-9223372036854775808L))
1710 return (-9223372036854775808L);
1715 f = copysignf((float) 1.0, a);
1717 return 9223372036854775807L;
1718 return (-9223372036854775808L); */
1722 double builtin_f2d(float a)
1724 if (finitef(a)) return (double) a;
1727 return longBitsToDouble(DBL_NAN);
1729 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1734 s4 builtin_d2i(double a)
1739 if (a >= 2147483647)
1741 if (a <= (-2147483647-1))
1742 return (-2147483647-1);
1747 d = copysign(1.0, a);
1750 return (-2147483647-1);
1754 s8 builtin_d2l(double a)
1759 if (a >= 9223372036854775807LL)
1760 return 9223372036854775807LL;
1761 if (a <= (-9223372036854775807LL-1))
1762 return (-9223372036854775807LL-1);
1767 d = copysign(1.0, a);
1769 return 9223372036854775807LL;
1770 return (-9223372036854775807LL-1);
1774 float builtin_d2f(double a)
1780 return intBitsToFloat(FLT_NAN);
1782 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1787 /* used to convert FLT_xxx defines into float values */
1789 inline float intBitsToFloat(s4 i)
1798 /* used to convert DBL_xxx defines into double values */
1800 inline float longBitsToDouble(s8 l)
1809 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1811 return (java_arrayheader *)
1812 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1818 panic("Internal error: builtin_dummy called (native function is missing)");
1819 return 0; /* for the compiler */
1823 /* builtin_asm_get_exceptionptrptr *********************************************
1825 this is a wrapper for calls from asmpart
1827 *******************************************************************************/
1829 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1830 java_objectheader **builtin_asm_get_exceptionptrptr()
1832 return builtin_get_exceptionptrptr();
1837 methodinfo *builtin_asm_get_threadrootmethod()
1839 return *threadrootmethod;
1843 inline void* builtin_asm_get_stackframeinfo()
1845 /*log_text("builtin_asm_get_stackframeinfo()");*/
1846 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1847 return &THREADINFO->_stackframeinfo;
1849 #if defined(__GNUC__)
1850 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1852 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1856 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1857 /* stacktraceelement *el;*/
1860 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1861 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1863 *el=MNEW(stacktraceelement,s+1); /*GC*/
1865 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1867 #if defined(__GNUC__)
1868 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1870 (*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 */
1875 * These are local overrides for various environment variables in Emacs.
1876 * Please do not remove this and leave it at the end of the file, where
1877 * Emacs will automagically detect them.
1878 * ---------------------------------------------------------------------
1881 * indent-tabs-mode: t