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 1369 2004-08-01 21:53:32Z stefan $
45 #include "exceptions.h"
54 #include "threads/thread.h"
55 #include "threads/locks.h"
56 #include "toolbox/logging.h"
57 #include "toolbox/memory.h"
58 #include "nat/java_lang_Cloneable.h"
59 #include "nat/java_lang_VMObject.h"
62 #undef DEBUG /*define DEBUG 1*/
64 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
65 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
67 /*****************************************************************************
69 *****************************************************************************/
73 /*************** internal function: builtin_isanysubclass *********************
75 Checks a subclass relation between two classes. Implemented interfaces
76 are interpreted as super classes.
77 Return value: 1 ... sub is subclass of super
80 *****************************************************************************/
81 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
87 if (super->flags & ACC_INTERFACE)
88 return (sub->vftbl->interfacetablelength > super->index) &&
89 (sub->vftbl->interfacetable[-super->index] != NULL);
102 for (tmp=sub;tmp!=0;tmp=tmp->super) {
104 utf_display(tmp->name);
108 for (tmp=super;tmp!=0;tmp=tmp->super) {
110 utf_display(tmp->name);
115 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
116 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
117 super->vftbl->diffval); */
119 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
121 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval) <=
122 (unsigned) classvalues.super_diffval;
127 s4 builtin_isanysubclass_vftbl(vftbl_t *sub,vftbl_t *super)
131 castinfo classvalues;
133 asm_getclassvalues_atomic(super, sub, &classvalues);
135 if ((base = classvalues.super_baseval) <= 0)
136 /* super is an interface */
137 res = (sub->interfacetablelength > -base) &&
138 (sub->interfacetable[base] != NULL);
140 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
141 <= (unsigned) classvalues.super_diffval;
147 /****************** function: builtin_instanceof *****************************
149 Checks if an object is an instance of some given class (or subclass of
150 that class). If class is an interface, checks if the interface is
152 Return value: 1 ... obj is an instance of class or implements the interface
153 0 ... otherwise or if obj == NULL
155 *****************************************************************************/
157 /* XXX should use vftbl */
158 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
161 log_text ("builtin_instanceof called");
164 return builtin_isanysubclass (obj->vftbl->class, class);
169 /**************** function: builtin_checkcast *******************************
171 The same as builtin_instanceof except that 1 is returned when
174 ****************************************************************************/
176 /* XXX should use vftbl */
177 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
180 log_text("builtin_checkcast called");
185 if (builtin_isanysubclass(obj->vftbl->class, class))
189 printf("#### checkcast failed ");
190 utf_display(obj->vftbl->class->name);
192 utf_display(class->name);
200 /*********** internal function: builtin_descriptorscompatible ******************
202 Checks if two array type descriptors are assignment compatible
203 Return value: 1 ... target = desc is possible
206 ******************************************************************************/
208 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
210 if (desc==target) return 1;
211 if (desc->arraytype != target->arraytype) return 0;
212 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
214 /* {both arrays are arrays of references} */
215 if (desc->dimension == target->dimension) {
216 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
217 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
218 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
220 if (desc->dimension < target->dimension) return 0;
222 /* {desc has higher dimension than target} */
223 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
227 /******************** function: builtin_checkarraycast ***********************
229 Checks if an object is really a subtype of the requested array type.
230 The object has to be an array to begin with. For simple arrays (int, short,
231 double, etc.) the types have to match exactly.
232 For arrays of objects, the type of elements in the array has to be a
233 subtype (or the same type) of the requested element type. For arrays of
234 arrays (which in turn can again be arrays of arrays), the types at the
235 lowest level have to satisfy the corresponding sub class relation.
237 Return value: 1 ... cast is possible
240 ATTENTION: a cast with a NULL pointer is always possible.
242 *****************************************************************************/
244 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
246 arraydescriptor *desc;
249 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
251 return builtin_descriptorscompatible(desc, target->arraydesc);
255 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
258 return builtin_checkarraycast(obj, target);
262 /************************** exception functions *******************************
264 ******************************************************************************/
266 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
269 char logtext[MAXLOGTEXT];
270 sprintf(logtext, "Builtin exception thrown: ");
272 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
274 utf_sprint_classname(logtext + strlen(logtext),
275 xptr->vftbl->class->name);
277 if (t->detailMessage) {
278 sprintf(logtext + strlen(logtext), ": %s",
279 javastring_tochar(t->detailMessage));
283 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
288 *exceptionptr = xptr;
295 /******************* function: builtin_canstore *******************************
297 Checks, if an object can be stored in an array.
298 Return value: 1 ... possible
301 ******************************************************************************/
303 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
305 arraydescriptor *desc;
306 arraydescriptor *valuedesc;
307 vftbl_t *componentvftbl;
311 castinfo classvalues;
315 /* The following is guaranteed (by verifier checks):
317 * *) a->...vftbl->arraydesc != NULL
318 * *) a->...vftbl->arraydesc->componentvftbl != NULL
319 * *) o->vftbl is not an interface vftbl
322 desc = a->header.objheader.vftbl->arraydesc;
323 componentvftbl = desc->componentvftbl;
324 valuevftbl = o->vftbl;
326 if ((dim_m1 = desc->dimension - 1) == 0) {
329 /* {a is a one-dimensional array} */
330 /* {a is an array of references} */
332 if (valuevftbl == componentvftbl)
335 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
337 if ((base = classvalues.super_baseval) <= 0)
338 /* an array of interface references */
339 return (valuevftbl->interfacetablelength > -base &&
340 valuevftbl->interfacetable[base] != NULL);
342 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
343 <= (unsigned) classvalues.super_diffval;
347 /* {a has dimension > 1} */
348 /* {componentvftbl->arraydesc != NULL} */
350 /* check if o is an array */
351 if ((valuedesc = valuevftbl->arraydesc) == NULL)
353 /* {o is an array} */
355 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
359 /* This is an optimized version where a is guaranteed to be one-dimensional */
360 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
362 arraydescriptor *desc;
363 vftbl_t *elementvftbl;
367 castinfo classvalues;
371 /* The following is guaranteed (by verifier checks):
373 * *) a->...vftbl->arraydesc != NULL
374 * *) a->...vftbl->arraydesc->elementvftbl != NULL
375 * *) a->...vftbl->arraydesc->dimension == 1
376 * *) o->vftbl is not an interface vftbl
379 desc = a->header.objheader.vftbl->arraydesc;
380 elementvftbl = desc->elementvftbl;
381 valuevftbl = o->vftbl;
383 /* {a is a one-dimensional array} */
385 if (valuevftbl == elementvftbl)
388 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
390 if ((base = classvalues.super_baseval) <= 0)
391 /* an array of interface references */
392 return (valuevftbl->interfacetablelength > -base &&
393 valuevftbl->interfacetable[base] != NULL);
395 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
396 <= (unsigned) classvalues.super_diffval;
402 /* This is an optimized version where a is guaranteed to be a
403 * one-dimensional array of a class type */
404 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
406 vftbl_t *elementvftbl;
409 castinfo classvalues;
413 /* The following is guaranteed (by verifier checks):
415 * *) a->...vftbl->arraydesc != NULL
416 * *) a->...vftbl->arraydesc->elementvftbl != NULL
417 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
418 * *) a->...vftbl->arraydesc->dimension == 1
419 * *) o->vftbl is not an interface vftbl
422 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
423 valuevftbl = o->vftbl;
425 /* {a is a one-dimensional array} */
427 if (valuevftbl == elementvftbl)
430 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
432 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
433 <= (unsigned) classvalues.super_diffval;
439 /******************** Function: builtin_new **********************************
441 Creates a new instance of class c on the heap.
442 Return value: pointer to the object or NULL if no memory is
445 *****************************************************************************/
448 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
450 java_objectheader *builtin_new(classinfo *c)
452 java_objectheader *o;
454 /* is the class loaded */
459 /* is the class linked */
464 if (!c->initialized) {
466 log_message_class("Initialize class (from builtin_new): ", c);
472 #ifdef SIZE_FROM_CLASSINFO
473 c->alignedsize = align_size(c->instancesize);
474 o = heap_allocate(c->alignedsize, true, c->finalizer);
476 o = heap_allocate(c->instancesize, true, c->finalizer);
482 memset(o, 0, c->instancesize);
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);
1154 * Locks the class object - needed for static synchronized methods.
1155 * The use_class_as_object call is needed in order to circumvent a
1156 * possible deadlock with builtin_monitorenter called by another
1157 * thread calling use_class_as_object.
1159 void builtin_staticmonitorenter(classinfo *c)
1161 use_class_as_object(c);
1162 builtin_monitorenter(&c->header);
1166 void *builtin_monitorexit(java_objectheader *o)
1168 #if defined(USE_THREADS)
1169 #if !defined(NATIVE_THREADS)
1174 hashValue = MUTEX_HASH_VALUE(o);
1175 if (mutexHashTable[hashValue].object == o) {
1176 if (mutexHashTable[hashValue].mutex.count == 1
1177 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1178 internal_unlock_mutex_for_object(o);
1180 --mutexHashTable[hashValue].mutex.count;
1183 internal_unlock_mutex_for_object(o);
1188 monitorExit((threadobject *) THREADOBJECT, o);
1195 /*****************************************************************************
1196 MISCELLANEOUS HELPER FUNCTIONS
1197 *****************************************************************************/
1201 /*********** Functions for integer divisions *****************************
1203 On some systems (eg. DEC ALPHA), integer division is not supported by the
1204 CPU. These helper functions implement the missing functionality.
1206 ******************************************************************************/
1208 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1209 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1212 /************** Functions for long arithmetics *******************************
1214 On systems where 64 bit Integers are not supported by the CPU, these
1215 functions are needed.
1217 ******************************************************************************/
1220 s8 builtin_ladd(s8 a, s8 b)
1225 return builtin_i2l(0);
1229 s8 builtin_lsub(s8 a, s8 b)
1234 return builtin_i2l(0);
1238 s8 builtin_lmul(s8 a, s8 b)
1243 return builtin_i2l(0);
1247 s8 builtin_ldiv(s8 a, s8 b)
1252 return builtin_i2l(0);
1256 s8 builtin_lrem(s8 a, s8 b)
1261 return builtin_i2l(0);
1265 s8 builtin_lshl(s8 a, s4 b)
1268 return a << (b & 63);
1270 return builtin_i2l(0);
1274 s8 builtin_lshr(s8 a, s4 b)
1277 return a >> (b & 63);
1279 return builtin_i2l(0);
1283 s8 builtin_lushr(s8 a, s4 b)
1286 return ((u8) a) >> (b & 63);
1288 return builtin_i2l(0);
1292 s8 builtin_land(s8 a, s8 b)
1297 return builtin_i2l(0);
1301 s8 builtin_lor(s8 a, s8 b)
1306 return builtin_i2l(0);
1310 s8 builtin_lxor(s8 a, s8 b)
1315 return builtin_i2l(0);
1319 s8 builtin_lneg(s8 a)
1324 return builtin_i2l(0);
1328 s4 builtin_lcmp(s8 a, s8 b)
1331 if (a < b) return -1;
1332 if (a > b) return 1;
1343 /*********** Functions for floating point operations *************************/
1345 float builtin_fadd(float a, float b)
1347 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1348 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1359 if (copysignf(1.0, a) == copysignf(1.0, b))
1362 return intBitsToFloat(FLT_NAN);
1368 float builtin_fsub(float a, float b)
1370 return builtin_fadd(a, builtin_fneg(b));
1374 float builtin_fmul(float a, float b)
1376 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1377 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1379 if (finitef(b)) return a * b;
1381 if (a == 0) return intBitsToFloat(FLT_NAN);
1382 else return copysignf(b, copysignf(1.0, b)*a);
1387 if (b == 0) return intBitsToFloat(FLT_NAN);
1388 else return copysignf(a, copysignf(1.0, a)*b);
1391 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1397 float builtin_fdiv(float a, float b)
1399 if (finitef(a) && finitef(b)) {
1404 return intBitsToFloat(FLT_POSINF);
1406 return intBitsToFloat(FLT_NEGINF);
1409 return intBitsToFloat(FLT_NAN);
1413 float builtin_frem(float a, float b)
1419 float builtin_fneg(float a)
1421 if (isnanf(a)) return a;
1423 if (finitef(a)) return -a;
1424 else return copysignf(a, -copysignf(1.0, a));
1429 s4 builtin_fcmpl(float a, float b)
1431 if (isnanf(a)) return -1;
1432 if (isnanf(b)) return -1;
1433 if (!finitef(a) || !finitef(b)) {
1434 a = finitef(a) ? 0 : copysignf(1.0, a);
1435 b = finitef(b) ? 0 : copysignf(1.0, b);
1437 if (a > b) return 1;
1438 if (a == b) return 0;
1443 s4 builtin_fcmpg(float a, float b)
1445 if (isnanf(a)) return 1;
1446 if (isnanf(b)) return 1;
1447 if (!finitef(a) || !finitef(b)) {
1448 a = finitef(a) ? 0 : copysignf(1.0, a);
1449 b = finitef(b) ? 0 : copysignf(1.0, b);
1451 if (a > b) return 1;
1452 if (a == b) return 0;
1458 /************************* Functions for doubles ****************************/
1460 double builtin_dadd(double a, double b)
1462 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1463 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1465 if (finite(b)) return a + b;
1469 if (finite(b)) return a;
1471 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1472 else return longBitsToDouble(DBL_NAN);
1478 double builtin_dsub(double a, double b)
1480 return builtin_dadd(a, builtin_dneg(b));
1484 double builtin_dmul(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;
1491 if (a == 0) return longBitsToDouble(DBL_NAN);
1492 else return copysign(b, copysign(1.0, b) * a);
1497 if (b == 0) return longBitsToDouble(DBL_NAN);
1498 else return copysign(a, copysign(1.0, a) * b);
1501 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1507 double builtin_ddiv(double a, double b)
1515 return longBitsToDouble(DBL_NAN);
1517 return copysign(0.0, b);
1523 return longBitsToDouble(DBL_POSINF);
1525 return longBitsToDouble(DBL_NEGINF);
1528 return longBitsToDouble(DBL_NAN);
1531 /* if (finite(a) && finite(b)) { */
1536 /* return longBitsToDouble(DBL_POSINF); */
1537 /* else if (a < 0) */
1538 /* return longBitsToDouble(DBL_NEGINF); */
1542 /* keep compiler happy */
1547 double builtin_drem(double a, double b)
1553 double builtin_dneg(double a)
1555 if (isnan(a)) return a;
1557 if (finite(a)) return -a;
1558 else return copysign(a, -copysign(1.0, a));
1563 s4 builtin_dcmpl(double a, double b)
1565 if (isnan(a)) return -1;
1566 if (isnan(b)) return -1;
1567 if (!finite(a) || !finite(b)) {
1568 a = finite(a) ? 0 : copysign(1.0, a);
1569 b = finite(b) ? 0 : copysign(1.0, b);
1571 if (a > b) return 1;
1572 if (a == b) return 0;
1577 s4 builtin_dcmpg(double a, double b)
1579 if (isnan(a)) return 1;
1580 if (isnan(b)) return 1;
1581 if (!finite(a) || !finite(b)) {
1582 a = finite(a) ? 0 : copysign(1.0, a);
1583 b = finite(b) ? 0 : copysign(1.0, b);
1585 if (a > b) return 1;
1586 if (a == b) return 0;
1591 /*********************** Conversion operations ****************************/
1593 s8 builtin_i2l(s4 i)
1606 float builtin_i2f(s4 a)
1608 float f = (float) a;
1613 double builtin_i2d(s4 a)
1615 double d = (double) a;
1620 s4 builtin_l2i(s8 l)
1630 float builtin_l2f(s8 a)
1633 float f = (float) a;
1641 double builtin_l2d(s8 a)
1644 double d = (double) a;
1652 s4 builtin_f2i(float a)
1655 return builtin_d2i((double) a);
1664 if (a < (-2147483648))
1665 return (-2147483648);
1668 f = copysignf((float) 1.0, a);
1671 return (-2147483648); */
1675 s8 builtin_f2l(float a)
1678 return builtin_d2l((double) a);
1683 if (a > 9223372036854775807L)
1684 return 9223372036854775807L;
1685 if (a < (-9223372036854775808L))
1686 return (-9223372036854775808L);
1691 f = copysignf((float) 1.0, a);
1693 return 9223372036854775807L;
1694 return (-9223372036854775808L); */
1698 double builtin_f2d(float a)
1700 if (finitef(a)) return (double) a;
1703 return longBitsToDouble(DBL_NAN);
1705 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1710 s4 builtin_d2i(double a)
1715 if (a >= 2147483647)
1717 if (a <= (-2147483647-1))
1718 return (-2147483647-1);
1723 d = copysign(1.0, a);
1726 return (-2147483647-1);
1730 s8 builtin_d2l(double a)
1735 if (a >= 9223372036854775807LL)
1736 return 9223372036854775807LL;
1737 if (a <= (-9223372036854775807LL-1))
1738 return (-9223372036854775807LL-1);
1743 d = copysign(1.0, a);
1745 return 9223372036854775807LL;
1746 return (-9223372036854775807LL-1);
1750 float builtin_d2f(double a)
1756 return intBitsToFloat(FLT_NAN);
1758 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1763 /* used to convert FLT_xxx defines into float values */
1765 inline float intBitsToFloat(s4 i)
1774 /* used to convert DBL_xxx defines into double values */
1776 inline float longBitsToDouble(s8 l)
1785 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1787 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1793 panic("Internal error: builtin_dummy called (native function is missing)");
1794 return 0; /* for the compiler */
1798 /* builtin_asm_get_exceptionptrptr *********************************************
1800 this is a wrapper for calls from asmpart
1802 *******************************************************************************/
1804 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1805 java_objectheader **builtin_asm_get_exceptionptrptr()
1807 return builtin_get_exceptionptrptr();
1812 methodinfo *builtin_asm_get_threadrootmethod()
1814 return *threadrootmethod;
1818 inline void* builtin_asm_get_stackframeinfo()
1820 /*log_text("builtin_asm_get_stackframeinfo()");*/
1821 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1822 return &THREADINFO->_stackframeinfo;
1824 #if defined(__GNUC__)
1825 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1827 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1831 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1832 /* stacktraceelement *el;*/
1835 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1836 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
1838 *el=MNEW(stacktraceelement,s+1); /*GC*/
1840 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1842 #if defined(__GNUC__)
1843 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
1845 (*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 */
1850 * These are local overrides for various environment variables in Emacs.
1851 * Please do not remove this and leave it at the end of the file, where
1852 * Emacs will automagically detect them.
1853 * ---------------------------------------------------------------------
1856 * indent-tabs-mode: t