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 921 2004-02-16 04:00:59Z jowenn $
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*/
64 /*****************************************************************************
66 *****************************************************************************/
70 /*************** internal function: builtin_isanysubclass *********************
72 Checks a subclass relation between two classes. Implemented interfaces
73 are interpreted as super classes.
74 Return value: 1 ... sub is subclass of super
77 *****************************************************************************/
78 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
83 if (super->flags & ACC_INTERFACE)
84 return (sub->vftbl->interfacetablelength > super->index) &&
85 (sub->vftbl->interfacetable[-super->index] != NULL);
98 for (tmp=sub;tmp!=0;tmp=tmp->super) {
100 utf_display(tmp->name);
104 for (tmp=super;tmp!=0;tmp=tmp->super) {
106 utf_display(tmp->name);
111 printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
112 sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
113 super->vftbl->diffval); */
115 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
119 res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
120 (unsigned) (super->vftbl->diffval);
122 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
129 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
138 if ((base = super->baseval) <= 0)
139 /* super is an interface */
140 res = (sub->interfacetablelength > -base) &&
141 (sub->interfacetable[base] != NULL);
143 res = (unsigned) (sub->baseval - base)
144 <= (unsigned) (super->diffval);
146 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
154 /****************** function: builtin_instanceof *****************************
156 Checks if an object is an instance of some given class (or subclass of
157 that class). If class is an interface, checks if the interface is
159 Return value: 1 ... obj is an instance of class or implements the interface
160 0 ... otherwise or if obj == NULL
162 *****************************************************************************/
164 /* XXX should use vftbl */
165 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
168 log_text ("builtin_instanceof called");
171 return builtin_isanysubclass (obj->vftbl->class, class);
176 /**************** function: builtin_checkcast *******************************
178 The same as builtin_instanceof except that 1 is returned when
181 ****************************************************************************/
183 /* XXX should use vftbl */
184 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
187 log_text("builtin_checkcast called");
192 if (builtin_isanysubclass(obj->vftbl->class, class))
196 printf("#### checkcast failed ");
197 utf_display(obj->vftbl->class->name);
199 utf_display(class->name);
207 /*********** internal function: builtin_descriptorscompatible ******************
209 Checks if two array type descriptors are assignment compatible
210 Return value: 1 ... target = desc is possible
213 ******************************************************************************/
215 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
217 if (desc==target) return 1;
218 if (desc->arraytype != target->arraytype) return 0;
219 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
221 /* {both arrays are arrays of references} */
222 if (desc->dimension == target->dimension) {
223 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
224 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
225 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
227 if (desc->dimension < target->dimension) return 0;
229 /* {desc has higher dimension than target} */
230 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
234 /******************** function: builtin_checkarraycast ***********************
236 Checks if an object is really a subtype of the requested array type.
237 The object has to be an array to begin with. For simple arrays (int, short,
238 double, etc.) the types have to match exactly.
239 For arrays of objects, the type of elements in the array has to be a
240 subtype (or the same type) of the requested element type. For arrays of
241 arrays (which in turn can again be arrays of arrays), the types at the
242 lowest level have to satisfy the corresponding sub class relation.
244 Return value: 1 ... cast is possible
247 ATTENTION: a cast with a NULL pointer is always possible.
249 *****************************************************************************/
251 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
253 arraydescriptor *desc;
256 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
258 return builtin_descriptorscompatible(desc, target->arraydesc);
262 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
265 return builtin_checkarraycast(obj, target);
269 /************************** exception functions *******************************
271 ******************************************************************************/
273 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
276 char logtext[MAXLOGTEXT];
277 sprintf(logtext, "Builtin exception thrown: ");
278 if (local_exceptionptr)
279 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
281 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
282 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
283 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
284 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
285 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
286 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
287 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
288 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
289 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
290 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
291 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
295 *exceptionptr = local_exceptionptr;
296 return local_exceptionptr;
299 void builtin_reset_exceptionptr()
301 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
303 _exceptionptr = NULL;
305 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
308 panic("builtin_reset_exceptionptr should not be used in this configuration");
313 /******************* function: builtin_canstore *******************************
315 Checks, if an object can be stored in an array.
316 Return value: 1 ... possible
319 ******************************************************************************/
321 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
323 arraydescriptor *desc;
324 arraydescriptor *valuedesc;
325 vftbl *componentvftbl;
332 /* The following is guaranteed (by verifier checks):
334 * *) a->...vftbl->arraydesc != NULL
335 * *) a->...vftbl->arraydesc->componentvftbl != NULL
336 * *) o->vftbl is not an interface vftbl
339 desc = a->header.objheader.vftbl->arraydesc;
340 componentvftbl = desc->componentvftbl;
341 valuevftbl = o->vftbl;
343 if ((dim_m1 = desc->dimension - 1) == 0) {
346 /* {a is a one-dimensional array} */
347 /* {a is an array of references} */
349 if (valuevftbl == componentvftbl)
352 if ((base = componentvftbl->baseval) <= 0)
353 /* an array of interface references */
354 return (valuevftbl->interfacetablelength > -base &&
355 valuevftbl->interfacetable[base] != NULL);
357 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
361 res = (unsigned)(valuevftbl->baseval - base)
362 <= (unsigned)(componentvftbl->diffval);
364 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
370 /* {a has dimension > 1} */
371 /* {componentvftbl->arraydesc != NULL} */
373 /* check if o is an array */
374 if ((valuedesc = valuevftbl->arraydesc) == NULL)
376 /* {o is an array} */
378 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
382 /* This is an optimized version where a is guaranteed to be one-dimensional */
383 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
385 arraydescriptor *desc;
393 /* The following is guaranteed (by verifier checks):
395 * *) a->...vftbl->arraydesc != NULL
396 * *) a->...vftbl->arraydesc->elementvftbl != NULL
397 * *) a->...vftbl->arraydesc->dimension == 1
398 * *) o->vftbl is not an interface vftbl
401 desc = a->header.objheader.vftbl->arraydesc;
402 elementvftbl = desc->elementvftbl;
403 valuevftbl = o->vftbl;
405 /* {a is a one-dimensional array} */
407 if (valuevftbl == elementvftbl)
410 if ((base = elementvftbl->baseval) <= 0)
411 /* an array of interface references */
412 return (valuevftbl->interfacetablelength > -base &&
413 valuevftbl->interfacetable[base] != NULL);
415 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
419 res = (unsigned)(valuevftbl->baseval - base)
420 <= (unsigned)(elementvftbl->diffval);
422 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
430 /* This is an optimized version where a is guaranteed to be a
431 * one-dimensional array of a class type */
432 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
440 /* The following is guaranteed (by verifier checks):
442 * *) a->...vftbl->arraydesc != NULL
443 * *) a->...vftbl->arraydesc->elementvftbl != NULL
444 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
445 * *) a->...vftbl->arraydesc->dimension == 1
446 * *) o->vftbl is not an interface vftbl
449 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
450 valuevftbl = o->vftbl;
452 /* {a is a one-dimensional array} */
454 if (valuevftbl == elementvftbl)
457 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
461 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
462 <= (unsigned)(elementvftbl->diffval);
464 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
472 /******************** Function: builtin_new **********************************
474 Creates a new instance of class c on the heap.
475 Return value: pointer to the object or NULL if no memory is
478 *****************************************************************************/
481 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
483 java_objectheader *builtin_new(classinfo *c)
485 java_objectheader *o;
487 if (!c->initialized) {
489 char logtext[MAXLOGTEXT];
490 sprintf(logtext, "Initialize class ");
491 utf_sprint(logtext + strlen(logtext), c->name);
492 sprintf(logtext + strlen(logtext), " (from builtin_new)");
498 #ifdef SIZE_FROM_CLASSINFO
499 c->alignedsize = align_size(c->instancesize);
500 o = heap_allocate(c->alignedsize, true, c->finalizer);
502 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 = arrayvftbl->arraydesc;
528 s4 dataoffset = desc->dataoffset;
529 s4 componentsize = desc->componentsize;
533 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
536 #ifdef SIZE_FROM_CLASSINFO
537 actualsize = align_size(dataoffset + size * componentsize);
539 actualsize = dataoffset + size * componentsize;
542 if (((u4)actualsize)<((u4)size)) { /* overflow */
543 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
546 a = heap_allocate(actualsize,
547 (desc->arraytype == ARRAYTYPE_OBJECT),
551 memset(a, 0, actualsize);
554 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
556 a->objheader.vftbl = arrayvftbl;
558 #ifdef SIZE_FROM_CLASSINFO
559 a->alignedsize = actualsize;
566 /********************** Function: builtin_anewarray *************************
568 Creates an array of references to the given class type on the heap.
570 Return value: pointer to the array or NULL if no memory is available
572 XXX This function does not do The Right Thing, because it uses a
573 classinfo pointer at runtime. builtin_newarray should be used
576 *****************************************************************************/
578 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
581 printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
582 printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
583 utf_display(component->vftbl->class->name);
584 printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
585 utf_display(component->super->name);*/
586 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
590 /******************** Function: builtin_newarray_int ***********************
592 Creates an array of 32 bit Integers on the heap.
594 Return value: pointer to the array or NULL if no memory is available
596 *****************************************************************************/
598 java_intarray *builtin_newarray_int(s4 size)
600 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
604 /******************** Function: builtin_newarray_long ***********************
606 Creates an array of 64 bit Integers on the heap.
608 Return value: pointer to the array or NULL if no memory is available
610 *****************************************************************************/
612 java_longarray *builtin_newarray_long(s4 size)
614 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
618 /******************** function: builtin_newarray_float ***********************
620 Creates an array of 32 bit IEEE floats on the heap.
622 Return value: pointer to the array or NULL if no memory is available
624 *****************************************************************************/
626 java_floatarray *builtin_newarray_float(s4 size)
628 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
632 /******************** function: builtin_newarray_double ***********************
634 Creates an array of 64 bit IEEE floats on the heap.
636 Return value: pointer to the array or NULL if no memory is available
638 *****************************************************************************/
640 java_doublearray *builtin_newarray_double(s4 size)
642 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
646 /******************** function: builtin_newarray_byte ***********************
648 Creates an array of 8 bit Integers on the heap.
650 Return value: pointer to the array or NULL if no memory is available
652 *****************************************************************************/
654 java_bytearray *builtin_newarray_byte(s4 size)
656 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
660 /******************** function: builtin_newarray_char ************************
662 Creates an array of characters on the heap.
664 Return value: pointer to the array or NULL if no memory is available
666 *****************************************************************************/
668 java_chararray *builtin_newarray_char(s4 size)
670 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
674 /******************** function: builtin_newarray_short ***********************
676 Creates an array of 16 bit Integers on the heap.
678 Return value: pointer to the array or NULL if no memory is available
680 *****************************************************************************/
682 java_shortarray *builtin_newarray_short(s4 size)
684 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
688 /******************** function: builtin_newarray_boolean ************************
690 Creates an array of bytes on the heap. The array is designated as an array
691 of booleans (important for casts)
693 Return value: pointer to the array or NULL if no memory is available
695 *****************************************************************************/
697 java_booleanarray *builtin_newarray_boolean(s4 size)
699 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
703 /**************** function: builtin_nmultianewarray ***************************
705 Creates a multi-dimensional array on the heap. The dimensions are passed in
709 n............number of dimensions to create
710 arrayvftbl...vftbl of the array class
711 dims.........array containing the size of each dimension to create
713 Return value: pointer to the array or NULL if no memory is available
715 ******************************************************************************/
717 /* Helper functions */
719 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
723 vftbl *componentvftbl;
725 /* create this dimension */
726 size = (int) dims[0];
727 a = builtin_newarray(size,arrayvftbl);
730 /* if this is the last dimension return */
733 /* get the vftbl of the components to create */
734 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
736 /* The verifier guarantees this. */
737 /* if (!componentvftbl) */
738 /* panic ("multianewarray with too many dimensions"); */
740 /* create the component arrays */
741 for (i = 0; i < size; i++) {
742 java_arrayheader *ea =
743 builtin_nmultianewarray(n,componentvftbl,dims+1);
744 if (!ea) return NULL;
745 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
752 /*****************************************************************************
755 Various functions for printing a message at method entry or exit (for
758 *****************************************************************************/
763 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
764 methodinfo *method, int *pos,
771 log_text("WARNING: unmatched methodindent--");
773 if (verbose || runverbose) {
774 printf("Exception ");
776 utf_display(_exceptionptr->vftbl->class->name);
779 printf("Error: <Nullpointer instead of exception>");
780 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
781 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
782 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
783 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
784 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
785 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
786 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
787 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
788 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
789 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
792 printf(" thrown in ");
795 utf_display(method->class->name);
797 utf_display(method->name);
798 if (method->flags & ACC_SYNCHRONIZED)
802 printf("(%p) at position %p\n", method->entrypoint, pos);
805 printf("call_java_method\n");
809 return _exceptionptr;
813 #ifdef TRACE_ARGS_NUM
814 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
815 #if TRACE_ARGS_NUM > 6
821 char logtext[MAXLOGTEXT];
822 for (i = 0; i < methodindent; i++)
824 sprintf(logtext + methodindent, "called: ");
825 utf_sprint(logtext + strlen(logtext), method->class->name);
826 sprintf(logtext + strlen(logtext), ".");
827 utf_sprint(logtext + strlen(logtext), method->name);
828 utf_sprint(logtext + strlen(logtext), method->descriptor);
830 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
831 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
832 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
833 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
834 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
835 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
836 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
837 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
838 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
839 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
840 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
843 sprintf(logtext + strlen(logtext), "(");
845 switch (method->paramcount) {
849 #if defined(__I386__)
851 sprintf(logtext+strlen(logtext), "%llx", a0);
855 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
859 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
863 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
868 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
873 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
874 a0, a1, a2, a3, a4, a5);
877 #if TRACE_ARGS_NUM > 6
879 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
880 a0, a1, a2, a3, a4, a5, a6);
884 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
885 a0, a1, a2, a3, a4, a5, a6, a7);
889 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
890 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
894 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
895 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
900 sprintf(logtext+strlen(logtext), "%lx", a0);
904 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
908 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
912 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
917 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
922 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
923 a0, a1, a2, a3, a4, a5);
926 #if TRACE_ARGS_NUM > 6
928 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
929 a0, a1, a2, a3, a4, a5, a6);
933 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
934 a0, a1, a2, a3, a4, a5, a6, a7);
938 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
939 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
943 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
944 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
949 sprintf (logtext+strlen(logtext), ")");
957 void builtin_displaymethodstart(methodinfo *method)
959 char logtext[MAXLOGTEXT];
960 sprintf(logtext, " ");
961 sprintf(logtext + methodindent, "called: ");
962 utf_sprint(logtext + strlen(logtext), method->class->name);
963 sprintf(logtext + strlen(logtext), ".");
964 utf_sprint(logtext + strlen(logtext), method->name);
965 utf_sprint(logtext + strlen(logtext), method->descriptor);
967 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
968 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
969 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
970 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
971 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
972 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
973 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
974 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
975 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
976 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
977 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
984 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
987 char logtext[MAXLOGTEXT];
988 for (i = 0; i < methodindent; i++)
993 log_text("WARNING: unmatched methodindent--");
994 sprintf(logtext + methodindent, "finished: ");
995 utf_sprint(logtext + strlen(logtext), method->class->name);
996 sprintf(logtext + strlen(logtext), ".");
997 utf_sprint(logtext + strlen(logtext), method->name);
998 utf_sprint(logtext + strlen(logtext), method->descriptor);
1000 switch (method->returntype) {
1002 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1005 #if defined(__I386__)
1006 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1008 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1012 #if defined(__I386__)
1013 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1015 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1019 sprintf(logtext + strlen(logtext), "->%g", f);
1022 sprintf(logtext + strlen(logtext), "->%g", d);
1029 void builtin_displaymethodexception(methodinfo *method)
1032 char logtext[MAXLOGTEXT];
1033 for (i = 0; i < methodindent; i++)
1035 sprintf(logtext + methodindent, "exception abort: ");
1036 utf_sprint(logtext + strlen(logtext), method->class->name);
1037 sprintf(logtext + strlen(logtext), ".");
1038 utf_sprint(logtext + strlen(logtext), method->name);
1039 utf_sprint(logtext + strlen(logtext), method->descriptor);
1044 /****************************************************************************
1045 SYNCHRONIZATION FUNCTIONS
1046 *****************************************************************************/
1049 * Lock the mutex of an object.
1051 void internal_lock_mutex_for_object(java_objectheader *object)
1053 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1054 mutexHashEntry *entry;
1057 assert(object != 0);
1059 hashValue = MUTEX_HASH_VALUE(object);
1060 entry = &mutexHashTable[hashValue];
1062 if (entry->object != 0) {
1063 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1065 entry->mutex.holder = 0;
1066 entry->mutex.count = 0;
1067 entry->mutex.muxWaiters = 0;
1070 while (entry->next != 0 && entry->object != object)
1071 entry = entry->next;
1073 if (entry->object != object) {
1074 entry->next = firstFreeOverflowEntry;
1075 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1077 entry = entry->next;
1080 assert(entry->conditionCount == 0);
1085 entry->mutex.holder = 0;
1086 entry->mutex.count = 0;
1087 entry->mutex.muxWaiters = 0;
1090 if (entry->object == 0)
1091 entry->object = object;
1093 internal_lock_mutex(&entry->mutex);
1099 * Unlocks the mutex of an object.
1101 void internal_unlock_mutex_for_object (java_objectheader *object)
1103 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1105 mutexHashEntry *entry;
1107 hashValue = MUTEX_HASH_VALUE(object);
1108 entry = &mutexHashTable[hashValue];
1110 if (entry->object == object) {
1111 internal_unlock_mutex(&entry->mutex);
1114 while (entry->next != 0 && entry->next->object != object)
1115 entry = entry->next;
1117 assert(entry->next != 0);
1119 internal_unlock_mutex(&entry->next->mutex);
1121 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1122 mutexHashEntry *unlinked = entry->next;
1124 entry->next = unlinked->next;
1125 unlinked->next = firstFreeOverflowEntry;
1126 firstFreeOverflowEntry = unlinked;
1133 void builtin_monitorenter(java_objectheader *o)
1135 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1138 assert(blockInts == 0);
1142 hashValue = MUTEX_HASH_VALUE(o);
1143 if (mutexHashTable[hashValue].object == o
1144 && mutexHashTable[hashValue].mutex.holder == currentThread)
1145 ++mutexHashTable[hashValue].mutex.count;
1147 internal_lock_mutex_for_object(o);
1151 assert(blockInts == 0);
1156 void builtin_monitorexit (java_objectheader *o)
1158 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1161 assert(blockInts == 0);
1165 hashValue = MUTEX_HASH_VALUE(o);
1166 if (mutexHashTable[hashValue].object == o) {
1167 if (mutexHashTable[hashValue].mutex.count == 1
1168 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1169 internal_unlock_mutex_for_object(o);
1171 --mutexHashTable[hashValue].mutex.count;
1174 internal_unlock_mutex_for_object(o);
1178 assert(blockInts == 0);
1183 /*****************************************************************************
1184 MISCELLANEOUS HELPER FUNCTIONS
1185 *****************************************************************************/
1189 /*********** Functions for integer divisions *****************************
1191 On some systems (eg. DEC ALPHA), integer division is not supported by the
1192 CPU. These helper functions implement the missing functionality.
1194 ******************************************************************************/
1196 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1197 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1200 /************** Functions for long arithmetics *******************************
1202 On systems where 64 bit Integers are not supported by the CPU, these
1203 functions are needed.
1205 ******************************************************************************/
1208 s8 builtin_ladd(s8 a, s8 b)
1213 return builtin_i2l(0);
1217 s8 builtin_lsub(s8 a, s8 b)
1222 return builtin_i2l(0);
1226 s8 builtin_lmul(s8 a, s8 b)
1231 return builtin_i2l(0);
1235 s8 builtin_ldiv(s8 a, s8 b)
1240 return builtin_i2l(0);
1244 s8 builtin_lrem(s8 a, s8 b)
1249 return builtin_i2l(0);
1253 s8 builtin_lshl(s8 a, s4 b)
1256 return a << (b & 63);
1258 return builtin_i2l(0);
1262 s8 builtin_lshr(s8 a, s4 b)
1265 return a >> (b & 63);
1267 return builtin_i2l(0);
1271 s8 builtin_lushr(s8 a, s4 b)
1274 return ((u8) a) >> (b & 63);
1276 return builtin_i2l(0);
1280 s8 builtin_land(s8 a, s8 b)
1285 return builtin_i2l(0);
1289 s8 builtin_lor(s8 a, s8 b)
1294 return builtin_i2l(0);
1298 s8 builtin_lxor(s8 a, s8 b)
1303 return builtin_i2l(0);
1307 s8 builtin_lneg(s8 a)
1312 return builtin_i2l(0);
1316 s4 builtin_lcmp(s8 a, s8 b)
1319 if (a < b) return -1;
1320 if (a > b) return 1;
1331 /*********** Functions for floating point operations *************************/
1333 float builtin_fadd(float a, float b)
1335 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1336 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1347 if (copysignf(1.0, a) == copysignf(1.0, b))
1350 return intBitsToFloat(FLT_NAN);
1356 float builtin_fsub(float a, float b)
1358 return builtin_fadd(a, builtin_fneg(b));
1362 float builtin_fmul(float a, float b)
1364 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1365 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1367 if (finitef(b)) return a * b;
1369 if (a == 0) return intBitsToFloat(FLT_NAN);
1370 else return copysignf(b, copysignf(1.0, b)*a);
1375 if (b == 0) return intBitsToFloat(FLT_NAN);
1376 else return copysignf(a, copysignf(1.0, a)*b);
1379 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1385 float builtin_fdiv(float a, float b)
1387 if (finitef(a) && finitef(b)) {
1392 return intBitsToFloat(FLT_POSINF);
1394 return intBitsToFloat(FLT_NEGINF);
1397 return intBitsToFloat(FLT_NAN);
1401 float builtin_frem(float a, float b)
1407 float builtin_fneg(float a)
1409 if (isnanf(a)) return a;
1411 if (finitef(a)) return -a;
1412 else return copysignf(a, -copysignf(1.0, a));
1417 s4 builtin_fcmpl(float a, float b)
1419 if (isnanf(a)) return -1;
1420 if (isnanf(b)) return -1;
1421 if (!finitef(a) || !finitef(b)) {
1422 a = finitef(a) ? 0 : copysignf(1.0, a);
1423 b = finitef(b) ? 0 : copysignf(1.0, b);
1425 if (a > b) return 1;
1426 if (a == b) return 0;
1431 s4 builtin_fcmpg(float a, float b)
1433 if (isnanf(a)) return 1;
1434 if (isnanf(b)) return 1;
1435 if (!finitef(a) || !finitef(b)) {
1436 a = finitef(a) ? 0 : copysignf(1.0, a);
1437 b = finitef(b) ? 0 : copysignf(1.0, b);
1439 if (a > b) return 1;
1440 if (a == b) return 0;
1446 /************************* Functions for doubles ****************************/
1448 double builtin_dadd(double a, double b)
1450 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1451 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1453 if (finite(b)) return a + b;
1457 if (finite(b)) return a;
1459 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1460 else return longBitsToDouble(DBL_NAN);
1466 double builtin_dsub(double a, double b)
1468 return builtin_dadd(a, builtin_dneg(b));
1472 double builtin_dmul(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;
1479 if (a == 0) return longBitsToDouble(DBL_NAN);
1480 else return copysign(b, copysign(1.0, b) * a);
1485 if (b == 0) return longBitsToDouble(DBL_NAN);
1486 else return copysign(a, copysign(1.0, a) * b);
1489 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1495 double builtin_ddiv(double a, double b)
1503 return longBitsToDouble(DBL_NAN);
1505 return copysign(0.0, b);
1511 return longBitsToDouble(DBL_POSINF);
1513 return longBitsToDouble(DBL_NEGINF);
1516 return longBitsToDouble(DBL_NAN);
1519 /* if (finite(a) && finite(b)) { */
1524 /* return longBitsToDouble(DBL_POSINF); */
1525 /* else if (a < 0) */
1526 /* return longBitsToDouble(DBL_NEGINF); */
1530 /* keep compiler happy */
1535 double builtin_drem(double a, double b)
1541 double builtin_dneg(double a)
1543 if (isnan(a)) return a;
1545 if (finite(a)) return -a;
1546 else return copysign(a, -copysign(1.0, a));
1551 s4 builtin_dcmpl(double a, double b)
1553 if (isnan(a)) return -1;
1554 if (isnan(b)) return -1;
1555 if (!finite(a) || !finite(b)) {
1556 a = finite(a) ? 0 : copysign(1.0, a);
1557 b = finite(b) ? 0 : copysign(1.0, b);
1559 if (a > b) return 1;
1560 if (a == b) return 0;
1565 s4 builtin_dcmpg(double a, double b)
1567 if (isnan(a)) return 1;
1568 if (isnan(b)) return 1;
1569 if (!finite(a) || !finite(b)) {
1570 a = finite(a) ? 0 : copysign(1.0, a);
1571 b = finite(b) ? 0 : copysign(1.0, b);
1573 if (a > b) return 1;
1574 if (a == b) return 0;
1579 /*********************** Conversion operations ****************************/
1581 s8 builtin_i2l(s4 i)
1594 float builtin_i2f(s4 a)
1596 float f = (float) a;
1601 double builtin_i2d(s4 a)
1603 double d = (double) a;
1608 s4 builtin_l2i(s8 l)
1618 float builtin_l2f(s8 a)
1621 float f = (float) a;
1629 double builtin_l2d(s8 a)
1632 double d = (double) a;
1640 s4 builtin_f2i(float a)
1643 return builtin_d2i((double) a);
1652 if (a < (-2147483648))
1653 return (-2147483648);
1656 f = copysignf((float) 1.0, a);
1659 return (-2147483648); */
1663 s8 builtin_f2l(float a)
1666 return builtin_d2l((double) a);
1671 if (a > 9223372036854775807L)
1672 return 9223372036854775807L;
1673 if (a < (-9223372036854775808L))
1674 return (-9223372036854775808L);
1679 f = copysignf((float) 1.0, a);
1681 return 9223372036854775807L;
1682 return (-9223372036854775808L); */
1686 double builtin_f2d(float a)
1688 if (finitef(a)) return (double) a;
1691 return longBitsToDouble(DBL_NAN);
1693 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1698 s4 builtin_d2i(double a)
1703 if (a >= 2147483647)
1705 if (a <= (-2147483647-1))
1706 return (-2147483647-1);
1711 d = copysign(1.0, a);
1714 return (-2147483647-1);
1718 s8 builtin_d2l(double a)
1723 if (a >= 9223372036854775807LL)
1724 return 9223372036854775807LL;
1725 if (a <= (-9223372036854775807LL-1))
1726 return (-9223372036854775807LL-1);
1731 d = copysign(1.0, a);
1733 return 9223372036854775807LL;
1734 return (-9223372036854775807LL-1);
1738 float builtin_d2f(double a)
1744 return intBitsToFloat(FLT_NAN);
1746 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1751 /* used to convert FLT_xxx defines into float values */
1753 inline float intBitsToFloat(s4 i)
1762 /* used to convert DBL_xxx defines into double values */
1764 inline float longBitsToDouble(s8 l)
1773 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1775 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1780 panic("Internal error: builtin_dummy called (native function is missing)");
1781 return 0; /* for the compiler */
1786 * These are local overrides for various environment variables in Emacs.
1787 * Please do not remove this and leave it at the end of the file, where
1788 * Emacs will automagically detect them.
1789 * ---------------------------------------------------------------------
1792 * indent-tabs-mode: t