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 1542 2004-11-18 12:19:49Z 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((java_objectheader *) 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);
485 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
493 /********************** Function: builtin_newarray **************************
495 Creates an array with the given vftbl on the heap.
497 Return value: pointer to the array or NULL if no memory is available
499 CAUTION: The given vftbl must be the vftbl of the *array* class,
500 not of the element class.
502 *****************************************************************************/
504 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
507 arraydescriptor *desc;
512 desc = arrayvftbl->arraydesc;
513 dataoffset = desc->dataoffset;
514 componentsize = desc->componentsize;
518 new_exception(string_java_lang_NegativeArraySizeException);
522 #ifdef SIZE_FROM_CLASSINFO
523 actualsize = align_size(dataoffset + size * componentsize);
524 actualsize = dataoffset + size * componentsize;
529 if (((u4) actualsize) < ((u4) size)) { /* overflow */
530 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
534 a = heap_allocate(actualsize,
535 (desc->arraytype == ARRAYTYPE_OBJECT),
541 memset(a, 0, actualsize);
543 a->objheader.vftbl = arrayvftbl;
544 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
545 initObjectLock(&a->objheader);
548 #ifdef SIZE_FROM_CLASSINFO
549 a->alignedsize = actualsize;
556 /********************** Function: builtin_anewarray *************************
558 Creates an array of references to the given class type on the heap.
560 Return value: pointer to the array or NULL if no memory is available
562 XXX This function does not do The Right Thing, because it uses a
563 classinfo pointer at runtime. builtin_newarray should be used
566 *****************************************************************************/
568 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
570 /* is class loaded */
571 if (!component->loaded)
572 if (!class_load(component))
575 /* is class linked */
576 if (!component->linked)
577 if (!class_link(component))
580 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
584 /******************** Function: builtin_newarray_int ***********************
586 Creates an array of 32 bit Integers on the heap.
588 Return value: pointer to the array or NULL if no memory is available
590 *****************************************************************************/
592 java_intarray *builtin_newarray_int(s4 size)
594 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
598 /******************** Function: builtin_newarray_long ***********************
600 Creates an array of 64 bit Integers on the heap.
602 Return value: pointer to the array or NULL if no memory is available
604 *****************************************************************************/
606 java_longarray *builtin_newarray_long(s4 size)
608 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
612 /******************** function: builtin_newarray_float ***********************
614 Creates an array of 32 bit IEEE floats on the heap.
616 Return value: pointer to the array or NULL if no memory is available
618 *****************************************************************************/
620 java_floatarray *builtin_newarray_float(s4 size)
622 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
626 /******************** function: builtin_newarray_double ***********************
628 Creates an array of 64 bit IEEE floats on the heap.
630 Return value: pointer to the array or NULL if no memory is available
632 *****************************************************************************/
634 java_doublearray *builtin_newarray_double(s4 size)
636 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
640 /******************** function: builtin_newarray_byte ***********************
642 Creates an array of 8 bit Integers on the heap.
644 Return value: pointer to the array or NULL if no memory is available
646 *****************************************************************************/
648 java_bytearray *builtin_newarray_byte(s4 size)
650 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
654 /******************** function: builtin_newarray_char ************************
656 Creates an array of characters on the heap.
658 Return value: pointer to the array or NULL if no memory is available
660 *****************************************************************************/
662 java_chararray *builtin_newarray_char(s4 size)
664 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
668 /******************** function: builtin_newarray_short ***********************
670 Creates an array of 16 bit Integers on the heap.
672 Return value: pointer to the array or NULL if no memory is available
674 *****************************************************************************/
676 java_shortarray *builtin_newarray_short(s4 size)
678 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
682 /******************** function: builtin_newarray_boolean ************************
684 Creates an array of bytes on the heap. The array is designated as an array
685 of booleans (important for casts)
687 Return value: pointer to the array or NULL if no memory is available
689 *****************************************************************************/
691 java_booleanarray *builtin_newarray_boolean(s4 size)
693 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
697 /**************** function: builtin_nmultianewarray ***************************
699 Creates a multi-dimensional array on the heap. The dimensions are passed in
703 n............number of dimensions to create
704 arrayvftbl...vftbl of the array class
705 dims.........array containing the size of each dimension to create
707 Return value: pointer to the array or NULL if no memory is available
709 ******************************************************************************/
711 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
712 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
716 vftbl_t *componentvftbl;
718 /* utf_display(arrayclass->name); */
720 /* class_load(arrayclass); */
721 /* class_link(arrayclass); */
723 /* create this dimension */
725 a = builtin_newarray(size, arrayvftbl);
726 /* a = builtin_newarray(size, arrayclass->vftbl); */
731 /* if this is the last dimension return */
735 /* get the vftbl of the components to create */
736 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
737 /* component = arrayclass->vftbl->arraydesc; */
739 /* The verifier guarantees this. */
740 /* if (!componentvftbl) */
741 /* panic ("multianewarray with too many dimensions"); */
743 /* create the component arrays */
744 for (i = 0; i < size; i++) {
745 java_arrayheader *ea =
746 builtin_nmultianewarray(n, componentvftbl, dims + 1);
751 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
758 /*****************************************************************************
761 Various functions for printing a message at method entry or exit (for
764 *****************************************************************************/
768 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
778 log_text("WARNING: unmatched methodindent--");
780 if (opt_verbose || runverbose || verboseexception) {
782 printf("Exception ");
783 utf_display_classname(xptr->vftbl->class->name);
786 printf("Some Throwable");
788 printf(" thrown in ");
791 utf_display_classname(m->class->name);
793 utf_display(m->name);
794 if (m->flags & ACC_SYNCHRONIZED) {
801 if (m->flags & ACC_NATIVE) {
804 printf(")(0x%016lx) at position %p\n", (s8) m->entrypoint, pos);
806 printf(")(0x%08lx) at position %p\n", (s4) m->entrypoint, pos);
811 printf(")(0x%016lx) at position %p (", (s8) m->entrypoint, pos);
813 printf(")(0x%08lx) at position %p (", (s4) m->entrypoint, pos);
815 if (m->class->sourcefile == NULL) {
816 printf("<NO CLASSFILE INFORMATION>");
819 utf_display(m->class->sourcefile);
821 printf(":%d)\n", line);
825 printf("call_java_method\n");
833 #ifdef TRACE_ARGS_NUM
834 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
835 #if TRACE_ARGS_NUM > 6
841 char logtext[MAXLOGTEXT];
842 for (i = 0; i < methodindent; i++)
845 sprintf(logtext + methodindent, "called: ");
846 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
847 sprintf(logtext + strlen(logtext), ".");
848 utf_sprint(logtext + strlen(logtext), m->name);
849 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
851 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
852 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
853 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
854 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
855 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
856 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
857 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
858 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
859 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
860 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
861 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
864 sprintf(logtext + strlen(logtext), "(");
866 switch (m->paramcount) {
870 #if defined(__I386__) || defined(__POWERPC__)
872 sprintf(logtext+strlen(logtext), "%llx", a0);
876 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
880 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
884 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
889 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
894 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
895 a0, a1, a2, a3, a4, a5);
898 #if TRACE_ARGS_NUM > 6
900 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
901 a0, a1, a2, a3, a4, a5, a6);
905 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
906 a0, a1, a2, a3, a4, a5, a6, a7);
910 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
911 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
915 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
916 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
921 sprintf(logtext+strlen(logtext), "%lx", a0);
925 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
929 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
933 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
938 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
943 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
944 a0, a1, a2, a3, a4, a5);
947 #if TRACE_ARGS_NUM > 6
949 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
950 a0, a1, a2, a3, a4, a5, a6);
954 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
955 a0, a1, a2, a3, a4, a5, a6, a7);
959 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
960 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
964 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
965 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
971 sprintf(logtext + strlen(logtext), ")");
979 void builtin_displaymethodstart(methodinfo *m)
981 char logtext[MAXLOGTEXT];
982 sprintf(logtext, " ");
983 sprintf(logtext + methodindent, "called: ");
984 utf_sprint(logtext + strlen(logtext), m->class->name);
985 sprintf(logtext + strlen(logtext), ".");
986 utf_sprint(logtext + strlen(logtext), m->name);
987 utf_sprint(logtext + strlen(logtext), m->descriptor);
989 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
990 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
991 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
992 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
993 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
994 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
995 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
996 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
997 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
998 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
999 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1006 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1009 char logtext[MAXLOGTEXT];
1010 for (i = 0; i < methodindent; i++)
1015 log_text("WARNING: unmatched methodindent--");
1017 sprintf(logtext + methodindent, "finished: ");
1018 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1019 sprintf(logtext + strlen(logtext), ".");
1020 utf_sprint(logtext + strlen(logtext), m->name);
1021 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1023 switch (m->returntype) {
1025 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1029 #if defined(__I386__) || defined(__POWERPC__)
1030 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1032 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1037 #if defined(__I386__) || defined(__POWERPC__)
1038 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1040 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1045 sprintf(logtext + strlen(logtext), "->%g", f);
1049 sprintf(logtext + strlen(logtext), "->%g", d);
1056 /****************************************************************************
1057 SYNCHRONIZATION FUNCTIONS
1058 *****************************************************************************/
1061 * Lock the mutex of an object.
1063 void internal_lock_mutex_for_object(java_objectheader *object)
1065 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1066 mutexHashEntry *entry;
1069 assert(object != 0);
1071 hashValue = MUTEX_HASH_VALUE(object);
1072 entry = &mutexHashTable[hashValue];
1074 if (entry->object != 0) {
1075 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1077 entry->mutex.holder = 0;
1078 entry->mutex.count = 0;
1079 entry->mutex.muxWaiters = 0;
1082 while (entry->next != 0 && entry->object != object)
1083 entry = entry->next;
1085 if (entry->object != object) {
1086 entry->next = firstFreeOverflowEntry;
1087 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1089 entry = entry->next;
1092 assert(entry->conditionCount == 0);
1097 entry->mutex.holder = 0;
1098 entry->mutex.count = 0;
1099 entry->mutex.muxWaiters = 0;
1102 if (entry->object == 0)
1103 entry->object = object;
1105 internal_lock_mutex(&entry->mutex);
1111 * Unlocks the mutex of an object.
1113 void internal_unlock_mutex_for_object (java_objectheader *object)
1115 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1117 mutexHashEntry *entry;
1119 hashValue = MUTEX_HASH_VALUE(object);
1120 entry = &mutexHashTable[hashValue];
1122 if (entry->object == object) {
1123 internal_unlock_mutex(&entry->mutex);
1126 while (entry->next != 0 && entry->next->object != object)
1127 entry = entry->next;
1129 assert(entry->next != 0);
1131 internal_unlock_mutex(&entry->next->mutex);
1133 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1134 mutexHashEntry *unlinked = entry->next;
1136 entry->next = unlinked->next;
1137 unlinked->next = firstFreeOverflowEntry;
1138 firstFreeOverflowEntry = unlinked;
1145 void builtin_monitorenter(java_objectheader *o)
1147 #if defined(USE_THREADS)
1148 #if !defined(NATIVE_THREADS)
1153 hashValue = MUTEX_HASH_VALUE(o);
1154 if (mutexHashTable[hashValue].object == o
1155 && mutexHashTable[hashValue].mutex.holder == currentThread)
1156 ++mutexHashTable[hashValue].mutex.count;
1158 internal_lock_mutex_for_object(o);
1162 monitorEnter((threadobject *) THREADOBJECT, o);
1169 * Locks the class object - needed for static synchronized methods.
1170 * The use_class_as_object call is needed in order to circumvent a
1171 * possible deadlock with builtin_monitorenter called by another
1172 * thread calling use_class_as_object.
1174 void builtin_staticmonitorenter(classinfo *c)
1176 use_class_as_object(c);
1177 builtin_monitorenter(&c->header);
1181 void *builtin_monitorexit(java_objectheader *o)
1183 #if defined(USE_THREADS)
1184 #if !defined(NATIVE_THREADS)
1189 hashValue = MUTEX_HASH_VALUE(o);
1190 if (mutexHashTable[hashValue].object == o) {
1191 if (mutexHashTable[hashValue].mutex.count == 1
1192 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1193 internal_unlock_mutex_for_object(o);
1195 --mutexHashTable[hashValue].mutex.count;
1198 internal_unlock_mutex_for_object(o);
1203 monitorExit((threadobject *) THREADOBJECT, o);
1210 /*****************************************************************************
1211 MISCELLANEOUS HELPER FUNCTIONS
1212 *****************************************************************************/
1216 /*********** Functions for integer divisions *****************************
1218 On some systems (eg. DEC ALPHA), integer division is not supported by the
1219 CPU. These helper functions implement the missing functionality.
1221 ******************************************************************************/
1223 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1224 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1227 /************** Functions for long arithmetics *******************************
1229 On systems where 64 bit Integers are not supported by the CPU, these
1230 functions are needed.
1232 ******************************************************************************/
1235 s8 builtin_ladd(s8 a, s8 b)
1240 return builtin_i2l(0);
1244 s8 builtin_lsub(s8 a, s8 b)
1249 return builtin_i2l(0);
1253 s8 builtin_lmul(s8 a, s8 b)
1258 return builtin_i2l(0);
1262 s8 builtin_ldiv(s8 a, s8 b)
1267 return builtin_i2l(0);
1271 s8 builtin_lrem(s8 a, s8 b)
1276 return builtin_i2l(0);
1280 s8 builtin_lshl(s8 a, s4 b)
1283 return a << (b & 63);
1285 return builtin_i2l(0);
1289 s8 builtin_lshr(s8 a, s4 b)
1292 return a >> (b & 63);
1294 return builtin_i2l(0);
1298 s8 builtin_lushr(s8 a, s4 b)
1301 return ((u8) a) >> (b & 63);
1303 return builtin_i2l(0);
1307 s8 builtin_land(s8 a, s8 b)
1312 return builtin_i2l(0);
1316 s8 builtin_lor(s8 a, s8 b)
1321 return builtin_i2l(0);
1325 s8 builtin_lxor(s8 a, s8 b)
1330 return builtin_i2l(0);
1334 s8 builtin_lneg(s8 a)
1339 return builtin_i2l(0);
1343 s4 builtin_lcmp(s8 a, s8 b)
1346 if (a < b) return -1;
1347 if (a > b) return 1;
1358 /*********** Functions for floating point operations *************************/
1360 float builtin_fadd(float a, float b)
1362 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1363 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1374 if (copysignf(1.0, a) == copysignf(1.0, b))
1377 return intBitsToFloat(FLT_NAN);
1383 float builtin_fsub(float a, float b)
1385 return builtin_fadd(a, builtin_fneg(b));
1389 float builtin_fmul(float a, float b)
1391 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1392 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1394 if (finitef(b)) return a * b;
1396 if (a == 0) return intBitsToFloat(FLT_NAN);
1397 else return copysignf(b, copysignf(1.0, b)*a);
1402 if (b == 0) return intBitsToFloat(FLT_NAN);
1403 else return copysignf(a, copysignf(1.0, a)*b);
1406 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1412 float builtin_fdiv(float a, float b)
1414 if (finitef(a) && finitef(b)) {
1419 return intBitsToFloat(FLT_POSINF);
1421 return intBitsToFloat(FLT_NEGINF);
1424 return intBitsToFloat(FLT_NAN);
1428 float builtin_frem(float a, float b)
1434 float builtin_fneg(float a)
1436 if (isnanf(a)) return a;
1438 if (finitef(a)) return -a;
1439 else return copysignf(a, -copysignf(1.0, a));
1444 s4 builtin_fcmpl(float a, float b)
1446 if (isnanf(a)) return -1;
1447 if (isnanf(b)) return -1;
1448 if (!finitef(a) || !finitef(b)) {
1449 a = finitef(a) ? 0 : copysignf(1.0, a);
1450 b = finitef(b) ? 0 : copysignf(1.0, b);
1452 if (a > b) return 1;
1453 if (a == b) return 0;
1458 s4 builtin_fcmpg(float a, float b)
1460 if (isnanf(a)) return 1;
1461 if (isnanf(b)) return 1;
1462 if (!finitef(a) || !finitef(b)) {
1463 a = finitef(a) ? 0 : copysignf(1.0, a);
1464 b = finitef(b) ? 0 : copysignf(1.0, b);
1466 if (a > b) return 1;
1467 if (a == b) return 0;
1473 /************************* Functions for doubles ****************************/
1475 double builtin_dadd(double a, double b)
1477 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1478 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1480 if (finite(b)) return a + b;
1484 if (finite(b)) return a;
1486 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1487 else return longBitsToDouble(DBL_NAN);
1493 double builtin_dsub(double a, double b)
1495 return builtin_dadd(a, builtin_dneg(b));
1499 double builtin_dmul(double a, double b)
1501 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1502 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1504 if (finite(b)) return a * b;
1506 if (a == 0) return longBitsToDouble(DBL_NAN);
1507 else return copysign(b, copysign(1.0, b) * a);
1512 if (b == 0) return longBitsToDouble(DBL_NAN);
1513 else return copysign(a, copysign(1.0, a) * b);
1516 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1522 double builtin_ddiv(double a, double b)
1530 return longBitsToDouble(DBL_NAN);
1532 return copysign(0.0, b);
1538 return longBitsToDouble(DBL_POSINF);
1540 return longBitsToDouble(DBL_NEGINF);
1543 return longBitsToDouble(DBL_NAN);
1546 /* if (finite(a) && finite(b)) { */
1551 /* return longBitsToDouble(DBL_POSINF); */
1552 /* else if (a < 0) */
1553 /* return longBitsToDouble(DBL_NEGINF); */
1557 /* keep compiler happy */
1562 double builtin_drem(double a, double b)
1568 double builtin_dneg(double a)
1570 if (isnan(a)) return a;
1572 if (finite(a)) return -a;
1573 else return copysign(a, -copysign(1.0, a));
1578 s4 builtin_dcmpl(double a, double b)
1580 if (isnan(a)) return -1;
1581 if (isnan(b)) return -1;
1582 if (!finite(a) || !finite(b)) {
1583 a = finite(a) ? 0 : copysign(1.0, a);
1584 b = finite(b) ? 0 : copysign(1.0, b);
1586 if (a > b) return 1;
1587 if (a == b) return 0;
1592 s4 builtin_dcmpg(double a, double b)
1594 if (isnan(a)) return 1;
1595 if (isnan(b)) return 1;
1596 if (!finite(a) || !finite(b)) {
1597 a = finite(a) ? 0 : copysign(1.0, a);
1598 b = finite(b) ? 0 : copysign(1.0, b);
1600 if (a > b) return 1;
1601 if (a == b) return 0;
1606 /*********************** Conversion operations ****************************/
1608 s8 builtin_i2l(s4 i)
1621 float builtin_i2f(s4 a)
1623 float f = (float) a;
1628 double builtin_i2d(s4 a)
1630 double d = (double) a;
1635 s4 builtin_l2i(s8 l)
1645 float builtin_l2f(s8 a)
1648 float f = (float) a;
1656 double builtin_l2d(s8 a)
1659 double d = (double) a;
1667 s4 builtin_f2i(float a)
1670 return builtin_d2i((double) a);
1679 if (a < (-2147483648))
1680 return (-2147483648);
1683 f = copysignf((float) 1.0, a);
1686 return (-2147483648); */
1690 s8 builtin_f2l(float a)
1693 return builtin_d2l((double) a);
1698 if (a > 9223372036854775807L)
1699 return 9223372036854775807L;
1700 if (a < (-9223372036854775808L))
1701 return (-9223372036854775808L);
1706 f = copysignf((float) 1.0, a);
1708 return 9223372036854775807L;
1709 return (-9223372036854775808L); */
1713 double builtin_f2d(float a)
1715 if (finitef(a)) return (double) a;
1718 return longBitsToDouble(DBL_NAN);
1720 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1725 s4 builtin_d2i(double a)
1730 if (a >= 2147483647)
1732 if (a <= (-2147483647-1))
1733 return (-2147483647-1);
1738 d = copysign(1.0, a);
1741 return (-2147483647-1);
1745 s8 builtin_d2l(double a)
1750 if (a >= 9223372036854775807LL)
1751 return 9223372036854775807LL;
1752 if (a <= (-9223372036854775807LL-1))
1753 return (-9223372036854775807LL-1);
1758 d = copysign(1.0, a);
1760 return 9223372036854775807LL;
1761 return (-9223372036854775807LL-1);
1765 float builtin_d2f(double a)
1771 return intBitsToFloat(FLT_NAN);
1773 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1778 /* used to convert FLT_xxx defines into float values */
1780 inline float intBitsToFloat(s4 i)
1789 /* used to convert DBL_xxx defines into double values */
1791 inline float longBitsToDouble(s8 l)
1800 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1802 return (java_arrayheader *)
1803 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1809 panic("Internal error: builtin_dummy called (native function is missing)");
1810 return 0; /* for the compiler */
1814 /* builtin_asm_get_exceptionptrptr *********************************************
1816 this is a wrapper for calls from asmpart
1818 *******************************************************************************/
1820 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1821 java_objectheader **builtin_asm_get_exceptionptrptr()
1823 return builtin_get_exceptionptrptr();
1828 methodinfo *builtin_asm_get_threadrootmethod()
1830 return *threadrootmethod;
1834 inline void* builtin_asm_get_stackframeinfo()
1836 /*log_text("builtin_asm_get_stackframeinfo()");*/
1837 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1838 return &THREADINFO->_stackframeinfo;
1840 #if defined(__GNUC__)
1841 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1843 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1847 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1848 /* stacktraceelement *el;*/
1851 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1852 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1854 *el=MNEW(stacktraceelement,s+1); /*GC*/
1856 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1858 #if defined(__GNUC__)
1859 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1861 (*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 */
1866 * These are local overrides for various environment variables in Emacs.
1867 * Please do not remove this and leave it at the end of the file, where
1868 * Emacs will automagically detect them.
1869 * ---------------------------------------------------------------------
1872 * indent-tabs-mode: t