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 1027 2004-04-26 15:53:01Z twisti $
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.h"
61 #undef DEBUG /*define DEBUG 1*/
63 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
64 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
66 /*****************************************************************************
68 *****************************************************************************/
72 /*************** internal function: builtin_isanysubclass *********************
74 Checks a subclass relation between two classes. Implemented interfaces
75 are interpreted as super classes.
76 Return value: 1 ... sub is subclass of super
79 *****************************************************************************/
80 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
85 if (super->flags & ACC_INTERFACE)
86 return (sub->vftbl->interfacetablelength > super->index) &&
87 (sub->vftbl->interfacetable[-super->index] != NULL);
100 for (tmp=sub;tmp!=0;tmp=tmp->super) {
102 utf_display(tmp->name);
106 for (tmp=super;tmp!=0;tmp=tmp->super) {
108 utf_display(tmp->name);
113 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
114 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
115 super->vftbl->diffval); */
117 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
121 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
122 (unsigned) (super->vftbl->diffval);
124 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
131 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
136 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
140 if ((base = super->baseval) <= 0)
141 /* super is an interface */
142 res = (sub->interfacetablelength > -base) &&
143 (sub->interfacetable[base] != NULL);
145 res = (unsigned) (sub->baseval - base)
146 <= (unsigned) (super->diffval);
148 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
156 /****************** function: builtin_instanceof *****************************
158 Checks if an object is an instance of some given class (or subclass of
159 that class). If class is an interface, checks if the interface is
161 Return value: 1 ... obj is an instance of class or implements the interface
162 0 ... otherwise or if obj == NULL
164 *****************************************************************************/
166 /* XXX should use vftbl */
167 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
170 log_text ("builtin_instanceof called");
173 return builtin_isanysubclass (obj->vftbl->class, class);
178 /**************** function: builtin_checkcast *******************************
180 The same as builtin_instanceof except that 1 is returned when
183 ****************************************************************************/
185 /* XXX should use vftbl */
186 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
189 log_text("builtin_checkcast called");
194 if (builtin_isanysubclass(obj->vftbl->class, class))
198 printf("#### checkcast failed ");
199 utf_display(obj->vftbl->class->name);
201 utf_display(class->name);
209 /*********** internal function: builtin_descriptorscompatible ******************
211 Checks if two array type descriptors are assignment compatible
212 Return value: 1 ... target = desc is possible
215 ******************************************************************************/
217 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
219 if (desc==target) return 1;
220 if (desc->arraytype != target->arraytype) return 0;
221 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
223 /* {both arrays are arrays of references} */
224 if (desc->dimension == target->dimension) {
225 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
226 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
227 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
229 if (desc->dimension < target->dimension) return 0;
231 /* {desc has higher dimension than target} */
232 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
236 /******************** function: builtin_checkarraycast ***********************
238 Checks if an object is really a subtype of the requested array type.
239 The object has to be an array to begin with. For simple arrays (int, short,
240 double, etc.) the types have to match exactly.
241 For arrays of objects, the type of elements in the array has to be a
242 subtype (or the same type) of the requested element type. For arrays of
243 arrays (which in turn can again be arrays of arrays), the types at the
244 lowest level have to satisfy the corresponding sub class relation.
246 Return value: 1 ... cast is possible
249 ATTENTION: a cast with a NULL pointer is always possible.
251 *****************************************************************************/
253 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
255 arraydescriptor *desc;
258 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
260 return builtin_descriptorscompatible(desc, target->arraydesc);
264 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
267 return builtin_checkarraycast(obj, target);
271 /************************** exception functions *******************************
273 ******************************************************************************/
275 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
278 char logtext[MAXLOGTEXT];
279 sprintf(logtext, "Builtin exception thrown: ");
280 if (local_exceptionptr) {
281 utf_sprint_classname(logtext + strlen(logtext),
282 local_exceptionptr->vftbl->class->name);
285 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
290 *exceptionptr = local_exceptionptr;
292 return local_exceptionptr;
297 /******************* function: builtin_canstore *******************************
299 Checks, if an object can be stored in an array.
300 Return value: 1 ... possible
303 ******************************************************************************/
305 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
307 arraydescriptor *desc;
308 arraydescriptor *valuedesc;
309 vftbl *componentvftbl;
316 /* The following is guaranteed (by verifier checks):
318 * *) a->...vftbl->arraydesc != NULL
319 * *) a->...vftbl->arraydesc->componentvftbl != NULL
320 * *) o->vftbl is not an interface vftbl
323 desc = a->header.objheader.vftbl->arraydesc;
324 componentvftbl = desc->componentvftbl;
325 valuevftbl = o->vftbl;
327 if ((dim_m1 = desc->dimension - 1) == 0) {
330 /* {a is a one-dimensional array} */
331 /* {a is an array of references} */
333 if (valuevftbl == componentvftbl)
336 if ((base = componentvftbl->baseval) <= 0)
337 /* an array of interface references */
338 return (valuevftbl->interfacetablelength > -base &&
339 valuevftbl->interfacetable[base] != NULL);
341 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
345 res = (unsigned)(valuevftbl->baseval - base)
346 <= (unsigned)(componentvftbl->diffval);
348 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
354 /* {a has dimension > 1} */
355 /* {componentvftbl->arraydesc != NULL} */
357 /* check if o is an array */
358 if ((valuedesc = valuevftbl->arraydesc) == NULL)
360 /* {o is an array} */
362 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
366 /* This is an optimized version where a is guaranteed to be one-dimensional */
367 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
369 arraydescriptor *desc;
377 /* The following is guaranteed (by verifier checks):
379 * *) a->...vftbl->arraydesc != NULL
380 * *) a->...vftbl->arraydesc->elementvftbl != NULL
381 * *) a->...vftbl->arraydesc->dimension == 1
382 * *) o->vftbl is not an interface vftbl
385 desc = a->header.objheader.vftbl->arraydesc;
386 elementvftbl = desc->elementvftbl;
387 valuevftbl = o->vftbl;
389 /* {a is a one-dimensional array} */
391 if (valuevftbl == elementvftbl)
394 if ((base = elementvftbl->baseval) <= 0)
395 /* an array of interface references */
396 return (valuevftbl->interfacetablelength > -base &&
397 valuevftbl->interfacetable[base] != NULL);
399 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
403 res = (unsigned)(valuevftbl->baseval - base)
404 <= (unsigned)(elementvftbl->diffval);
406 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
414 /* This is an optimized version where a is guaranteed to be a
415 * one-dimensional array of a class type */
416 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
424 /* The following is guaranteed (by verifier checks):
426 * *) a->...vftbl->arraydesc != NULL
427 * *) a->...vftbl->arraydesc->elementvftbl != NULL
428 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
429 * *) a->...vftbl->arraydesc->dimension == 1
430 * *) o->vftbl is not an interface vftbl
433 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
434 valuevftbl = o->vftbl;
436 /* {a is a one-dimensional array} */
438 if (valuevftbl == elementvftbl)
441 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
445 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
446 <= (unsigned)(elementvftbl->diffval);
448 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
456 /******************** Function: builtin_new **********************************
458 Creates a new instance of class c on the heap.
459 Return value: pointer to the object or NULL if no memory is
462 *****************************************************************************/
465 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
467 java_objectheader *builtin_new(classinfo *c)
469 java_objectheader *o;
471 /* is the class loaded */
476 /* is the class linked */
481 if (!c->initialized) {
483 char logtext[MAXLOGTEXT];
484 sprintf(logtext, "Initialize class ");
485 utf_sprint_classname(logtext + strlen(logtext), c->name);
486 sprintf(logtext + strlen(logtext), " (from builtin_new)");
489 (void) class_init(c);
491 /* we had an ExceptionInInitializerError */
497 #ifdef SIZE_FROM_CLASSINFO
498 c->alignedsize = align_size(c->instancesize);
499 o = heap_allocate(c->alignedsize, true, c->finalizer);
501 o = heap_allocate(c->instancesize, true, c->finalizer);
506 memset(o, 0, c->instancesize);
513 /********************** Function: builtin_newarray **************************
515 Creates an array with the given vftbl on the heap.
517 Return value: pointer to the array or NULL if no memory is available
519 CAUTION: The given vftbl must be the vftbl of the *array* class,
520 not of the element class.
522 *****************************************************************************/
524 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
527 arraydescriptor *desc;
532 desc = arrayvftbl->arraydesc;
533 dataoffset = desc->dataoffset;
534 componentsize = desc->componentsize;
538 new_exception(string_java_lang_NegativeArraySizeException);
542 #ifdef SIZE_FROM_CLASSINFO
543 actualsize = align_size(dataoffset + size * componentsize);
544 actualsize = dataoffset + size * componentsize;
547 if (((u4) actualsize) < ((u4) size)) { /* overflow */
548 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
552 a = heap_allocate(actualsize,
553 (desc->arraytype == ARRAYTYPE_OBJECT),
559 memset(a, 0, actualsize);
561 a->objheader.vftbl = arrayvftbl;
563 #ifdef SIZE_FROM_CLASSINFO
564 a->alignedsize = actualsize;
571 /********************** Function: builtin_anewarray *************************
573 Creates an array of references to the given class type on the heap.
575 Return value: pointer to the array or NULL if no memory is available
577 XXX This function does not do The Right Thing, because it uses a
578 classinfo pointer at runtime. builtin_newarray should be used
581 *****************************************************************************/
583 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
585 /* is class loaded */
586 if (!component->loaded)
587 class_load(component);
589 /* is class linked */
590 if (!component->linked)
591 class_link(component);
593 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
597 /******************** Function: builtin_newarray_int ***********************
599 Creates an array of 32 bit Integers on the heap.
601 Return value: pointer to the array or NULL if no memory is available
603 *****************************************************************************/
605 java_intarray *builtin_newarray_int(s4 size)
607 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
611 /******************** Function: builtin_newarray_long ***********************
613 Creates an array of 64 bit Integers on the heap.
615 Return value: pointer to the array or NULL if no memory is available
617 *****************************************************************************/
619 java_longarray *builtin_newarray_long(s4 size)
621 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
625 /******************** function: builtin_newarray_float ***********************
627 Creates an array of 32 bit IEEE floats on the heap.
629 Return value: pointer to the array or NULL if no memory is available
631 *****************************************************************************/
633 java_floatarray *builtin_newarray_float(s4 size)
635 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
639 /******************** function: builtin_newarray_double ***********************
641 Creates an array of 64 bit IEEE floats on the heap.
643 Return value: pointer to the array or NULL if no memory is available
645 *****************************************************************************/
647 java_doublearray *builtin_newarray_double(s4 size)
649 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
653 /******************** function: builtin_newarray_byte ***********************
655 Creates an array of 8 bit Integers on the heap.
657 Return value: pointer to the array or NULL if no memory is available
659 *****************************************************************************/
661 java_bytearray *builtin_newarray_byte(s4 size)
663 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
667 /******************** function: builtin_newarray_char ************************
669 Creates an array of characters on the heap.
671 Return value: pointer to the array or NULL if no memory is available
673 *****************************************************************************/
675 java_chararray *builtin_newarray_char(s4 size)
677 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
681 /******************** function: builtin_newarray_short ***********************
683 Creates an array of 16 bit Integers on the heap.
685 Return value: pointer to the array or NULL if no memory is available
687 *****************************************************************************/
689 java_shortarray *builtin_newarray_short(s4 size)
691 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
695 /******************** function: builtin_newarray_boolean ************************
697 Creates an array of bytes on the heap. The array is designated as an array
698 of booleans (important for casts)
700 Return value: pointer to the array or NULL if no memory is available
702 *****************************************************************************/
704 java_booleanarray *builtin_newarray_boolean(s4 size)
706 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
710 /**************** function: builtin_nmultianewarray ***************************
712 Creates a multi-dimensional array on the heap. The dimensions are passed in
716 n............number of dimensions to create
717 arrayvftbl...vftbl of the array class
718 dims.........array containing the size of each dimension to create
720 Return value: pointer to the array or NULL if no memory is available
722 ******************************************************************************/
724 java_arrayheader *builtin_nmultianewarray(int n, vftbl *arrayvftbl, long *dims)
725 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
729 vftbl *componentvftbl;
731 /* utf_display(arrayclass->name); */
733 /* class_load(arrayclass); */
734 /* class_link(arrayclass); */
736 /* create this dimension */
738 a = builtin_newarray(size, arrayvftbl);
739 /* a = builtin_newarray(size, arrayclass->vftbl); */
744 /* if this is the last dimension return */
748 /* get the vftbl of the components to create */
749 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
750 /* component = arrayclass->vftbl->arraydesc; */
752 /* The verifier guarantees this. */
753 /* if (!componentvftbl) */
754 /* panic ("multianewarray with too many dimensions"); */
756 /* create the component arrays */
757 for (i = 0; i < size; i++) {
758 java_arrayheader *ea =
759 builtin_nmultianewarray(n, componentvftbl, dims + 1);
764 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
771 /*****************************************************************************
774 Various functions for printing a message at method entry or exit (for
777 *****************************************************************************/
781 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
791 log_text("WARNING: unmatched methodindent--");
793 if (verbose || runverbose || verboseexception) {
795 printf("Exception ");
796 utf_display_classname(_exceptionptr->vftbl->class->name);
799 printf("Some Throwable");
801 printf(" thrown in ");
804 utf_display_classname(method->class->name);
806 utf_display(method->name);
807 if (method->flags & ACC_SYNCHRONIZED)
811 if (method->flags & ACC_NATIVE) {
813 printf(")(%p) at position %p\n", method->entrypoint, pos);
815 printf(")(%p) at position %p (",method->entrypoint,pos);
816 if (method->class->sourcefile==NULL)
817 printf("<NO CLASSFILE INFORMATION>");
819 utf_display(method->class->sourcefile);
820 printf(":%d)\n",line);
824 printf("call_java_method\n");
828 return _exceptionptr;
832 #ifdef TRACE_ARGS_NUM
833 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
834 #if TRACE_ARGS_NUM > 6
840 char logtext[MAXLOGTEXT];
841 for (i = 0; i < methodindent; i++)
844 sprintf(logtext + methodindent, "called: ");
845 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
846 sprintf(logtext + strlen(logtext), ".");
847 utf_sprint(logtext + strlen(logtext), method->name);
848 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
850 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
851 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
852 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
853 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
854 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
855 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
856 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
857 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
858 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
859 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
860 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
863 sprintf(logtext + strlen(logtext), "(");
865 switch (method->paramcount) {
869 #if defined(__I386__) || defined(__POWERPC__)
871 sprintf(logtext+strlen(logtext), "%llx", a0);
875 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
879 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
883 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
888 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
893 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
894 a0, a1, a2, a3, a4, a5);
897 #if TRACE_ARGS_NUM > 6
899 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
900 a0, a1, a2, a3, a4, a5, a6);
904 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
905 a0, a1, a2, a3, a4, a5, a6, a7);
909 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
910 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
914 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
915 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
920 sprintf(logtext+strlen(logtext), "%lx", a0);
924 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
928 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
932 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
937 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
942 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
943 a0, a1, a2, a3, a4, a5);
946 #if TRACE_ARGS_NUM > 6
948 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
949 a0, a1, a2, a3, a4, a5, a6);
953 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
954 a0, a1, a2, a3, a4, a5, a6, a7);
958 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
959 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
963 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
964 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
970 sprintf(logtext + strlen(logtext), ")");
978 void builtin_displaymethodstart(methodinfo *method)
980 char logtext[MAXLOGTEXT];
981 sprintf(logtext, " ");
982 sprintf(logtext + methodindent, "called: ");
983 utf_sprint(logtext + strlen(logtext), method->class->name);
984 sprintf(logtext + strlen(logtext), ".");
985 utf_sprint(logtext + strlen(logtext), method->name);
986 utf_sprint(logtext + strlen(logtext), method->descriptor);
988 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
989 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
990 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
991 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
992 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
993 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
994 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
995 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
996 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
997 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
998 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
1005 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1008 char logtext[MAXLOGTEXT];
1009 for (i = 0; i < methodindent; i++)
1014 log_text("WARNING: unmatched methodindent--");
1016 sprintf(logtext + methodindent, "finished: ");
1017 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
1018 sprintf(logtext + strlen(logtext), ".");
1019 utf_sprint(logtext + strlen(logtext), method->name);
1020 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
1022 switch (method->returntype) {
1024 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1028 #if defined(__I386__) || defined(__POWERPC__)
1029 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1031 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1036 #if defined(__I386__) || defined(__POWERPC__)
1037 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1039 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1044 sprintf(logtext + strlen(logtext), "->%g", f);
1048 sprintf(logtext + strlen(logtext), "->%g", d);
1055 /****************************************************************************
1056 SYNCHRONIZATION FUNCTIONS
1057 *****************************************************************************/
1060 * Lock the mutex of an object.
1062 void internal_lock_mutex_for_object(java_objectheader *object)
1064 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1065 mutexHashEntry *entry;
1068 assert(object != 0);
1070 hashValue = MUTEX_HASH_VALUE(object);
1071 entry = &mutexHashTable[hashValue];
1073 if (entry->object != 0) {
1074 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1076 entry->mutex.holder = 0;
1077 entry->mutex.count = 0;
1078 entry->mutex.muxWaiters = 0;
1081 while (entry->next != 0 && entry->object != object)
1082 entry = entry->next;
1084 if (entry->object != object) {
1085 entry->next = firstFreeOverflowEntry;
1086 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1088 entry = entry->next;
1091 assert(entry->conditionCount == 0);
1096 entry->mutex.holder = 0;
1097 entry->mutex.count = 0;
1098 entry->mutex.muxWaiters = 0;
1101 if (entry->object == 0)
1102 entry->object = object;
1104 internal_lock_mutex(&entry->mutex);
1110 * Unlocks the mutex of an object.
1112 void internal_unlock_mutex_for_object (java_objectheader *object)
1114 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1116 mutexHashEntry *entry;
1118 hashValue = MUTEX_HASH_VALUE(object);
1119 entry = &mutexHashTable[hashValue];
1121 if (entry->object == object) {
1122 internal_unlock_mutex(&entry->mutex);
1125 while (entry->next != 0 && entry->next->object != object)
1126 entry = entry->next;
1128 assert(entry->next != 0);
1130 internal_unlock_mutex(&entry->next->mutex);
1132 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1133 mutexHashEntry *unlinked = entry->next;
1135 entry->next = unlinked->next;
1136 unlinked->next = firstFreeOverflowEntry;
1137 firstFreeOverflowEntry = unlinked;
1144 void builtin_monitorenter(java_objectheader *o)
1146 #if defined(USE_THREADS)
1147 #if !defined(NATIVE_THREADS)
1150 /*log_text("Monitor enter");*/
1152 assert(blockInts == 0);
1156 hashValue = MUTEX_HASH_VALUE(o);
1157 if (mutexHashTable[hashValue].object == o
1158 && mutexHashTable[hashValue].mutex.holder == currentThread)
1159 ++mutexHashTable[hashValue].mutex.count;
1161 internal_lock_mutex_for_object(o);
1165 assert(blockInts == 0);
1167 monitorEnter((threadobject*) THREADOBJECT, o);
1173 void builtin_monitorexit (java_objectheader *o)
1176 #if defined(USE_THREADS)
1177 #if !defined(NATIVE_THREADS)
1180 /* log_text("Monitor leave"); */
1182 assert(blockInts == 0);
1186 hashValue = MUTEX_HASH_VALUE(o);
1187 if (mutexHashTable[hashValue].object == o) {
1188 if (mutexHashTable[hashValue].mutex.count == 1
1189 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1190 internal_unlock_mutex_for_object(o);
1192 --mutexHashTable[hashValue].mutex.count;
1195 internal_unlock_mutex_for_object(o);
1199 assert(blockInts == 0);
1201 monitorExit((threadobject*) THREADOBJECT, o);
1207 /*****************************************************************************
1208 MISCELLANEOUS HELPER FUNCTIONS
1209 *****************************************************************************/
1213 /*********** Functions for integer divisions *****************************
1215 On some systems (eg. DEC ALPHA), integer division is not supported by the
1216 CPU. These helper functions implement the missing functionality.
1218 ******************************************************************************/
1220 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1221 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1224 /************** Functions for long arithmetics *******************************
1226 On systems where 64 bit Integers are not supported by the CPU, these
1227 functions are needed.
1229 ******************************************************************************/
1232 s8 builtin_ladd(s8 a, s8 b)
1237 return builtin_i2l(0);
1241 s8 builtin_lsub(s8 a, s8 b)
1246 return builtin_i2l(0);
1250 s8 builtin_lmul(s8 a, s8 b)
1255 return builtin_i2l(0);
1259 s8 builtin_ldiv(s8 a, s8 b)
1264 return builtin_i2l(0);
1268 s8 builtin_lrem(s8 a, s8 b)
1273 return builtin_i2l(0);
1277 s8 builtin_lshl(s8 a, s4 b)
1280 return a << (b & 63);
1282 return builtin_i2l(0);
1286 s8 builtin_lshr(s8 a, s4 b)
1289 return a >> (b & 63);
1291 return builtin_i2l(0);
1295 s8 builtin_lushr(s8 a, s4 b)
1298 return ((u8) a) >> (b & 63);
1300 return builtin_i2l(0);
1304 s8 builtin_land(s8 a, s8 b)
1309 return builtin_i2l(0);
1313 s8 builtin_lor(s8 a, s8 b)
1318 return builtin_i2l(0);
1322 s8 builtin_lxor(s8 a, s8 b)
1327 return builtin_i2l(0);
1331 s8 builtin_lneg(s8 a)
1336 return builtin_i2l(0);
1340 s4 builtin_lcmp(s8 a, s8 b)
1343 if (a < b) return -1;
1344 if (a > b) return 1;
1355 /*********** Functions for floating point operations *************************/
1357 float builtin_fadd(float a, float b)
1359 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1360 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1371 if (copysignf(1.0, a) == copysignf(1.0, b))
1374 return intBitsToFloat(FLT_NAN);
1380 float builtin_fsub(float a, float b)
1382 return builtin_fadd(a, builtin_fneg(b));
1386 float builtin_fmul(float a, float b)
1388 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1389 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1391 if (finitef(b)) return a * b;
1393 if (a == 0) return intBitsToFloat(FLT_NAN);
1394 else return copysignf(b, copysignf(1.0, b)*a);
1399 if (b == 0) return intBitsToFloat(FLT_NAN);
1400 else return copysignf(a, copysignf(1.0, a)*b);
1403 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1409 float builtin_fdiv(float a, float b)
1411 if (finitef(a) && finitef(b)) {
1416 return intBitsToFloat(FLT_POSINF);
1418 return intBitsToFloat(FLT_NEGINF);
1421 return intBitsToFloat(FLT_NAN);
1425 float builtin_frem(float a, float b)
1431 float builtin_fneg(float a)
1433 if (isnanf(a)) return a;
1435 if (finitef(a)) return -a;
1436 else return copysignf(a, -copysignf(1.0, a));
1441 s4 builtin_fcmpl(float a, float b)
1443 if (isnanf(a)) return -1;
1444 if (isnanf(b)) return -1;
1445 if (!finitef(a) || !finitef(b)) {
1446 a = finitef(a) ? 0 : copysignf(1.0, a);
1447 b = finitef(b) ? 0 : copysignf(1.0, b);
1449 if (a > b) return 1;
1450 if (a == b) return 0;
1455 s4 builtin_fcmpg(float a, float b)
1457 if (isnanf(a)) return 1;
1458 if (isnanf(b)) return 1;
1459 if (!finitef(a) || !finitef(b)) {
1460 a = finitef(a) ? 0 : copysignf(1.0, a);
1461 b = finitef(b) ? 0 : copysignf(1.0, b);
1463 if (a > b) return 1;
1464 if (a == b) return 0;
1470 /************************* Functions for doubles ****************************/
1472 double builtin_dadd(double a, double b)
1474 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1475 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1477 if (finite(b)) return a + b;
1481 if (finite(b)) return a;
1483 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1484 else return longBitsToDouble(DBL_NAN);
1490 double builtin_dsub(double a, double b)
1492 return builtin_dadd(a, builtin_dneg(b));
1496 double builtin_dmul(double a, double b)
1498 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1499 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1501 if (finite(b)) return a * b;
1503 if (a == 0) return longBitsToDouble(DBL_NAN);
1504 else return copysign(b, copysign(1.0, b) * a);
1509 if (b == 0) return longBitsToDouble(DBL_NAN);
1510 else return copysign(a, copysign(1.0, a) * b);
1513 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1519 double builtin_ddiv(double a, double b)
1527 return longBitsToDouble(DBL_NAN);
1529 return copysign(0.0, b);
1535 return longBitsToDouble(DBL_POSINF);
1537 return longBitsToDouble(DBL_NEGINF);
1540 return longBitsToDouble(DBL_NAN);
1543 /* if (finite(a) && finite(b)) { */
1548 /* return longBitsToDouble(DBL_POSINF); */
1549 /* else if (a < 0) */
1550 /* return longBitsToDouble(DBL_NEGINF); */
1554 /* keep compiler happy */
1559 double builtin_drem(double a, double b)
1565 double builtin_dneg(double a)
1567 if (isnan(a)) return a;
1569 if (finite(a)) return -a;
1570 else return copysign(a, -copysign(1.0, a));
1575 s4 builtin_dcmpl(double a, double b)
1577 if (isnan(a)) return -1;
1578 if (isnan(b)) return -1;
1579 if (!finite(a) || !finite(b)) {
1580 a = finite(a) ? 0 : copysign(1.0, a);
1581 b = finite(b) ? 0 : copysign(1.0, b);
1583 if (a > b) return 1;
1584 if (a == b) return 0;
1589 s4 builtin_dcmpg(double a, double b)
1591 if (isnan(a)) return 1;
1592 if (isnan(b)) return 1;
1593 if (!finite(a) || !finite(b)) {
1594 a = finite(a) ? 0 : copysign(1.0, a);
1595 b = finite(b) ? 0 : copysign(1.0, b);
1597 if (a > b) return 1;
1598 if (a == b) return 0;
1603 /*********************** Conversion operations ****************************/
1605 s8 builtin_i2l(s4 i)
1618 float builtin_i2f(s4 a)
1620 float f = (float) a;
1625 double builtin_i2d(s4 a)
1627 double d = (double) a;
1632 s4 builtin_l2i(s8 l)
1642 float builtin_l2f(s8 a)
1645 float f = (float) a;
1653 double builtin_l2d(s8 a)
1656 double d = (double) a;
1664 s4 builtin_f2i(float a)
1667 return builtin_d2i((double) a);
1676 if (a < (-2147483648))
1677 return (-2147483648);
1680 f = copysignf((float) 1.0, a);
1683 return (-2147483648); */
1687 s8 builtin_f2l(float a)
1690 return builtin_d2l((double) a);
1695 if (a > 9223372036854775807L)
1696 return 9223372036854775807L;
1697 if (a < (-9223372036854775808L))
1698 return (-9223372036854775808L);
1703 f = copysignf((float) 1.0, a);
1705 return 9223372036854775807L;
1706 return (-9223372036854775808L); */
1710 double builtin_f2d(float a)
1712 if (finitef(a)) return (double) a;
1715 return longBitsToDouble(DBL_NAN);
1717 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1722 s4 builtin_d2i(double a)
1727 if (a >= 2147483647)
1729 if (a <= (-2147483647-1))
1730 return (-2147483647-1);
1735 d = copysign(1.0, a);
1738 return (-2147483647-1);
1742 s8 builtin_d2l(double a)
1747 if (a >= 9223372036854775807LL)
1748 return 9223372036854775807LL;
1749 if (a <= (-9223372036854775807LL-1))
1750 return (-9223372036854775807LL-1);
1755 d = copysign(1.0, a);
1757 return 9223372036854775807LL;
1758 return (-9223372036854775807LL-1);
1762 float builtin_d2f(double a)
1768 return intBitsToFloat(FLT_NAN);
1770 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1775 /* used to convert FLT_xxx defines into float values */
1777 inline float intBitsToFloat(s4 i)
1786 /* used to convert DBL_xxx defines into double values */
1788 inline float longBitsToDouble(s8 l)
1797 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1799 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1805 panic("Internal error: builtin_dummy called (native function is missing)");
1806 return 0; /* for the compiler */
1810 /* builtin_asm_get_exceptionptrptr *********************************************
1812 this is a wrapper for calls from asmpart
1814 *******************************************************************************/
1816 java_objectheader **builtin_asm_get_exceptionptrptr()
1818 return builtin_get_exceptionptrptr();
1822 methodinfo *builtin_asm_get_threadrootmethod()
1824 return *threadrootmethod;
1828 inline void* builtin_asm_get_stackframeinfo()
1830 /*log_text("builtin_asm_get_stackframeinfo()");*/
1831 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1832 return &THREADINFO->_stackframeinfo;
1834 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1835 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1839 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
1840 /* stacktraceelement *el;*/
1843 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
1844 *el=GCNEW(stacktraceelement,s+1);
1845 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
1847 (*el)[s].linenumber=0;
1852 * These are local overrides for various environment variables in Emacs.
1853 * Please do not remove this and leave it at the end of the file, where
1854 * Emacs will automagically detect them.
1855 * ---------------------------------------------------------------------
1858 * indent-tabs-mode: t