1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
34 Contains C functions for JavaVM Instructions that cannot be
35 translated to machine language directly. Consequently, the
36 generated machine code for these instructions contains function
37 calls instead of machine instructions, using the C calling
40 $Id: builtin.c 4908 2006-05-12 16:49:50Z edwin $
57 #include "fdlibm/fdlibm.h"
60 #include "mm/memory.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Cloneable.h"
63 #include "native/include/java_lang_Object.h" /* required by VMObject */
64 #include "native/include/java_lang_VMObject.h"
66 #if defined(USE_THREADS)
67 # if defined(NATIVE_THREADS)
68 # include "threads/native/threads.h"
70 # include "threads/green/threads.h"
71 # include "threads/green/locks.h"
75 #include "toolbox/logging.h"
76 #include "toolbox/util.h"
77 #include "vm/builtin.h"
79 #include "vm/exceptions.h"
80 #include "vm/global.h"
81 #include "vm/initialize.h"
82 #include "vm/loader.h"
83 #include "vm/options.h"
84 #include "vm/stringlocal.h"
85 #include "vm/jit/asmpart.h"
86 #include "vm/jit/patcher.h"
87 #include "vm/rt-timing.h"
88 #include "vm/cycles-stats.h"
91 /* include builtin tables *****************************************************/
93 #include "vm/builtintable.inc"
96 CYCLES_STATS_DECLARE(builtin_monitorenter,100,2)
97 CYCLES_STATS_DECLARE(builtin_monitorexit ,100,2)
98 CYCLES_STATS_DECLARE(builtin_new ,100,5)
99 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
101 /* builtintable_init ***********************************************************
103 Parse the descriptors of builtin functions and create the parsed
106 *******************************************************************************/
108 static bool builtintable_init(void)
110 descriptor_pool *descpool;
114 s4 entries_automatic;
117 /* mark start of dump memory area */
119 dumpsize = dump_size();
121 /* create a new descriptor pool */
123 descpool = descriptor_pool_new(class_java_lang_Object);
125 /* add some entries we need */
127 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
130 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
133 /* calculate table entries statically */
136 sizeof(builtintable_internal) / sizeof(builtintable_entry);
139 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
140 - 1; /* last filler entry (comment see builtintable.inc) */
142 /* first add all descriptors to the pool */
144 for (i = 0; i < entries_internal; i++) {
145 /* create a utf8 string from descriptor */
147 descriptor = utf_new_char(builtintable_internal[i].descriptor);
149 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
150 /* release dump area */
152 dump_release(dumpsize);
158 for (i = 0; i < entries_automatic; i++) {
159 /* create a utf8 string from descriptor */
161 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
163 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
164 /* release dump area */
166 dump_release(dumpsize);
172 /* create the class reference table */
174 (void) descriptor_pool_create_classrefs(descpool, NULL);
176 /* allocate space for the parsed descriptors */
178 descriptor_pool_alloc_parsed_descriptors(descpool);
180 /* now parse all descriptors */
182 for (i = 0; i < entries_internal; i++) {
183 /* create a utf8 string from descriptor */
185 descriptor = utf_new_char(builtintable_internal[i].descriptor);
187 /* parse the descriptor, builtin is always static (no `this' pointer) */
189 builtintable_internal[i].md =
190 descriptor_pool_parse_method_descriptor(descpool, descriptor,
194 for (i = 0; i < entries_automatic; i++) {
195 /* create a utf8 string from descriptor */
197 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
199 /* parse the descriptor, builtin is always static (no `this' pointer) */
201 builtintable_automatic[i].md =
202 descriptor_pool_parse_method_descriptor(descpool, descriptor,
206 /* release dump area */
208 dump_release(dumpsize);
214 /* builtintable_comparator *****************************************************
216 qsort comparator for the automatic builtin table.
218 *******************************************************************************/
220 static int builtintable_comparator(const void *a, const void *b)
222 builtintable_entry *bte1;
223 builtintable_entry *bte2;
225 bte1 = (builtintable_entry *) a;
226 bte2 = (builtintable_entry *) b;
228 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
232 /* builtintable_sort_automatic *************************************************
234 Sorts the automatic builtin table.
236 *******************************************************************************/
238 static void builtintable_sort_automatic(void)
242 /* calculate table size statically (`- 1' comment see builtintable.inc) */
244 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
246 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
247 builtintable_comparator);
251 /* builtin_init ****************************************************************
255 *******************************************************************************/
257 bool builtin_init(void)
259 /* initialize the builtin tables */
261 if (!builtintable_init())
264 /* sort builtin tables */
266 builtintable_sort_automatic();
272 /* builtintable_get_internal ***************************************************
274 Finds an entry in the builtintable for internal functions and
275 returns the a pointer to the structure.
277 *******************************************************************************/
279 builtintable_entry *builtintable_get_internal(functionptr fp)
283 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
284 if (builtintable_internal[i].fp == fp)
285 return &builtintable_internal[i];
292 /* builtintable_get_automatic **************************************************
294 Finds an entry in the builtintable for functions which are replaced
295 automatically and returns the a pointer to the structure.
297 *******************************************************************************/
299 builtintable_entry *builtintable_get_automatic(s4 opcode)
301 builtintable_entry *first;
302 builtintable_entry *last;
303 builtintable_entry *middle;
307 /* calculate table size statically (`- 1' comment see builtintable.inc) */
309 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
311 first = builtintable_automatic;
312 last = builtintable_automatic + entries;
314 while (entries > 0) {
316 middle = first + half;
318 if (middle->opcode < opcode) {
325 return (first != last ? first : NULL);
329 /*****************************************************************************
331 *****************************************************************************/
335 /*************** internal function: builtin_isanysubclass *********************
337 Checks a subclass relation between two classes. Implemented interfaces
338 are interpreted as super classes.
339 Return value: 1 ... sub is subclass of super
342 *****************************************************************************/
343 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
346 castinfo classvalues;
351 if (super->flags & ACC_INTERFACE) {
352 res = (sub->vftbl->interfacetablelength > super->index) &&
353 (sub->vftbl->interfacetable[-super->index] != NULL);
356 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
358 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
359 (u4) classvalues.super_diffval;
366 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
370 castinfo classvalues;
375 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
377 if ((base = classvalues.super_baseval) <= 0) {
378 /* super is an interface */
379 res = (sub->interfacetablelength > -base) &&
380 (sub->interfacetable[base] != NULL);
382 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
383 <= (u4) classvalues.super_diffval;
390 /****************** function: builtin_instanceof *****************************
392 Checks if an object is an instance of some given class (or subclass of
393 that class). If class is an interface, checks if the interface is
395 Return value: 1 ... obj is an instance of class or implements the interface
396 0 ... otherwise or if obj == NULL
398 *****************************************************************************/
400 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
405 return builtin_isanysubclass(obj->vftbl->class, class);
410 /**************** function: builtin_checkcast *******************************
412 The same as builtin_instanceof except that 1 is returned when
415 ****************************************************************************/
417 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
422 if (builtin_isanysubclass(obj->vftbl->class, class))
429 /* builtin_descriptorscompatible ***********************************************
431 Checks if two array type descriptors are assignment compatible
433 Return value: 1 ... target = desc is possible
436 *******************************************************************************/
438 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
439 arraydescriptor *target)
444 if (desc->arraytype != target->arraytype)
447 if (desc->arraytype != ARRAYTYPE_OBJECT)
450 /* {both arrays are arrays of references} */
452 if (desc->dimension == target->dimension) {
453 /* an array which contains elements of interface types is
454 allowed to be casted to Object (JOWENN)*/
456 if ((desc->elementvftbl->baseval < 0) &&
457 (target->elementvftbl->baseval == 1))
460 return builtin_isanysubclass_vftbl(desc->elementvftbl,
461 target->elementvftbl);
464 if (desc->dimension < target->dimension)
467 /* {desc has higher dimension than target} */
469 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
470 target->elementvftbl);
474 /* builtin_arraycheckcast ******************************************************
476 Checks if an object is really a subtype of the requested array
477 type. The object has to be an array to begin with. For simple
478 arrays (int, short, double, etc.) the types have to match exactly.
479 For arrays of objects, the type of elements in the array has to be
480 a subtype (or the same type) of the requested element type. For
481 arrays of arrays (which in turn can again be arrays of arrays), the
482 types at the lowest level have to satisfy the corresponding sub
485 *******************************************************************************/
487 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
489 arraydescriptor *desc;
494 if ((desc = o->vftbl->arraydesc) == NULL)
497 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
501 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
506 return builtin_arraycheckcast(o, targetclass);
510 /* builtin_throw_exception *****************************************************
512 Sets the exceptionptr with the thrown exception and prints some
513 debugging information. Called from asm_vm_call_method.
515 *******************************************************************************/
517 void *builtin_throw_exception(java_objectheader *xptr)
520 java_lang_Throwable *t;
526 t = (java_lang_Throwable *) xptr;
528 /* calculate message length */
530 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
534 utf_bytes(xptr->vftbl->class->name);
535 if (t->detailMessage) {
536 logtextlen += strlen(": ") +
537 u2_utflength(t->detailMessage->value->data
538 + t->detailMessage->offset,
539 t->detailMessage->count);
543 logtextlen += strlen("(nil)");
546 /* allocate memory */
548 dumpsize = dump_size();
550 logtext = DMNEW(char, logtextlen);
552 strcpy(logtext, "Builtin exception thrown: ");
555 utf_cat_classname(logtext, xptr->vftbl->class->name);
557 if (t->detailMessage) {
560 buf = javastring_tochar((java_objectheader *) t->detailMessage);
561 strcat(logtext, ": ");
562 strcat(logtext, buf);
563 MFREE(buf, char, strlen(buf) + 1);
567 strcat(logtext, "(nil)");
574 dump_release(dumpsize);
576 #endif /* !defined(NDEBUG) */
578 /* actually set the exception */
580 *exceptionptr = xptr;
582 /* Return a NULL pointer. This is required for vm_call_method to
583 check for an exception. This is for convenience. */
589 /* builtin_canstore ************************************************************
591 Checks, if an object can be stored in an array.
593 Return value: 1 ... possible
596 *******************************************************************************/
598 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
600 arraydescriptor *desc;
601 arraydescriptor *valuedesc;
602 vftbl_t *componentvftbl;
605 castinfo classvalues;
610 /* The following is guaranteed (by verifier checks):
612 * *) oa->...vftbl->arraydesc != NULL
613 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
614 * *) o->vftbl is not an interface vftbl
617 desc = oa->header.objheader.vftbl->arraydesc;
618 componentvftbl = desc->componentvftbl;
619 valuevftbl = o->vftbl;
621 if ((desc->dimension - 1) == 0) {
624 /* {oa is a one-dimensional array} */
625 /* {oa is an array of references} */
627 if (valuevftbl == componentvftbl)
630 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
632 if ((base = classvalues.super_baseval) <= 0)
633 /* an array of interface references */
634 return (valuevftbl->interfacetablelength > -base &&
635 valuevftbl->interfacetable[base] != NULL);
637 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
638 <= (unsigned) classvalues.super_diffval);
643 /* {oa has dimension > 1} */
644 /* {componentvftbl->arraydesc != NULL} */
646 /* check if o is an array */
648 if ((valuedesc = valuevftbl->arraydesc) == NULL)
651 /* {o is an array} */
653 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
657 /* This is an optimized version where a is guaranteed to be one-dimensional */
658 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
660 arraydescriptor *desc;
661 vftbl_t *elementvftbl;
665 castinfo classvalues;
669 /* The following is guaranteed (by verifier checks):
671 * *) a->...vftbl->arraydesc != NULL
672 * *) a->...vftbl->arraydesc->elementvftbl != NULL
673 * *) a->...vftbl->arraydesc->dimension == 1
674 * *) o->vftbl is not an interface vftbl
677 desc = a->header.objheader.vftbl->arraydesc;
678 elementvftbl = desc->elementvftbl;
679 valuevftbl = o->vftbl;
681 /* {a is a one-dimensional array} */
683 if (valuevftbl == elementvftbl)
686 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
688 if ((base = classvalues.super_baseval) <= 0)
689 /* an array of interface references */
690 return (valuevftbl->interfacetablelength > -base &&
691 valuevftbl->interfacetable[base] != NULL);
693 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
694 <= (unsigned) classvalues.super_diffval;
700 /* This is an optimized version where a is guaranteed to be a
701 * one-dimensional array of a class type */
702 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
704 vftbl_t *elementvftbl;
707 castinfo classvalues;
711 /* The following is guaranteed (by verifier checks):
713 * *) a->...vftbl->arraydesc != NULL
714 * *) a->...vftbl->arraydesc->elementvftbl != NULL
715 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
716 * *) a->...vftbl->arraydesc->dimension == 1
717 * *) o->vftbl is not an interface vftbl
720 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
721 valuevftbl = o->vftbl;
723 /* {a is a one-dimensional array} */
725 if (valuevftbl == elementvftbl)
728 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
730 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
731 <= (unsigned) classvalues.super_diffval;
737 /* builtin_new *****************************************************************
739 Creates a new instance of class c on the heap.
741 Return value: pointer to the object or NULL if no memory is
744 *******************************************************************************/
746 java_objectheader *builtin_new(classinfo *c)
748 java_objectheader *o;
749 #if defined(ENABLE_RT_TIMING)
750 struct timespec time_start, time_end;
752 #if defined(ENABLE_CYCLES_STATS)
753 u8 cycles_start, cycles_end;
756 RT_TIMING_GET_TIME(time_start);
757 CYCLES_STATS_GET(cycles_start);
759 /* is the class loaded */
761 assert(c->state & CLASS_LOADED);
763 /* check if we can instantiate this class */
765 if (c->flags & ACC_ABSTRACT) {
767 new_exception_utfmessage(string_java_lang_InstantiationError,
772 /* is the class linked */
774 if (!(c->state & CLASS_LINKED))
778 if (!(c->state & CLASS_INITIALIZED)) {
781 log_message_class("Initialize class (from builtin_new): ", c);
784 if (!initialize_class(c))
788 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
796 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
797 lock_init_object_lock(o);
800 CYCLES_STATS_GET(cycles_end);
801 RT_TIMING_GET_TIME(time_end);
803 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
804 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
810 /* builtin_newarray ************************************************************
812 Creates an array with the given vftbl on the heap. This function
813 takes as class argument an array class.
815 Return value: pointer to the array or NULL if no memory is available
817 *******************************************************************************/
819 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
821 arraydescriptor *desc;
826 #if defined(ENABLE_RT_TIMING)
827 struct timespec time_start, time_end;
830 RT_TIMING_GET_TIME(time_start);
832 desc = arrayclass->vftbl->arraydesc;
833 dataoffset = desc->dataoffset;
834 componentsize = desc->componentsize;
837 exceptions_throw_negativearraysizeexception();
841 actualsize = dataoffset + size * componentsize;
843 if (((u4) actualsize) < ((u4) size)) { /* overflow */
844 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
848 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
853 a->objheader.vftbl = arrayclass->vftbl;
855 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
856 lock_init_object_lock(&a->objheader);
861 RT_TIMING_GET_TIME(time_end);
862 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
868 /* builtin_anewarray ***********************************************************
870 Creates an array of references to the given class type on the heap.
872 Return value: pointer to the array or NULL if no memory is
875 *******************************************************************************/
877 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
879 classinfo *arrayclass;
881 /* is class loaded */
883 assert(componentclass->state & CLASS_LOADED);
885 /* is class linked */
887 if (!(componentclass->state & CLASS_LINKED))
888 if (!link_class(componentclass))
891 arrayclass = class_array_of(componentclass, true);
896 return (java_objectarray *) builtin_newarray(size, arrayclass);
900 /* builtin_newarray_boolean ****************************************************
902 Creates an array of bytes on the heap. The array is designated as
903 an array of booleans (important for casts)
905 Return value: pointer to the array or NULL if no memory is
908 *******************************************************************************/
910 java_booleanarray *builtin_newarray_boolean(s4 size)
912 return (java_booleanarray *)
913 builtin_newarray(size,
914 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
918 /* builtin_newarray_byte *******************************************************
920 Creates an array of 8 bit Integers on the heap.
922 Return value: pointer to the array or NULL if no memory is
925 *******************************************************************************/
927 java_bytearray *builtin_newarray_byte(s4 size)
929 return (java_bytearray *)
930 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
934 /* builtin_newarray_char *******************************************************
936 Creates an array of characters on the heap.
938 Return value: pointer to the array or NULL if no memory is
941 *******************************************************************************/
943 java_chararray *builtin_newarray_char(s4 size)
945 return (java_chararray *)
946 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
950 /* builtin_newarray_short ******************************************************
952 Creates an array of 16 bit Integers on the heap.
954 Return value: pointer to the array or NULL if no memory is
957 *******************************************************************************/
959 java_shortarray *builtin_newarray_short(s4 size)
961 return (java_shortarray *)
962 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
966 /* builtin_newarray_int ********************************************************
968 Creates an array of 32 bit Integers on the heap.
970 Return value: pointer to the array or NULL if no memory is
973 *******************************************************************************/
975 java_intarray *builtin_newarray_int(s4 size)
977 return (java_intarray *)
978 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
982 /* builtin_newarray_long *******************************************************
984 Creates an array of 64 bit Integers on the heap.
986 Return value: pointer to the array or NULL if no memory is
989 *******************************************************************************/
991 java_longarray *builtin_newarray_long(s4 size)
993 return (java_longarray *)
994 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
998 /* builtin_newarray_float ******************************************************
1000 Creates an array of 32 bit IEEE floats on the heap.
1002 Return value: pointer to the array or NULL if no memory is
1005 *******************************************************************************/
1007 java_floatarray *builtin_newarray_float(s4 size)
1009 return (java_floatarray *)
1010 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1014 /* builtin_newarray_double *****************************************************
1016 Creates an array of 64 bit IEEE floats on the heap.
1018 Return value: pointer to the array or NULL if no memory is
1021 *******************************************************************************/
1023 java_doublearray *builtin_newarray_double(s4 size)
1025 return (java_doublearray *)
1026 builtin_newarray(size,
1027 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1031 /* builtin_multianewarray_intern ***********************************************
1033 Creates a multi-dimensional array on the heap. The dimensions are
1034 passed in an array of longs.
1037 n............number of dimensions to create
1038 arrayvftbl...vftbl of the array class
1039 dims.........array containing the size of each dimension to create
1041 Return value: pointer to the array or NULL if no memory is
1044 ******************************************************************************/
1046 static java_arrayheader *builtin_multianewarray_intern(int n,
1047 classinfo *arrayclass,
1051 java_arrayheader *a;
1052 classinfo *componentclass;
1055 /* create this dimension */
1057 size = (s4) dims[0];
1058 a = builtin_newarray(size, arrayclass);
1063 /* if this is the last dimension return */
1068 /* get the class of the components to create */
1070 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1072 /* The verifier guarantees that the dimension count is in the range. */
1074 /* create the component arrays */
1076 for (i = 0; i < size; i++) {
1077 java_arrayheader *ea =
1078 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1079 /* we save an s4 to a s8 slot, 8-byte aligned */
1081 builtin_multianewarray_intern(n, componentclass, dims + 2);
1083 builtin_multianewarray_intern(n, componentclass, dims + 1);
1089 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1096 /* builtin_multianewarray ******************************************************
1098 Wrapper for builtin_multianewarray_intern which checks all
1099 dimensions before we start allocating.
1101 ******************************************************************************/
1103 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1109 /* check all dimensions before doing anything */
1111 for (i = 0; i < n; i++) {
1112 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1113 /* we save an s4 to a s8 slot, 8-byte aligned */
1114 size = (s4) dims[i * 2];
1116 size = (s4) dims[i];
1120 exceptions_throw_negativearraysizeexception();
1125 /* now call the real function */
1127 return builtin_multianewarray_intern(n, arrayclass, dims);
1131 /*****************************************************************************
1134 Various functions for printing a message at method entry or exit (for
1137 *****************************************************************************/
1139 #if !defined(NDEBUG)
1140 static s4 methodindent = 0;
1141 static u4 callcount = 0;
1143 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1153 if (opt_verbosecall && indent)
1156 /* calculate message length */
1160 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1163 logtextlen = strlen("Some Throwable");
1166 logtextlen += strlen(" thrown in ");
1170 utf_bytes(m->class->name) +
1172 utf_bytes(m->name) +
1173 utf_bytes(m->descriptor) +
1174 strlen("(NOSYNC,NATIVE");
1176 #if SIZEOF_VOID_P == 8
1178 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1180 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1183 if (m->class->sourcefile == NULL)
1184 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1186 logtextlen += utf_bytes(m->class->sourcefile);
1188 logtextlen += strlen(":65536)");
1192 logtextlen += strlen("call_java_method");
1195 logtextlen += strlen("0");
1197 /* allocate memory */
1199 dumpsize = dump_size();
1201 logtext = DMNEW(char, logtextlen);
1204 strcpy(logtext, "Exception ");
1205 utf_cat_classname(logtext, xptr->vftbl->class->name);
1208 strcpy(logtext, "Some Throwable");
1211 strcat(logtext, " thrown in ");
1214 utf_cat_classname(logtext, m->class->name);
1215 strcat(logtext, ".");
1216 utf_cat(logtext, m->name);
1217 utf_cat(logtext, m->descriptor);
1219 if (m->flags & ACC_SYNCHRONIZED)
1220 strcat(logtext, "(SYNC");
1222 strcat(logtext, "(NOSYNC");
1224 if (m->flags & ACC_NATIVE) {
1225 strcat(logtext, ",NATIVE");
1229 #if SIZEOF_VOID_P == 8
1230 sprintf(logtext + strlen(logtext),
1231 ")(0x%016lx) at position 0x%016lx",
1232 (ptrint) code->entrypoint, (ptrint) pos);
1234 sprintf(logtext + strlen(logtext),
1235 ")(0x%08x) at position 0x%08x",
1236 (ptrint) code->entrypoint, (ptrint) pos);
1241 /* XXX preliminary: This should get the actual codeinfo */
1242 /* in which the exception happened. */
1245 #if SIZEOF_VOID_P == 8
1246 sprintf(logtext + strlen(logtext),
1247 ")(0x%016lx) at position 0x%016lx (",
1248 (ptrint) code->entrypoint, (ptrint) pos);
1250 sprintf(logtext + strlen(logtext),
1251 ")(0x%08x) at position 0x%08x (",
1252 (ptrint) code->entrypoint, (ptrint) pos);
1255 if (m->class->sourcefile == NULL)
1256 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1258 utf_cat(logtext, m->class->sourcefile);
1260 sprintf(logtext + strlen(logtext), ":%d)", 0);
1264 strcat(logtext, "call_java_method");
1268 /* release memory */
1270 dump_release(dumpsize);
1274 #endif /* !defined(NDEBUG) */
1277 /* builtin_trace_args **********************************************************
1281 *******************************************************************************/
1283 #if !defined(NDEBUG)
1285 #ifdef TRACE_ARGS_NUM
1286 void builtin_trace_args(s8 a0, s8 a1,
1287 #if TRACE_ARGS_NUM >= 4
1289 #endif /* TRACE_ARGS_NUM >= 4 */
1290 #if TRACE_ARGS_NUM >= 6
1292 #endif /* TRACE_ARGS_NUM >= 6 */
1293 #if TRACE_ARGS_NUM == 8
1295 #endif /* TRACE_ARGS_NUM == 8 */
1307 /* calculate message length */
1310 strlen("4294967295 ") +
1311 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1313 strlen("called: ") +
1314 utf_bytes(m->class->name) +
1316 utf_bytes(m->name) +
1317 utf_bytes(m->descriptor) +
1318 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1320 /* add maximal argument length */
1322 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1324 /* allocate memory */
1326 dumpsize = dump_size();
1328 logtext = DMNEW(char, logtextlen);
1332 sprintf(logtext, "%10d ", callcount);
1333 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1335 pos = strlen(logtext);
1337 for (i = 0; i < methodindent; i++)
1338 logtext[pos++] = '\t';
1340 strcpy(logtext + pos, "called: ");
1342 utf_cat_classname(logtext, m->class->name);
1343 strcat(logtext, ".");
1344 utf_cat(logtext, m->name);
1345 utf_cat(logtext, m->descriptor);
1347 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1348 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1349 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1350 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1351 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1352 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1353 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1354 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1355 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1356 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1357 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1359 strcat(logtext, "(");
1361 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1362 /* Only Arguments in integer Registers are passed correctly here */
1363 /* long longs spilled on Stack have an wrong offset of +4 */
1364 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1365 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1366 switch (md->paramcount) {
1370 #if SIZEOF_VOID_P == 4
1372 sprintf(logtext + strlen(logtext),
1378 sprintf(logtext + strlen(logtext),
1383 #if TRACE_ARGS_NUM >= 4
1385 sprintf(logtext + strlen(logtext),
1386 "0x%llx, 0x%llx, 0x%llx",
1391 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1393 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1396 #endif /* TRACE_ARGS_NUM >= 4 */
1398 #if TRACE_ARGS_NUM >= 6
1400 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1402 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1407 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1409 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1412 #endif /* TRACE_ARGS_NUM >= 6 */
1414 #if TRACE_ARGS_NUM == 8
1416 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1418 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1420 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1424 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1426 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1428 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1430 #endif /* TRACE_ARGS_NUM == 8 */
1433 #if TRACE_ARGS_NUM == 2
1434 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1436 #elif TRACE_ARGS_NUM == 4
1437 sprintf(logtext + strlen(logtext),
1438 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1439 a0, a1, a2, a3, md->paramcount - 4);
1441 #elif TRACE_ARGS_NUM == 6
1442 sprintf(logtext + strlen(logtext),
1443 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1444 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1446 #elif TRACE_ARGS_NUM == 8
1447 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1449 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1451 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1452 , a6, a7, md->paramcount - 8);
1456 #else /* SIZEOF_VOID_P == 4 */
1459 sprintf(logtext + strlen(logtext),
1465 sprintf(logtext + strlen(logtext),
1471 sprintf(logtext + strlen(logtext),
1472 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1476 sprintf(logtext + strlen(logtext),
1477 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1481 #if TRACE_ARGS_NUM >= 6
1483 sprintf(logtext + strlen(logtext),
1484 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1485 a0, a1, a2, a3, a4);
1489 sprintf(logtext + strlen(logtext),
1490 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1491 a0, a1, a2, a3, a4, a5);
1493 #endif /* TRACE_ARGS_NUM >= 6 */
1495 #if TRACE_ARGS_NUM == 8
1497 sprintf(logtext + strlen(logtext),
1498 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1499 a0, a1, a2, a3, a4, a5, a6);
1503 sprintf(logtext + strlen(logtext),
1504 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1505 a0, a1, a2, a3, a4, a5, a6, a7);
1507 #endif /* TRACE_ARGS_NUM == 8 */
1510 #if TRACE_ARGS_NUM == 4
1511 sprintf(logtext + strlen(logtext),
1512 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1513 a0, a1, a2, a3, md->paramcount - 4);
1515 #elif TRACE_ARGS_NUM == 6
1516 sprintf(logtext + strlen(logtext),
1517 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1518 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1520 #elif TRACE_ARGS_NUM == 8
1521 sprintf(logtext + strlen(logtext),
1522 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1523 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1526 #endif /* SIZEOF_VOID_P == 4 */
1529 strcat(logtext, ")");
1533 /* release memory */
1535 dump_release(dumpsize);
1540 #endif /* !defined(NDEBUG) */
1543 /* builtin_displaymethodstop ***************************************************
1547 *******************************************************************************/
1549 #if !defined(NDEBUG)
1550 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1558 java_objectheader *o;
1559 java_lang_String *s;
1567 /* calculate message length */
1570 strlen("4294967295 ") +
1571 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1573 strlen("finished: ") +
1574 utf_bytes(m->class->name) +
1576 utf_bytes(m->name) +
1577 utf_bytes(m->descriptor) +
1578 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1580 /* add maximal argument length */
1582 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1584 /* allocate memory */
1586 dumpsize = dump_size();
1588 logtext = DMNEW(char, logtextlen);
1590 /* outdent the log message */
1595 log_text("WARNING: unmatched methodindent--");
1597 /* generate the message */
1599 sprintf(logtext, " ");
1600 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1602 pos = strlen(logtext);
1604 for (i = 0; i < methodindent; i++)
1605 logtext[pos++] = '\t';
1607 strcpy(logtext + pos, "finished: ");
1608 utf_cat_classname(logtext, m->class->name);
1609 strcat(logtext, ".");
1610 utf_cat(logtext, m->name);
1611 utf_cat(logtext, m->descriptor);
1613 switch (md->returntype.type) {
1615 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1619 #if SIZEOF_VOID_P == 4
1620 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1622 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1627 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1629 /* check return argument for java.lang.Class or java.lang.String */
1631 o = (java_objectheader *) (ptrint) l;
1634 if (o->vftbl->class == class_java_lang_String) {
1635 /* get java.lang.String object and the length of the
1638 s = (java_lang_String *) (ptrint) l;
1640 u = javastring_toutf(s, false);
1642 len = strlen(", String = \"") + utf_bytes(u) + strlen("\"");
1644 /* realloc memory for string length */
1646 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1648 /* convert to utf8 string and strcat it to the logtext */
1650 strcat(logtext, ", String = \"");
1651 utf_cat(logtext, u);
1652 strcat(logtext, "\"");
1655 if (o->vftbl->class == class_java_lang_Class) {
1656 /* if the object returned is a java.lang.Class
1657 cast it to classinfo structure and get the name
1660 c = (classinfo *) (ptrint) l;
1665 /* if the object returned is not a java.lang.String or
1666 a java.lang.Class just print the name of the class */
1668 u = o->vftbl->class->name;
1671 len = strlen(", Class = \"") + utf_bytes(u) + strlen("\"");
1673 /* realloc memory for string length */
1675 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1677 /* strcat to the logtext */
1679 strcat(logtext, ", Class = \"");
1680 utf_cat_classname(logtext, u);
1681 strcat(logtext, "\"");
1688 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1693 #if SIZEOF_VOID_P == 4
1694 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1696 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1703 /* release memory */
1705 dump_release(dumpsize);
1707 #endif /* !defined(NDEBUG) */
1710 /****************************************************************************
1711 SYNCHRONIZATION FUNCTIONS
1712 *****************************************************************************/
1714 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1716 * Lock the mutex of an object.
1718 void internal_lock_mutex_for_object(java_objectheader *object)
1720 mutexHashEntry *entry;
1723 assert(object != 0);
1725 hashValue = MUTEX_HASH_VALUE(object);
1726 entry = &mutexHashTable[hashValue];
1728 if (entry->object != 0) {
1729 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1731 entry->mutex.holder = 0;
1732 entry->mutex.count = 0;
1733 entry->mutex.muxWaiters = 0;
1736 while (entry->next != 0 && entry->object != object)
1737 entry = entry->next;
1739 if (entry->object != object) {
1740 entry->next = firstFreeOverflowEntry;
1741 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1743 entry = entry->next;
1746 assert(entry->conditionCount == 0);
1751 entry->mutex.holder = 0;
1752 entry->mutex.count = 0;
1753 entry->mutex.muxWaiters = 0;
1756 if (entry->object == 0)
1757 entry->object = object;
1759 internal_lock_mutex(&entry->mutex);
1764 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1766 * Unlocks the mutex of an object.
1768 void internal_unlock_mutex_for_object (java_objectheader *object)
1771 mutexHashEntry *entry;
1773 hashValue = MUTEX_HASH_VALUE(object);
1774 entry = &mutexHashTable[hashValue];
1776 if (entry->object == object) {
1777 internal_unlock_mutex(&entry->mutex);
1780 while (entry->next != 0 && entry->next->object != object)
1781 entry = entry->next;
1783 assert(entry->next != 0);
1785 internal_unlock_mutex(&entry->next->mutex);
1787 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1788 mutexHashEntry *unlinked = entry->next;
1790 entry->next = unlinked->next;
1791 unlinked->next = firstFreeOverflowEntry;
1792 firstFreeOverflowEntry = unlinked;
1798 #if defined(ENABLE_CYCLES_STATS)
1799 void builtin_print_cycles_stats(FILE *file)
1801 fprintf(file,"builtin cylce count statistics:\n");
1803 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1804 CYCLES_STATS_PRINT(builtin_monitorenter,file);
1805 CYCLES_STATS_PRINT(builtin_monitorexit ,file);
1806 CYCLES_STATS_PRINT(builtin_new ,file);
1810 #endif /* defined(ENABLE_CYCLES_STATS) */
1812 #if defined(USE_THREADS)
1813 void builtin_monitorenter(java_objectheader *o)
1815 #if defined(ENABLE_CYCLES_STATS)
1816 u8 cycles_start, cycles_overhead, cycles_end;
1819 #if !defined(NATIVE_THREADS)
1824 hashValue = MUTEX_HASH_VALUE(o);
1825 if (mutexHashTable[hashValue].object == o
1826 && mutexHashTable[hashValue].mutex.holder == currentThread)
1827 ++mutexHashTable[hashValue].mutex.count;
1829 internal_lock_mutex_for_object(o);
1832 #else /* defined(NATIVE_THREADS) */
1833 CYCLES_STATS_GET(cycles_start);
1834 CYCLES_STATS_GET(cycles_overhead);
1836 lock_monitor_enter((threadobject *) THREADOBJECT, o);
1838 CYCLES_STATS_GET(cycles_end);
1839 CYCLES_STATS_COUNT(builtin_monitorenter, cycles_end - cycles_overhead);
1840 CYCLES_STATS_COUNT(builtin_overhead , cycles_overhead - cycles_start);
1841 #endif /* defined(NATIVE_THREADS) */
1846 #if defined(USE_THREADS)
1848 * Locks the class object - needed for static synchronized methods.
1850 void builtin_staticmonitorenter(classinfo *c)
1852 builtin_monitorenter(&c->object.header);
1857 #if defined(USE_THREADS)
1858 void builtin_monitorexit(java_objectheader *o)
1860 #if defined(ENABLE_CYCLES_STATS)
1861 u8 cycles_start, cycles_end;
1864 #if !defined(NATIVE_THREADS)
1869 hashValue = MUTEX_HASH_VALUE(o);
1870 if (mutexHashTable[hashValue].object == o) {
1871 if (mutexHashTable[hashValue].mutex.count == 1
1872 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1873 internal_unlock_mutex_for_object(o);
1875 --mutexHashTable[hashValue].mutex.count;
1878 internal_unlock_mutex_for_object(o);
1881 #else /* defined(NATIVE_THREADS) */
1882 CYCLES_STATS_GET(cycles_start);
1884 lock_monitor_exit((threadobject *) THREADOBJECT, o);
1886 CYCLES_STATS_GET(cycles_end);
1887 CYCLES_STATS_COUNT(builtin_monitorexit, cycles_end - cycles_start);
1888 #endif /* defined(NATIVE_THREADS) */
1893 /*****************************************************************************
1894 MISCELLANEOUS HELPER FUNCTIONS
1895 *****************************************************************************/
1899 /*********** Functions for integer divisions *****************************
1901 On some systems (eg. DEC ALPHA), integer division is not supported by the
1902 CPU. These helper functions implement the missing functionality.
1904 ******************************************************************************/
1906 #if !SUPPORT_DIVISION
1907 s4 builtin_idiv(s4 a, s4 b)
1916 s4 builtin_irem(s4 a, s4 b)
1924 #endif /* !SUPPORT_DIVISION */
1927 /* functions for long arithmetics **********************************************
1929 On systems where 64 bit Integers are not supported by the CPU,
1930 these functions are needed.
1932 ******************************************************************************/
1934 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1935 s8 builtin_ladd(s8 a, s8 b)
1948 s8 builtin_lsub(s8 a, s8 b)
1961 s8 builtin_lneg(s8 a)
1973 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1976 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1977 s8 builtin_lmul(s8 a, s8 b)
1989 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1992 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1993 s8 builtin_ldiv(s8 a, s8 b)
2006 s8 builtin_lrem(s8 a, s8 b)
2018 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
2021 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
2022 s8 builtin_lshl(s8 a, s4 b)
2035 s8 builtin_lshr(s8 a, s4 b)
2048 s8 builtin_lushr(s8 a, s4 b)
2053 c = ((u8) a) >> (b & 63);
2060 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
2063 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
2064 s8 builtin_land(s8 a, s8 b)
2077 s8 builtin_lor(s8 a, s8 b)
2090 s8 builtin_lxor(s8 a, s8 b)
2102 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2105 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2106 s4 builtin_lcmp(s8 a, s8 b)
2120 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2123 /* functions for unsupported floating instructions ****************************/
2125 /* used to convert FLT_xxx defines into float values */
2127 static inline float intBitsToFloat(s4 i)
2136 /* used to convert DBL_xxx defines into double values */
2138 static inline float longBitsToDouble(s8 l)
2148 float builtin_fadd(float a, float b)
2150 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2151 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2162 if (copysignf(1.0, a) == copysignf(1.0, b))
2165 return intBitsToFloat(FLT_NAN);
2171 float builtin_fsub(float a, float b)
2173 return builtin_fadd(a, builtin_fneg(b));
2177 float builtin_fmul(float a, float b)
2179 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2180 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2182 if (finitef(b)) return a * b;
2184 if (a == 0) return intBitsToFloat(FLT_NAN);
2185 else return copysignf(b, copysignf(1.0, b)*a);
2190 if (b == 0) return intBitsToFloat(FLT_NAN);
2191 else return copysignf(a, copysignf(1.0, a)*b);
2194 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2200 /* builtin_ddiv ****************************************************************
2202 Implementation as described in VM Spec.
2204 *******************************************************************************/
2206 float builtin_fdiv(float a, float b)
2210 /* If neither value1' nor value2' is NaN, the sign of the result */
2211 /* is positive if both values have the same sign, negative if the */
2212 /* values have different signs. */
2218 /* If either value1' or value2' is NaN, the result is NaN. */
2220 return intBitsToFloat(FLT_NAN);
2223 /* Division of a finite value by an infinity results in a */
2224 /* signed zero, with the sign-producing rule just given. */
2226 /* is sign equal? */
2228 if (copysignf(1.0, a) == copysignf(1.0, b))
2237 /* If either value1' or value2' is NaN, the result is NaN. */
2239 return intBitsToFloat(FLT_NAN);
2241 } else if (finitef(b)) {
2242 /* Division of an infinity by a finite value results in a signed */
2243 /* infinity, with the sign-producing rule just given. */
2245 /* is sign equal? */
2247 if (copysignf(1.0, a) == copysignf(1.0, b))
2248 return intBitsToFloat(FLT_POSINF);
2250 return intBitsToFloat(FLT_NEGINF);
2253 /* Division of an infinity by an infinity results in NaN. */
2255 return intBitsToFloat(FLT_NAN);
2261 float builtin_fneg(float a)
2263 if (isnanf(a)) return a;
2265 if (finitef(a)) return -a;
2266 else return copysignf(a, -copysignf(1.0, a));
2269 #endif /* !SUPPORT_FLOAT */
2272 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2273 s4 builtin_fcmpl(float a, float b)
2275 if (isnanf(a)) return -1;
2276 if (isnanf(b)) return -1;
2277 if (!finitef(a) || !finitef(b)) {
2278 a = finitef(a) ? 0 : copysignf(1.0, a);
2279 b = finitef(b) ? 0 : copysignf(1.0, b);
2281 if (a > b) return 1;
2282 if (a == b) return 0;
2287 s4 builtin_fcmpg(float a, float b)
2289 if (isnanf(a)) return 1;
2290 if (isnanf(b)) return 1;
2291 if (!finitef(a) || !finitef(b)) {
2292 a = finitef(a) ? 0 : copysignf(1.0, a);
2293 b = finitef(b) ? 0 : copysignf(1.0, b);
2295 if (a > b) return 1;
2296 if (a == b) return 0;
2299 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2302 float builtin_frem(float a, float b)
2308 /* functions for unsupported double instructions ******************************/
2311 double builtin_dadd(double a, double b)
2313 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2314 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2316 if (finite(b)) return a + b;
2320 if (finite(b)) return a;
2322 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2323 else return longBitsToDouble(DBL_NAN);
2329 double builtin_dsub(double a, double b)
2331 return builtin_dadd(a, builtin_dneg(b));
2335 double builtin_dmul(double a, double b)
2337 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2338 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2340 if (finite(b)) return a * b;
2342 if (a == 0) return longBitsToDouble(DBL_NAN);
2343 else return copysign(b, copysign(1.0, b) * a);
2348 if (b == 0) return longBitsToDouble(DBL_NAN);
2349 else return copysign(a, copysign(1.0, a) * b);
2352 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2358 /* builtin_ddiv ****************************************************************
2360 Implementation as described in VM Spec.
2362 *******************************************************************************/
2364 double builtin_ddiv(double a, double b)
2368 /* If neither value1' nor value2' is NaN, the sign of the result */
2369 /* is positive if both values have the same sign, negative if the */
2370 /* values have different signs. */
2376 /* If either value1' or value2' is NaN, the result is NaN. */
2378 return longBitsToDouble(DBL_NAN);
2381 /* Division of a finite value by an infinity results in a */
2382 /* signed zero, with the sign-producing rule just given. */
2384 /* is sign equal? */
2386 if (copysign(1.0, a) == copysign(1.0, b))
2395 /* If either value1' or value2' is NaN, the result is NaN. */
2397 return longBitsToDouble(DBL_NAN);
2399 } else if (finite(b)) {
2400 /* Division of an infinity by a finite value results in a signed */
2401 /* infinity, with the sign-producing rule just given. */
2403 /* is sign equal? */
2405 if (copysign(1.0, a) == copysign(1.0, b))
2406 return longBitsToDouble(DBL_POSINF);
2408 return longBitsToDouble(DBL_NEGINF);
2411 /* Division of an infinity by an infinity results in NaN. */
2413 return longBitsToDouble(DBL_NAN);
2419 /* builtin_dneg ****************************************************************
2421 Implemented as described in VM Spec.
2423 *******************************************************************************/
2425 double builtin_dneg(double a)
2428 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2435 /* If the operand is a zero, the result is the zero of opposite */
2441 /* If the operand is an infinity, the result is the infinity of */
2442 /* opposite sign. */
2444 return copysign(a, -copysign(1.0, a));
2448 #endif /* !SUPPORT_DOUBLE */
2451 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2452 s4 builtin_dcmpl(double a, double b)
2454 if (isnan(a)) return -1;
2455 if (isnan(b)) return -1;
2456 if (!finite(a) || !finite(b)) {
2457 a = finite(a) ? 0 : copysign(1.0, a);
2458 b = finite(b) ? 0 : copysign(1.0, b);
2460 if (a > b) return 1;
2461 if (a == b) return 0;
2466 s4 builtin_dcmpg(double a, double b)
2468 if (isnan(a)) return 1;
2469 if (isnan(b)) return 1;
2470 if (!finite(a) || !finite(b)) {
2471 a = finite(a) ? 0 : copysign(1.0, a);
2472 b = finite(b) ? 0 : copysign(1.0, b);
2474 if (a > b) return 1;
2475 if (a == b) return 0;
2478 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2481 double builtin_drem(double a, double b)
2487 /* conversion operations ******************************************************/
2490 s8 builtin_i2l(s4 i)
2502 s4 builtin_l2i(s8 l)
2513 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2514 float builtin_i2f(s4 a)
2516 float f = (float) a;
2519 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2522 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2523 double builtin_i2d(s4 a)
2525 double d = (double) a;
2528 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2531 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2532 float builtin_l2f(s8 a)
2535 float f = (float) a;
2541 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2544 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2545 double builtin_l2d(s8 a)
2548 double d = (double) a;
2554 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2557 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2558 s4 builtin_f2i(float a)
2562 i = builtin_d2i((double) a);
2573 if (a < (-2147483648))
2574 return (-2147483648);
2577 f = copysignf((float) 1.0, a);
2580 return (-2147483648); */
2582 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2585 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2586 s8 builtin_f2l(float a)
2590 l = builtin_d2l((double) a);
2597 if (a > 9223372036854775807L)
2598 return 9223372036854775807L;
2599 if (a < (-9223372036854775808L))
2600 return (-9223372036854775808L);
2605 f = copysignf((float) 1.0, a);
2607 return 9223372036854775807L;
2608 return (-9223372036854775808L); */
2610 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2613 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2614 s4 builtin_d2i(double a)
2619 if (a >= 2147483647)
2621 if (a <= (-2147483647-1))
2622 return (-2147483647-1);
2627 d = copysign(1.0, a);
2630 return (-2147483647-1);
2632 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2635 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2636 s8 builtin_d2l(double a)
2641 if (a >= 9223372036854775807LL)
2642 return 9223372036854775807LL;
2643 if (a <= (-9223372036854775807LL-1))
2644 return (-9223372036854775807LL-1);
2649 d = copysign(1.0, a);
2651 return 9223372036854775807LL;
2652 return (-9223372036854775807LL-1);
2654 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2657 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2658 double builtin_f2d(float a)
2660 if (finitef(a)) return (double) a;
2663 return longBitsToDouble(DBL_NAN);
2665 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2669 float builtin_d2f(double a)
2675 return intBitsToFloat(FLT_NAN);
2677 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2680 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2683 /* builtin_clone_array *********************************************************
2685 Wrapper function for cloning arrays.
2687 *******************************************************************************/
2689 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2691 java_arrayheader *ah;
2692 java_lang_Cloneable *c;
2694 c = (java_lang_Cloneable *) o;
2696 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2702 /* builtin_asm_get_exceptionptrptr *********************************************
2704 this is a wrapper for calls from asmpart
2706 *******************************************************************************/
2708 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2709 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2711 return builtin_get_exceptionptrptr();
2717 * These are local overrides for various environment variables in Emacs.
2718 * Please do not remove this and leave it at the end of the file, where
2719 * Emacs will automagically detect them.
2720 * ---------------------------------------------------------------------
2723 * indent-tabs-mode: t
2727 * vim:noexpandtab:sw=4:ts=4: