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 908 2004-02-02 00:51:04Z 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*/
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 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
224 if (desc->dimension < target->dimension) return 0;
226 /* {desc has higher dimension than target} */
227 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
231 /******************** function: builtin_checkarraycast ***********************
233 Checks if an object is really a subtype of the requested array type.
234 The object has to be an array to begin with. For simple arrays (int, short,
235 double, etc.) the types have to match exactly.
236 For arrays of objects, the type of elements in the array has to be a
237 subtype (or the same type) of the requested element type. For arrays of
238 arrays (which in turn can again be arrays of arrays), the types at the
239 lowest level have to satisfy the corresponding sub class relation.
241 Return value: 1 ... cast is possible
244 ATTENTION: a cast with a NULL pointer is always possible.
246 *****************************************************************************/
248 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
250 arraydescriptor *desc;
253 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
255 return builtin_descriptorscompatible(desc, target->arraydesc);
259 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
262 return builtin_checkarraycast(obj, target);
266 /************************** exception functions *******************************
268 ******************************************************************************/
270 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
273 char logtext[MAXLOGTEXT];
274 sprintf(logtext, "Builtin exception thrown: ");
275 if (local_exceptionptr)
276 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
278 sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
279 if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
280 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
281 if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
282 if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
283 if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
284 if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
285 if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
286 if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
287 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
288 if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
292 *exceptionptr = local_exceptionptr;
293 return local_exceptionptr;
296 void builtin_reset_exceptionptr()
298 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
300 _exceptionptr = NULL;
302 ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
305 panic("builtin_reset_exceptionptr should not be used in this configuration");
310 /******************* function: builtin_canstore *******************************
312 Checks, if an object can be stored in an array.
313 Return value: 1 ... possible
316 ******************************************************************************/
318 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
320 arraydescriptor *desc;
321 arraydescriptor *valuedesc;
322 vftbl *componentvftbl;
329 /* The following is guaranteed (by verifier checks):
331 * *) a->...vftbl->arraydesc != NULL
332 * *) a->...vftbl->arraydesc->componentvftbl != NULL
333 * *) o->vftbl is not an interface vftbl
336 desc = a->header.objheader.vftbl->arraydesc;
337 componentvftbl = desc->componentvftbl;
338 valuevftbl = o->vftbl;
340 if ((dim_m1 = desc->dimension - 1) == 0) {
343 /* {a is a one-dimensional array} */
344 /* {a is an array of references} */
346 if (valuevftbl == componentvftbl)
349 if ((base = componentvftbl->baseval) <= 0)
350 /* an array of interface references */
351 return (valuevftbl->interfacetablelength > -base &&
352 valuevftbl->interfacetable[base] != NULL);
354 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
358 res = (unsigned)(valuevftbl->baseval - base)
359 <= (unsigned)(componentvftbl->diffval);
361 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
367 /* {a has dimension > 1} */
368 /* {componentvftbl->arraydesc != NULL} */
370 /* check if o is an array */
371 if ((valuedesc = valuevftbl->arraydesc) == NULL)
373 /* {o is an array} */
375 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
379 /* This is an optimized version where a is guaranteed to be one-dimensional */
380 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
382 arraydescriptor *desc;
390 /* The following is guaranteed (by verifier checks):
392 * *) a->...vftbl->arraydesc != NULL
393 * *) a->...vftbl->arraydesc->elementvftbl != NULL
394 * *) a->...vftbl->arraydesc->dimension == 1
395 * *) o->vftbl is not an interface vftbl
398 desc = a->header.objheader.vftbl->arraydesc;
399 elementvftbl = desc->elementvftbl;
400 valuevftbl = o->vftbl;
402 /* {a is a one-dimensional array} */
404 if (valuevftbl == elementvftbl)
407 if ((base = elementvftbl->baseval) <= 0)
408 /* an array of interface references */
409 return (valuevftbl->interfacetablelength > -base &&
410 valuevftbl->interfacetable[base] != NULL);
412 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
416 res = (unsigned)(valuevftbl->baseval - base)
417 <= (unsigned)(elementvftbl->diffval);
419 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
427 /* This is an optimized version where a is guaranteed to be a
428 * one-dimensional array of a class type */
429 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
437 /* The following is guaranteed (by verifier checks):
439 * *) a->...vftbl->arraydesc != NULL
440 * *) a->...vftbl->arraydesc->elementvftbl != NULL
441 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
442 * *) a->...vftbl->arraydesc->dimension == 1
443 * *) o->vftbl is not an interface vftbl
446 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
447 valuevftbl = o->vftbl;
449 /* {a is a one-dimensional array} */
451 if (valuevftbl == elementvftbl)
454 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
458 res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
459 <= (unsigned)(elementvftbl->diffval);
461 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
469 /******************** Function: builtin_new **********************************
471 Creates a new instance of class c on the heap.
472 Return value: pointer to the object or NULL if no memory is
475 *****************************************************************************/
478 #define align_size(size) ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
480 java_objectheader *builtin_new(classinfo *c)
482 java_objectheader *o;
484 if (!c->initialized) {
486 char logtext[MAXLOGTEXT];
487 sprintf(logtext, "Initialize class ");
488 utf_sprint(logtext + strlen(logtext), c->name);
489 sprintf(logtext + strlen(logtext), " (from builtin_new)");
495 #ifdef SIZE_FROM_CLASSINFO
496 c->alignedsize = align_size(c->instancesize);
497 o = heap_allocate(c->alignedsize, true, c->finalizer);
499 o = heap_allocate(c->instancesize, true, c->finalizer);
503 memset(o, 0, c->instancesize);
510 /********************** Function: builtin_newarray **************************
512 Creates an array with the given vftbl on the heap.
514 Return value: pointer to the array or NULL if no memory is available
516 CAUTION: The given vftbl must be the vftbl of the *array* class,
517 not of the element class.
519 *****************************************************************************/
521 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
524 arraydescriptor *desc = arrayvftbl->arraydesc;
525 s4 dataoffset = desc->dataoffset;
526 s4 componentsize = desc->componentsize;
530 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
533 #ifdef SIZE_FROM_CLASSINFO
534 actualsize = align_size(dataoffset + size * componentsize);
536 actualsize = dataoffset + size * componentsize;
539 if (((u4)actualsize)<((u4)size)) { /* overflow */
540 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
543 a = heap_allocate(actualsize,
544 (desc->arraytype == ARRAYTYPE_OBJECT),
548 memset(a, 0, actualsize);
551 /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
553 a->objheader.vftbl = arrayvftbl;
555 #ifdef SIZE_FROM_CLASSINFO
556 a->alignedsize = actualsize;
563 /********************** Function: builtin_anewarray *************************
565 Creates an array of references to the given class type on the heap.
567 Return value: pointer to the array or NULL if no memory is available
569 XXX This function does not do The Right Thing, because it uses a
570 classinfo pointer at runtime. builtin_newarray should be used
573 *****************************************************************************/
575 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
577 return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
581 /******************** Function: builtin_newarray_int ***********************
583 Creates an array of 32 bit Integers on the heap.
585 Return value: pointer to the array or NULL if no memory is available
587 *****************************************************************************/
589 java_intarray *builtin_newarray_int(s4 size)
591 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
595 /******************** Function: builtin_newarray_long ***********************
597 Creates an array of 64 bit Integers on the heap.
599 Return value: pointer to the array or NULL if no memory is available
601 *****************************************************************************/
603 java_longarray *builtin_newarray_long(s4 size)
605 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
609 /******************** function: builtin_newarray_float ***********************
611 Creates an array of 32 bit IEEE floats on the heap.
613 Return value: pointer to the array or NULL if no memory is available
615 *****************************************************************************/
617 java_floatarray *builtin_newarray_float(s4 size)
619 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
623 /******************** function: builtin_newarray_double ***********************
625 Creates an array of 64 bit IEEE floats on the heap.
627 Return value: pointer to the array or NULL if no memory is available
629 *****************************************************************************/
631 java_doublearray *builtin_newarray_double(s4 size)
633 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
637 /******************** function: builtin_newarray_byte ***********************
639 Creates an array of 8 bit Integers on the heap.
641 Return value: pointer to the array or NULL if no memory is available
643 *****************************************************************************/
645 java_bytearray *builtin_newarray_byte(s4 size)
647 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
651 /******************** function: builtin_newarray_char ************************
653 Creates an array of characters on the heap.
655 Return value: pointer to the array or NULL if no memory is available
657 *****************************************************************************/
659 java_chararray *builtin_newarray_char(s4 size)
661 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
665 /******************** function: builtin_newarray_short ***********************
667 Creates an array of 16 bit Integers on the heap.
669 Return value: pointer to the array or NULL if no memory is available
671 *****************************************************************************/
673 java_shortarray *builtin_newarray_short(s4 size)
675 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
679 /******************** function: builtin_newarray_boolean ************************
681 Creates an array of bytes on the heap. The array is designated as an array
682 of booleans (important for casts)
684 Return value: pointer to the array or NULL if no memory is available
686 *****************************************************************************/
688 java_booleanarray *builtin_newarray_boolean(s4 size)
690 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
694 /**************** function: builtin_nmultianewarray ***************************
696 Creates a multi-dimensional array on the heap. The dimensions are passed in
700 n............number of dimensions to create
701 arrayvftbl...vftbl of the array class
702 dims.........array containing the size of each dimension to create
704 Return value: pointer to the array or NULL if no memory is available
706 ******************************************************************************/
708 /* Helper functions */
710 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
714 vftbl *componentvftbl;
716 /* create this dimension */
717 size = (int) dims[0];
718 a = builtin_newarray(size,arrayvftbl);
721 /* if this is the last dimension return */
724 /* get the vftbl of the components to create */
725 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
727 /* The verifier guarantees this. */
728 /* if (!componentvftbl) */
729 /* panic ("multianewarray with too many dimensions"); */
731 /* create the component arrays */
732 for (i = 0; i < size; i++) {
733 java_arrayheader *ea =
734 builtin_nmultianewarray(n,componentvftbl,dims+1);
735 if (!ea) return NULL;
736 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
743 /*****************************************************************************
746 Various functions for printing a message at method entry or exit (for
749 *****************************************************************************/
754 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
755 methodinfo *method, int *pos,
762 log_text("WARNING: unmatched methodindent--");
764 if (verbose || runverbose) {
765 printf("Exception ");
767 utf_display(_exceptionptr->vftbl->class->name);
770 printf("Error: <Nullpointer instead of exception>");
771 if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
772 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
773 if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
774 if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
775 if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
776 if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
777 if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
778 if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
779 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
780 if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
783 printf(" thrown in ");
786 utf_display(method->class->name);
788 utf_display(method->name);
789 if (method->flags & ACC_SYNCHRONIZED)
793 printf("(%p) at position %p\n", method->entrypoint, pos);
796 printf("call_java_method\n");
800 return _exceptionptr;
804 #ifdef TRACE_ARGS_NUM
805 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
806 #if TRACE_ARGS_NUM > 6
812 char logtext[MAXLOGTEXT];
813 for (i = 0; i < methodindent; i++)
815 sprintf(logtext + methodindent, "called: ");
816 utf_sprint(logtext + strlen(logtext), method->class->name);
817 sprintf(logtext + strlen(logtext), ".");
818 utf_sprint(logtext + strlen(logtext), method->name);
819 utf_sprint(logtext + strlen(logtext), method->descriptor);
821 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
822 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
823 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
824 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
825 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
826 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
827 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
828 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
829 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
830 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
831 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
834 sprintf(logtext + strlen(logtext), "(");
836 switch (method->paramcount) {
840 #if defined(__I386__)
842 sprintf(logtext+strlen(logtext), "%llx", a0);
846 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
850 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
854 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
859 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
864 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
865 a0, a1, a2, a3, a4, a5);
868 #if TRACE_ARGS_NUM > 6
870 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
871 a0, a1, a2, a3, a4, a5, a6);
875 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
876 a0, a1, a2, a3, a4, a5, a6, a7);
880 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
881 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
885 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
886 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
891 sprintf(logtext+strlen(logtext), "%lx", a0);
895 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
899 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
903 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
908 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
913 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
914 a0, a1, a2, a3, a4, a5);
917 #if TRACE_ARGS_NUM > 6
919 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
920 a0, a1, a2, a3, a4, a5, a6);
924 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
925 a0, a1, a2, a3, a4, a5, a6, a7);
929 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
930 a0, a1, a2, a3, a4, a5, a6, a7, method->paramcount - 8);
934 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
935 a0, a1, a2, a3, a4, a5, method->paramcount - 6);
940 sprintf (logtext+strlen(logtext), ")");
948 void builtin_displaymethodstart(methodinfo *method)
950 char logtext[MAXLOGTEXT];
951 sprintf(logtext, " ");
952 sprintf(logtext + methodindent, "called: ");
953 utf_sprint(logtext + strlen(logtext), method->class->name);
954 sprintf(logtext + strlen(logtext), ".");
955 utf_sprint(logtext + strlen(logtext), method->name);
956 utf_sprint(logtext + strlen(logtext), method->descriptor);
958 if ( method->flags & ACC_PUBLIC ) sprintf (logtext + strlen(logtext)," PUBLIC");
959 if ( method->flags & ACC_PRIVATE ) sprintf (logtext + strlen(logtext)," PRIVATE");
960 if ( method->flags & ACC_PROTECTED ) sprintf (logtext + strlen(logtext)," PROTECTED");
961 if ( method->flags & ACC_STATIC ) sprintf (logtext + strlen(logtext)," STATIC");
962 if ( method->flags & ACC_FINAL ) sprintf (logtext + strlen(logtext)," FINAL");
963 if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
964 if ( method->flags & ACC_VOLATILE ) sprintf (logtext + strlen(logtext)," VOLATILE");
965 if ( method->flags & ACC_TRANSIENT ) sprintf (logtext + strlen(logtext)," TRANSIENT");
966 if ( method->flags & ACC_NATIVE ) sprintf (logtext + strlen(logtext)," NATIVE");
967 if ( method->flags & ACC_INTERFACE ) sprintf (logtext + strlen(logtext)," INTERFACE");
968 if ( method->flags & ACC_ABSTRACT ) sprintf (logtext + strlen(logtext)," ABSTRACT");
975 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
978 char logtext[MAXLOGTEXT];
979 for (i = 0; i < methodindent; i++)
984 log_text("WARNING: unmatched methodindent--");
985 sprintf(logtext + methodindent, "finished: ");
986 utf_sprint(logtext + strlen(logtext), method->class->name);
987 sprintf(logtext + strlen(logtext), ".");
988 utf_sprint(logtext + strlen(logtext), method->name);
989 utf_sprint(logtext + strlen(logtext), method->descriptor);
991 switch (method->returntype) {
993 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
996 #if defined(__I386__)
997 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
999 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1003 #if defined(__I386__)
1004 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1006 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1010 sprintf(logtext + strlen(logtext), "->%g", f);
1013 sprintf(logtext + strlen(logtext), "->%g", d);
1020 void builtin_displaymethodexception(methodinfo *method)
1023 char logtext[MAXLOGTEXT];
1024 for (i = 0; i < methodindent; i++)
1026 sprintf(logtext + methodindent, "exception abort: ");
1027 utf_sprint(logtext + strlen(logtext), method->class->name);
1028 sprintf(logtext + strlen(logtext), ".");
1029 utf_sprint(logtext + strlen(logtext), method->name);
1030 utf_sprint(logtext + strlen(logtext), method->descriptor);
1035 /****************************************************************************
1036 SYNCHRONIZATION FUNCTIONS
1037 *****************************************************************************/
1040 * Lock the mutex of an object.
1042 void internal_lock_mutex_for_object(java_objectheader *object)
1044 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1045 mutexHashEntry *entry;
1048 assert(object != 0);
1050 hashValue = MUTEX_HASH_VALUE(object);
1051 entry = &mutexHashTable[hashValue];
1053 if (entry->object != 0) {
1054 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1056 entry->mutex.holder = 0;
1057 entry->mutex.count = 0;
1058 entry->mutex.muxWaiters = 0;
1061 while (entry->next != 0 && entry->object != object)
1062 entry = entry->next;
1064 if (entry->object != object) {
1065 entry->next = firstFreeOverflowEntry;
1066 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1068 entry = entry->next;
1071 assert(entry->conditionCount == 0);
1076 entry->mutex.holder = 0;
1077 entry->mutex.count = 0;
1078 entry->mutex.muxWaiters = 0;
1081 if (entry->object == 0)
1082 entry->object = object;
1084 internal_lock_mutex(&entry->mutex);
1090 * Unlocks the mutex of an object.
1092 void internal_unlock_mutex_for_object (java_objectheader *object)
1094 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1096 mutexHashEntry *entry;
1098 hashValue = MUTEX_HASH_VALUE(object);
1099 entry = &mutexHashTable[hashValue];
1101 if (entry->object == object) {
1102 internal_unlock_mutex(&entry->mutex);
1105 while (entry->next != 0 && entry->next->object != object)
1106 entry = entry->next;
1108 assert(entry->next != 0);
1110 internal_unlock_mutex(&entry->next->mutex);
1112 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1113 mutexHashEntry *unlinked = entry->next;
1115 entry->next = unlinked->next;
1116 unlinked->next = firstFreeOverflowEntry;
1117 firstFreeOverflowEntry = unlinked;
1124 void builtin_monitorenter(java_objectheader *o)
1126 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1129 assert(blockInts == 0);
1133 hashValue = MUTEX_HASH_VALUE(o);
1134 if (mutexHashTable[hashValue].object == o
1135 && mutexHashTable[hashValue].mutex.holder == currentThread)
1136 ++mutexHashTable[hashValue].mutex.count;
1138 internal_lock_mutex_for_object(o);
1142 assert(blockInts == 0);
1147 void builtin_monitorexit (java_objectheader *o)
1149 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1152 assert(blockInts == 0);
1156 hashValue = MUTEX_HASH_VALUE(o);
1157 if (mutexHashTable[hashValue].object == o) {
1158 if (mutexHashTable[hashValue].mutex.count == 1
1159 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1160 internal_unlock_mutex_for_object(o);
1162 --mutexHashTable[hashValue].mutex.count;
1165 internal_unlock_mutex_for_object(o);
1169 assert(blockInts == 0);
1174 /*****************************************************************************
1175 MISCELLANEOUS HELPER FUNCTIONS
1176 *****************************************************************************/
1180 /*********** Functions for integer divisions *****************************
1182 On some systems (eg. DEC ALPHA), integer division is not supported by the
1183 CPU. These helper functions implement the missing functionality.
1185 ******************************************************************************/
1187 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1188 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1191 /************** Functions for long arithmetics *******************************
1193 On systems where 64 bit Integers are not supported by the CPU, these
1194 functions are needed.
1196 ******************************************************************************/
1199 s8 builtin_ladd(s8 a, s8 b)
1204 return builtin_i2l(0);
1208 s8 builtin_lsub(s8 a, s8 b)
1213 return builtin_i2l(0);
1217 s8 builtin_lmul(s8 a, s8 b)
1222 return builtin_i2l(0);
1226 s8 builtin_ldiv(s8 a, s8 b)
1231 return builtin_i2l(0);
1235 s8 builtin_lrem(s8 a, s8 b)
1240 return builtin_i2l(0);
1244 s8 builtin_lshl(s8 a, s4 b)
1247 return a << (b & 63);
1249 return builtin_i2l(0);
1253 s8 builtin_lshr(s8 a, s4 b)
1256 return a >> (b & 63);
1258 return builtin_i2l(0);
1262 s8 builtin_lushr(s8 a, s4 b)
1265 return ((u8) a) >> (b & 63);
1267 return builtin_i2l(0);
1271 s8 builtin_land(s8 a, s8 b)
1276 return builtin_i2l(0);
1280 s8 builtin_lor(s8 a, s8 b)
1285 return builtin_i2l(0);
1289 s8 builtin_lxor(s8 a, s8 b)
1294 return builtin_i2l(0);
1298 s8 builtin_lneg(s8 a)
1303 return builtin_i2l(0);
1307 s4 builtin_lcmp(s8 a, s8 b)
1310 if (a < b) return -1;
1311 if (a > b) return 1;
1322 /*********** Functions for floating point operations *************************/
1324 float builtin_fadd(float a, float b)
1326 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1327 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1338 if (copysignf(1.0, a) == copysignf(1.0, b))
1341 return intBitsToFloat(FLT_NAN);
1347 float builtin_fsub(float a, float b)
1349 return builtin_fadd(a, builtin_fneg(b));
1353 float builtin_fmul(float a, float b)
1355 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1356 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1358 if (finitef(b)) return a * b;
1360 if (a == 0) return intBitsToFloat(FLT_NAN);
1361 else return copysignf(b, copysignf(1.0, b)*a);
1366 if (b == 0) return intBitsToFloat(FLT_NAN);
1367 else return copysignf(a, copysignf(1.0, a)*b);
1370 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1376 float builtin_fdiv(float a, float b)
1378 if (finitef(a) && finitef(b)) {
1383 return intBitsToFloat(FLT_POSINF);
1385 return intBitsToFloat(FLT_NEGINF);
1388 return intBitsToFloat(FLT_NAN);
1392 float builtin_frem(float a, float b)
1398 float builtin_fneg(float a)
1400 if (isnanf(a)) return a;
1402 if (finitef(a)) return -a;
1403 else return copysignf(a, -copysignf(1.0, a));
1408 s4 builtin_fcmpl(float a, float b)
1410 if (isnanf(a)) return -1;
1411 if (isnanf(b)) return -1;
1412 if (!finitef(a) || !finitef(b)) {
1413 a = finitef(a) ? 0 : copysignf(1.0, a);
1414 b = finitef(b) ? 0 : copysignf(1.0, b);
1416 if (a > b) return 1;
1417 if (a == b) return 0;
1422 s4 builtin_fcmpg(float a, float b)
1424 if (isnanf(a)) return 1;
1425 if (isnanf(b)) return 1;
1426 if (!finitef(a) || !finitef(b)) {
1427 a = finitef(a) ? 0 : copysignf(1.0, a);
1428 b = finitef(b) ? 0 : copysignf(1.0, b);
1430 if (a > b) return 1;
1431 if (a == b) return 0;
1437 /************************* Functions for doubles ****************************/
1439 double builtin_dadd(double a, double b)
1441 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1442 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1444 if (finite(b)) return a + b;
1448 if (finite(b)) return a;
1450 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1451 else return longBitsToDouble(DBL_NAN);
1457 double builtin_dsub(double a, double b)
1459 return builtin_dadd(a, builtin_dneg(b));
1463 double builtin_dmul(double a, double b)
1465 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1466 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1468 if (finite(b)) return a * b;
1470 if (a == 0) return longBitsToDouble(DBL_NAN);
1471 else return copysign(b, copysign(1.0, b) * a);
1476 if (b == 0) return longBitsToDouble(DBL_NAN);
1477 else return copysign(a, copysign(1.0, a) * b);
1480 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1486 double builtin_ddiv(double a, double b)
1494 return longBitsToDouble(DBL_NAN);
1496 return copysign(0.0, b);
1502 return longBitsToDouble(DBL_POSINF);
1504 return longBitsToDouble(DBL_NEGINF);
1507 return longBitsToDouble(DBL_NAN);
1510 /* if (finite(a) && finite(b)) { */
1515 /* return longBitsToDouble(DBL_POSINF); */
1516 /* else if (a < 0) */
1517 /* return longBitsToDouble(DBL_NEGINF); */
1521 /* keep compiler happy */
1526 double builtin_drem(double a, double b)
1532 double builtin_dneg(double a)
1534 if (isnan(a)) return a;
1536 if (finite(a)) return -a;
1537 else return copysign(a, -copysign(1.0, a));
1542 s4 builtin_dcmpl(double a, double b)
1544 if (isnan(a)) return -1;
1545 if (isnan(b)) return -1;
1546 if (!finite(a) || !finite(b)) {
1547 a = finite(a) ? 0 : copysign(1.0, a);
1548 b = finite(b) ? 0 : copysign(1.0, b);
1550 if (a > b) return 1;
1551 if (a == b) return 0;
1556 s4 builtin_dcmpg(double a, double b)
1558 if (isnan(a)) return 1;
1559 if (isnan(b)) return 1;
1560 if (!finite(a) || !finite(b)) {
1561 a = finite(a) ? 0 : copysign(1.0, a);
1562 b = finite(b) ? 0 : copysign(1.0, b);
1564 if (a > b) return 1;
1565 if (a == b) return 0;
1570 /*********************** Conversion operations ****************************/
1572 s8 builtin_i2l(s4 i)
1585 float builtin_i2f(s4 a)
1587 float f = (float) a;
1592 double builtin_i2d(s4 a)
1594 double d = (double) a;
1599 s4 builtin_l2i(s8 l)
1609 float builtin_l2f(s8 a)
1612 float f = (float) a;
1620 double builtin_l2d(s8 a)
1623 double d = (double) a;
1631 s4 builtin_f2i(float a)
1634 return builtin_d2i((double) a);
1643 if (a < (-2147483648))
1644 return (-2147483648);
1647 f = copysignf((float) 1.0, a);
1650 return (-2147483648); */
1654 s8 builtin_f2l(float a)
1657 return builtin_d2l((double) a);
1662 if (a > 9223372036854775807L)
1663 return 9223372036854775807L;
1664 if (a < (-9223372036854775808L))
1665 return (-9223372036854775808L);
1670 f = copysignf((float) 1.0, a);
1672 return 9223372036854775807L;
1673 return (-9223372036854775808L); */
1677 double builtin_f2d(float a)
1679 if (finitef(a)) return (double) a;
1682 return longBitsToDouble(DBL_NAN);
1684 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1689 s4 builtin_d2i(double a)
1694 if (a >= 2147483647)
1696 if (a <= (-2147483647-1))
1697 return (-2147483647-1);
1702 d = copysign(1.0, a);
1705 return (-2147483647-1);
1709 s8 builtin_d2l(double a)
1714 if (a >= 9223372036854775807LL)
1715 return 9223372036854775807LL;
1716 if (a <= (-9223372036854775807LL-1))
1717 return (-9223372036854775807LL-1);
1722 d = copysign(1.0, a);
1724 return 9223372036854775807LL;
1725 return (-9223372036854775807LL-1);
1729 float builtin_d2f(double a)
1735 return intBitsToFloat(FLT_NAN);
1737 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1742 /* used to convert FLT_xxx defines into float values */
1744 inline float intBitsToFloat(s4 i)
1753 /* used to convert DBL_xxx defines into double values */
1755 inline float longBitsToDouble(s8 l)
1764 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1766 return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1771 panic("Internal error: builtin_dummy called (native function is missing)");
1772 return 0; /* for the compiler */
1777 * These are local overrides for various environment variables in Emacs.
1778 * Please do not remove this and leave it at the end of the file, where
1779 * Emacs will automagically detect them.
1780 * ---------------------------------------------------------------------
1783 * indent-tabs-mode: t