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 1506 2004-11-14 14:48:49Z jowenn $
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 (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)
798 if (m->flags & ACC_NATIVE) {
800 printf(")(%p) at position %p\n", m->entrypoint, pos);
802 printf(")(%p) at position %p (", m->entrypoint, pos);
803 if (m->class->sourcefile==NULL)
804 printf("<NO CLASSFILE INFORMATION>");
806 utf_display(m->class->sourcefile);
807 printf(":%d)\n", line);
811 printf("call_java_method\n");
819 #ifdef TRACE_ARGS_NUM
820 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
821 #if TRACE_ARGS_NUM > 6
827 char logtext[MAXLOGTEXT];
828 for (i = 0; i < methodindent; i++)
831 sprintf(logtext + methodindent, "called: ");
832 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
833 sprintf(logtext + strlen(logtext), ".");
834 utf_sprint(logtext + strlen(logtext), m->name);
835 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
837 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
838 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
839 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
840 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
841 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
842 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
843 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
844 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
845 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
846 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
847 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
850 sprintf(logtext + strlen(logtext), "(");
852 switch (m->paramcount) {
856 #if defined(__I386__) || defined(__POWERPC__)
858 sprintf(logtext+strlen(logtext), "%llx", a0);
862 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
866 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
870 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
875 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
880 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
881 a0, a1, a2, a3, a4, a5);
884 #if TRACE_ARGS_NUM > 6
886 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
887 a0, a1, a2, a3, a4, a5, a6);
891 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
892 a0, a1, a2, a3, a4, a5, a6, a7);
896 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
897 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
901 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
902 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
907 sprintf(logtext+strlen(logtext), "%lx", a0);
911 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
915 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
919 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
924 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
929 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
930 a0, a1, a2, a3, a4, a5);
933 #if TRACE_ARGS_NUM > 6
935 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
936 a0, a1, a2, a3, a4, a5, a6);
940 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
941 a0, a1, a2, a3, a4, a5, a6, a7);
945 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
946 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
950 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
951 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
957 sprintf(logtext + strlen(logtext), ")");
965 void builtin_displaymethodstart(methodinfo *m)
967 char logtext[MAXLOGTEXT];
968 sprintf(logtext, " ");
969 sprintf(logtext + methodindent, "called: ");
970 utf_sprint(logtext + strlen(logtext), m->class->name);
971 sprintf(logtext + strlen(logtext), ".");
972 utf_sprint(logtext + strlen(logtext), m->name);
973 utf_sprint(logtext + strlen(logtext), m->descriptor);
975 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
976 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
977 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
978 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
979 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
980 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
981 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
982 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
983 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
984 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
985 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
992 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
995 char logtext[MAXLOGTEXT];
996 for (i = 0; i < methodindent; i++)
1001 log_text("WARNING: unmatched methodindent--");
1003 sprintf(logtext + methodindent, "finished: ");
1004 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1005 sprintf(logtext + strlen(logtext), ".");
1006 utf_sprint(logtext + strlen(logtext), m->name);
1007 utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
1009 switch (m->returntype) {
1011 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1015 #if defined(__I386__) || defined(__POWERPC__)
1016 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1018 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1023 #if defined(__I386__) || defined(__POWERPC__)
1024 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1026 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1031 sprintf(logtext + strlen(logtext), "->%g", f);
1035 sprintf(logtext + strlen(logtext), "->%g", d);
1042 /****************************************************************************
1043 SYNCHRONIZATION FUNCTIONS
1044 *****************************************************************************/
1047 * Lock the mutex of an object.
1049 void internal_lock_mutex_for_object(java_objectheader *object)
1051 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1052 mutexHashEntry *entry;
1055 assert(object != 0);
1057 hashValue = MUTEX_HASH_VALUE(object);
1058 entry = &mutexHashTable[hashValue];
1060 if (entry->object != 0) {
1061 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1063 entry->mutex.holder = 0;
1064 entry->mutex.count = 0;
1065 entry->mutex.muxWaiters = 0;
1068 while (entry->next != 0 && entry->object != object)
1069 entry = entry->next;
1071 if (entry->object != object) {
1072 entry->next = firstFreeOverflowEntry;
1073 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1075 entry = entry->next;
1078 assert(entry->conditionCount == 0);
1083 entry->mutex.holder = 0;
1084 entry->mutex.count = 0;
1085 entry->mutex.muxWaiters = 0;
1088 if (entry->object == 0)
1089 entry->object = object;
1091 internal_lock_mutex(&entry->mutex);
1097 * Unlocks the mutex of an object.
1099 void internal_unlock_mutex_for_object (java_objectheader *object)
1101 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1103 mutexHashEntry *entry;
1105 hashValue = MUTEX_HASH_VALUE(object);
1106 entry = &mutexHashTable[hashValue];
1108 if (entry->object == object) {
1109 internal_unlock_mutex(&entry->mutex);
1112 while (entry->next != 0 && entry->next->object != object)
1113 entry = entry->next;
1115 assert(entry->next != 0);
1117 internal_unlock_mutex(&entry->next->mutex);
1119 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1120 mutexHashEntry *unlinked = entry->next;
1122 entry->next = unlinked->next;
1123 unlinked->next = firstFreeOverflowEntry;
1124 firstFreeOverflowEntry = unlinked;
1131 void builtin_monitorenter(java_objectheader *o)
1133 #if defined(USE_THREADS)
1134 #if !defined(NATIVE_THREADS)
1139 hashValue = MUTEX_HASH_VALUE(o);
1140 if (mutexHashTable[hashValue].object == o
1141 && mutexHashTable[hashValue].mutex.holder == currentThread)
1142 ++mutexHashTable[hashValue].mutex.count;
1144 internal_lock_mutex_for_object(o);
1148 monitorEnter((threadobject *) THREADOBJECT, o);
1155 * Locks the class object - needed for static synchronized methods.
1156 * The use_class_as_object call is needed in order to circumvent a
1157 * possible deadlock with builtin_monitorenter called by another
1158 * thread calling use_class_as_object.
1160 void builtin_staticmonitorenter(classinfo *c)
1162 use_class_as_object(c);
1163 builtin_monitorenter(&c->header);
1167 void *builtin_monitorexit(java_objectheader *o)
1169 #if defined(USE_THREADS)
1170 #if !defined(NATIVE_THREADS)
1175 hashValue = MUTEX_HASH_VALUE(o);
1176 if (mutexHashTable[hashValue].object == o) {
1177 if (mutexHashTable[hashValue].mutex.count == 1
1178 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1179 internal_unlock_mutex_for_object(o);
1181 --mutexHashTable[hashValue].mutex.count;
1184 internal_unlock_mutex_for_object(o);
1189 monitorExit((threadobject *) THREADOBJECT, o);
1196 /*****************************************************************************
1197 MISCELLANEOUS HELPER FUNCTIONS
1198 *****************************************************************************/
1202 /*********** Functions for integer divisions *****************************
1204 On some systems (eg. DEC ALPHA), integer division is not supported by the
1205 CPU. These helper functions implement the missing functionality.
1207 ******************************************************************************/
1209 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1210 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1213 /************** Functions for long arithmetics *******************************
1215 On systems where 64 bit Integers are not supported by the CPU, these
1216 functions are needed.
1218 ******************************************************************************/
1221 s8 builtin_ladd(s8 a, s8 b)
1226 return builtin_i2l(0);
1230 s8 builtin_lsub(s8 a, s8 b)
1235 return builtin_i2l(0);
1239 s8 builtin_lmul(s8 a, s8 b)
1244 return builtin_i2l(0);
1248 s8 builtin_ldiv(s8 a, s8 b)
1253 return builtin_i2l(0);
1257 s8 builtin_lrem(s8 a, s8 b)
1262 return builtin_i2l(0);
1266 s8 builtin_lshl(s8 a, s4 b)
1269 return a << (b & 63);
1271 return builtin_i2l(0);
1275 s8 builtin_lshr(s8 a, s4 b)
1278 return a >> (b & 63);
1280 return builtin_i2l(0);
1284 s8 builtin_lushr(s8 a, s4 b)
1287 return ((u8) a) >> (b & 63);
1289 return builtin_i2l(0);
1293 s8 builtin_land(s8 a, s8 b)
1298 return builtin_i2l(0);
1302 s8 builtin_lor(s8 a, s8 b)
1307 return builtin_i2l(0);
1311 s8 builtin_lxor(s8 a, s8 b)
1316 return builtin_i2l(0);
1320 s8 builtin_lneg(s8 a)
1325 return builtin_i2l(0);
1329 s4 builtin_lcmp(s8 a, s8 b)
1332 if (a < b) return -1;
1333 if (a > b) return 1;
1344 /*********** Functions for floating point operations *************************/
1346 float builtin_fadd(float a, float b)
1348 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1349 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1360 if (copysignf(1.0, a) == copysignf(1.0, b))
1363 return intBitsToFloat(FLT_NAN);
1369 float builtin_fsub(float a, float b)
1371 return builtin_fadd(a, builtin_fneg(b));
1375 float builtin_fmul(float a, float b)
1377 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1378 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1380 if (finitef(b)) return a * b;
1382 if (a == 0) return intBitsToFloat(FLT_NAN);
1383 else return copysignf(b, copysignf(1.0, b)*a);
1388 if (b == 0) return intBitsToFloat(FLT_NAN);
1389 else return copysignf(a, copysignf(1.0, a)*b);
1392 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1398 float builtin_fdiv(float a, float b)
1400 if (finitef(a) && finitef(b)) {
1405 return intBitsToFloat(FLT_POSINF);
1407 return intBitsToFloat(FLT_NEGINF);
1410 return intBitsToFloat(FLT_NAN);
1414 float builtin_frem(float a, float b)
1420 float builtin_fneg(float a)
1422 if (isnanf(a)) return a;
1424 if (finitef(a)) return -a;
1425 else return copysignf(a, -copysignf(1.0, a));
1430 s4 builtin_fcmpl(float a, float b)
1432 if (isnanf(a)) return -1;
1433 if (isnanf(b)) return -1;
1434 if (!finitef(a) || !finitef(b)) {
1435 a = finitef(a) ? 0 : copysignf(1.0, a);
1436 b = finitef(b) ? 0 : copysignf(1.0, b);
1438 if (a > b) return 1;
1439 if (a == b) return 0;
1444 s4 builtin_fcmpg(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;
1459 /************************* Functions for doubles ****************************/
1461 double builtin_dadd(double a, double b)
1463 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1464 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1466 if (finite(b)) return a + b;
1470 if (finite(b)) return a;
1472 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1473 else return longBitsToDouble(DBL_NAN);
1479 double builtin_dsub(double a, double b)
1481 return builtin_dadd(a, builtin_dneg(b));
1485 double builtin_dmul(double a, double b)
1487 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1488 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1490 if (finite(b)) return a * b;
1492 if (a == 0) return longBitsToDouble(DBL_NAN);
1493 else return copysign(b, copysign(1.0, b) * a);
1498 if (b == 0) return longBitsToDouble(DBL_NAN);
1499 else return copysign(a, copysign(1.0, a) * b);
1502 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1508 double builtin_ddiv(double a, double b)
1516 return longBitsToDouble(DBL_NAN);
1518 return copysign(0.0, b);
1524 return longBitsToDouble(DBL_POSINF);
1526 return longBitsToDouble(DBL_NEGINF);
1529 return longBitsToDouble(DBL_NAN);
1532 /* if (finite(a) && finite(b)) { */
1537 /* return longBitsToDouble(DBL_POSINF); */
1538 /* else if (a < 0) */
1539 /* return longBitsToDouble(DBL_NEGINF); */
1543 /* keep compiler happy */
1548 double builtin_drem(double a, double b)
1554 double builtin_dneg(double a)
1556 if (isnan(a)) return a;
1558 if (finite(a)) return -a;
1559 else return copysign(a, -copysign(1.0, a));
1564 s4 builtin_dcmpl(double a, double b)
1566 if (isnan(a)) return -1;
1567 if (isnan(b)) return -1;
1568 if (!finite(a) || !finite(b)) {
1569 a = finite(a) ? 0 : copysign(1.0, a);
1570 b = finite(b) ? 0 : copysign(1.0, b);
1572 if (a > b) return 1;
1573 if (a == b) return 0;
1578 s4 builtin_dcmpg(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 /*********************** Conversion operations ****************************/
1594 s8 builtin_i2l(s4 i)
1607 float builtin_i2f(s4 a)
1609 float f = (float) a;
1614 double builtin_i2d(s4 a)
1616 double d = (double) a;
1621 s4 builtin_l2i(s8 l)
1631 float builtin_l2f(s8 a)
1634 float f = (float) a;
1642 double builtin_l2d(s8 a)
1645 double d = (double) a;
1653 s4 builtin_f2i(float a)
1656 return builtin_d2i((double) a);
1665 if (a < (-2147483648))
1666 return (-2147483648);
1669 f = copysignf((float) 1.0, a);
1672 return (-2147483648); */
1676 s8 builtin_f2l(float a)
1679 return builtin_d2l((double) a);
1684 if (a > 9223372036854775807L)
1685 return 9223372036854775807L;
1686 if (a < (-9223372036854775808L))
1687 return (-9223372036854775808L);
1692 f = copysignf((float) 1.0, a);
1694 return 9223372036854775807L;
1695 return (-9223372036854775808L); */
1699 double builtin_f2d(float a)
1701 if (finitef(a)) return (double) a;
1704 return longBitsToDouble(DBL_NAN);
1706 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1711 s4 builtin_d2i(double a)
1716 if (a >= 2147483647)
1718 if (a <= (-2147483647-1))
1719 return (-2147483647-1);
1724 d = copysign(1.0, a);
1727 return (-2147483647-1);
1731 s8 builtin_d2l(double a)
1736 if (a >= 9223372036854775807LL)
1737 return 9223372036854775807LL;
1738 if (a <= (-9223372036854775807LL-1))
1739 return (-9223372036854775807LL-1);
1744 d = copysign(1.0, a);
1746 return 9223372036854775807LL;
1747 return (-9223372036854775807LL-1);
1751 float builtin_d2f(double a)
1757 return intBitsToFloat(FLT_NAN);
1759 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1764 /* used to convert FLT_xxx defines into float values */
1766 inline float intBitsToFloat(s4 i)
1775 /* used to convert DBL_xxx defines into double values */
1777 inline float longBitsToDouble(s8 l)
1786 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1788 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1794 panic("Internal error: builtin_dummy called (native function is missing)");
1795 return 0; /* for the compiler */
1799 /* builtin_asm_get_exceptionptrptr *********************************************
1801 this is a wrapper for calls from asmpart
1803 *******************************************************************************/
1805 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1806 java_objectheader **builtin_asm_get_exceptionptrptr()
1808 return builtin_get_exceptionptrptr();
1813 methodinfo *builtin_asm_get_threadrootmethod()
1815 return *threadrootmethod;
1819 inline void* builtin_asm_get_stackframeinfo()
1821 /*log_text("builtin_asm_get_stackframeinfo()");*/
1822 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1823 return &THREADINFO->_stackframeinfo;
1825 #if defined(__GNUC__)
1826 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1828 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1832 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1833 /* stacktraceelement *el;*/
1836 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1837 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1839 *el=MNEW(stacktraceelement,s+1); /*GC*/
1841 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1843 #if defined(__GNUC__)
1844 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1846 (*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 */
1851 * These are local overrides for various environment variables in Emacs.
1852 * Please do not remove this and leave it at the end of the file, where
1853 * Emacs will automagically detect them.
1854 * ---------------------------------------------------------------------
1857 * indent-tabs-mode: t