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 4829 2006-04-24 17:16:45Z 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_strlen(xptr->vftbl->class->name) +
536 javastring_strlen(t->detailMessage);
539 logtextlen += strlen("(nil)");
541 /* allocate memory */
543 dumpsize = dump_size();
545 logtext = DMNEW(char, logtextlen);
547 strcpy(logtext, "Builtin exception thrown: ");
550 utf_sprint_classname(logtext + strlen(logtext),
551 xptr->vftbl->class->name);
553 if (t->detailMessage) {
556 buf = javastring_tochar((java_objectheader *) t->detailMessage);
557 strcat(logtext, ": ");
558 strcat(logtext, buf);
559 MFREE(buf, char, strlen(buf));
563 strcat(logtext, "(nil)");
570 dump_release(dumpsize);
572 #endif /* !defined(NDEBUG) */
574 /* actually set the exception */
576 *exceptionptr = xptr;
578 /* Return a NULL pointer. This is required for vm_call_method to
579 check for an exception. This is for convenience. */
585 /* builtin_canstore ************************************************************
587 Checks, if an object can be stored in an array.
589 Return value: 1 ... possible
592 *******************************************************************************/
594 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
596 arraydescriptor *desc;
597 arraydescriptor *valuedesc;
598 vftbl_t *componentvftbl;
601 castinfo classvalues;
606 /* The following is guaranteed (by verifier checks):
608 * *) oa->...vftbl->arraydesc != NULL
609 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
610 * *) o->vftbl is not an interface vftbl
613 desc = oa->header.objheader.vftbl->arraydesc;
614 componentvftbl = desc->componentvftbl;
615 valuevftbl = o->vftbl;
617 if ((desc->dimension - 1) == 0) {
620 /* {oa is a one-dimensional array} */
621 /* {oa is an array of references} */
623 if (valuevftbl == componentvftbl)
626 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
628 if ((base = classvalues.super_baseval) <= 0)
629 /* an array of interface references */
630 return (valuevftbl->interfacetablelength > -base &&
631 valuevftbl->interfacetable[base] != NULL);
633 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
634 <= (unsigned) classvalues.super_diffval);
639 /* {oa has dimension > 1} */
640 /* {componentvftbl->arraydesc != NULL} */
642 /* check if o is an array */
644 if ((valuedesc = valuevftbl->arraydesc) == NULL)
647 /* {o is an array} */
649 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
653 /* This is an optimized version where a is guaranteed to be one-dimensional */
654 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
656 arraydescriptor *desc;
657 vftbl_t *elementvftbl;
661 castinfo classvalues;
665 /* The following is guaranteed (by verifier checks):
667 * *) a->...vftbl->arraydesc != NULL
668 * *) a->...vftbl->arraydesc->elementvftbl != NULL
669 * *) a->...vftbl->arraydesc->dimension == 1
670 * *) o->vftbl is not an interface vftbl
673 desc = a->header.objheader.vftbl->arraydesc;
674 elementvftbl = desc->elementvftbl;
675 valuevftbl = o->vftbl;
677 /* {a is a one-dimensional array} */
679 if (valuevftbl == elementvftbl)
682 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
684 if ((base = classvalues.super_baseval) <= 0)
685 /* an array of interface references */
686 return (valuevftbl->interfacetablelength > -base &&
687 valuevftbl->interfacetable[base] != NULL);
689 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
690 <= (unsigned) classvalues.super_diffval;
696 /* This is an optimized version where a is guaranteed to be a
697 * one-dimensional array of a class type */
698 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
700 vftbl_t *elementvftbl;
703 castinfo classvalues;
707 /* The following is guaranteed (by verifier checks):
709 * *) a->...vftbl->arraydesc != NULL
710 * *) a->...vftbl->arraydesc->elementvftbl != NULL
711 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
712 * *) a->...vftbl->arraydesc->dimension == 1
713 * *) o->vftbl is not an interface vftbl
716 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
717 valuevftbl = o->vftbl;
719 /* {a is a one-dimensional array} */
721 if (valuevftbl == elementvftbl)
724 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
726 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
727 <= (unsigned) classvalues.super_diffval;
733 /* builtin_new *****************************************************************
735 Creates a new instance of class c on the heap.
737 Return value: pointer to the object or NULL if no memory is
740 *******************************************************************************/
742 java_objectheader *builtin_new(classinfo *c)
744 java_objectheader *o;
745 #if defined(ENABLE_RT_TIMING)
746 struct timespec time_start, time_end;
748 #if defined(ENABLE_CYCLES_STATS)
749 u8 cycles_start, cycles_end;
752 RT_TIMING_GET_TIME(time_start);
753 CYCLES_STATS_GET(cycles_start);
755 /* is the class loaded */
757 assert(c->state & CLASS_LOADED);
759 /* check if we can instantiate this class */
761 if (c->flags & ACC_ABSTRACT) {
763 new_exception_utfmessage(string_java_lang_InstantiationError,
768 /* is the class linked */
770 if (!(c->state & CLASS_LINKED))
774 if (!(c->state & CLASS_INITIALIZED)) {
777 log_message_class("Initialize class (from builtin_new): ", c);
780 if (!initialize_class(c))
784 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
792 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
796 CYCLES_STATS_GET(cycles_end);
797 RT_TIMING_GET_TIME(time_end);
799 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
800 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
806 /* builtin_newarray ************************************************************
808 Creates an array with the given vftbl on the heap. This function
809 takes as class argument an array class.
811 Return value: pointer to the array or NULL if no memory is available
813 *******************************************************************************/
815 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
817 arraydescriptor *desc;
822 #if defined(ENABLE_RT_TIMING)
823 struct timespec time_start, time_end;
826 RT_TIMING_GET_TIME(time_start);
828 desc = arrayclass->vftbl->arraydesc;
829 dataoffset = desc->dataoffset;
830 componentsize = desc->componentsize;
833 exceptions_throw_negativearraysizeexception();
837 actualsize = dataoffset + size * componentsize;
839 if (((u4) actualsize) < ((u4) size)) { /* overflow */
840 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
844 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
849 a->objheader.vftbl = arrayclass->vftbl;
851 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
852 initObjectLock(&a->objheader);
857 RT_TIMING_GET_TIME(time_end);
858 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
864 /* builtin_anewarray ***********************************************************
866 Creates an array of references to the given class type on the heap.
868 Return value: pointer to the array or NULL if no memory is
871 *******************************************************************************/
873 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
875 classinfo *arrayclass;
877 /* is class loaded */
879 assert(componentclass->state & CLASS_LOADED);
881 /* is class linked */
883 if (!(componentclass->state & CLASS_LINKED))
884 if (!link_class(componentclass))
887 arrayclass = class_array_of(componentclass, true);
892 return (java_objectarray *) builtin_newarray(size, arrayclass);
896 /* builtin_newarray_boolean ****************************************************
898 Creates an array of bytes on the heap. The array is designated as
899 an array of booleans (important for casts)
901 Return value: pointer to the array or NULL if no memory is
904 *******************************************************************************/
906 java_booleanarray *builtin_newarray_boolean(s4 size)
908 return (java_booleanarray *)
909 builtin_newarray(size,
910 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
914 /* builtin_newarray_byte *******************************************************
916 Creates an array of 8 bit Integers on the heap.
918 Return value: pointer to the array or NULL if no memory is
921 *******************************************************************************/
923 java_bytearray *builtin_newarray_byte(s4 size)
925 return (java_bytearray *)
926 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
930 /* builtin_newarray_char *******************************************************
932 Creates an array of characters on the heap.
934 Return value: pointer to the array or NULL if no memory is
937 *******************************************************************************/
939 java_chararray *builtin_newarray_char(s4 size)
941 return (java_chararray *)
942 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
946 /* builtin_newarray_short ******************************************************
948 Creates an array of 16 bit Integers on the heap.
950 Return value: pointer to the array or NULL if no memory is
953 *******************************************************************************/
955 java_shortarray *builtin_newarray_short(s4 size)
957 return (java_shortarray *)
958 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
962 /* builtin_newarray_int ********************************************************
964 Creates an array of 32 bit Integers on the heap.
966 Return value: pointer to the array or NULL if no memory is
969 *******************************************************************************/
971 java_intarray *builtin_newarray_int(s4 size)
973 return (java_intarray *)
974 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
978 /* builtin_newarray_long *******************************************************
980 Creates an array of 64 bit Integers on the heap.
982 Return value: pointer to the array or NULL if no memory is
985 *******************************************************************************/
987 java_longarray *builtin_newarray_long(s4 size)
989 return (java_longarray *)
990 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
994 /* builtin_newarray_float ******************************************************
996 Creates an array of 32 bit IEEE floats on the heap.
998 Return value: pointer to the array or NULL if no memory is
1001 *******************************************************************************/
1003 java_floatarray *builtin_newarray_float(s4 size)
1005 return (java_floatarray *)
1006 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1010 /* builtin_newarray_double *****************************************************
1012 Creates an array of 64 bit IEEE floats on the heap.
1014 Return value: pointer to the array or NULL if no memory is
1017 *******************************************************************************/
1019 java_doublearray *builtin_newarray_double(s4 size)
1021 return (java_doublearray *)
1022 builtin_newarray(size,
1023 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1027 /* builtin_multianewarray_intern ***********************************************
1029 Creates a multi-dimensional array on the heap. The dimensions are
1030 passed in an array of longs.
1033 n............number of dimensions to create
1034 arrayvftbl...vftbl of the array class
1035 dims.........array containing the size of each dimension to create
1037 Return value: pointer to the array or NULL if no memory is
1040 ******************************************************************************/
1042 static java_arrayheader *builtin_multianewarray_intern(int n,
1043 classinfo *arrayclass,
1047 java_arrayheader *a;
1048 classinfo *componentclass;
1051 /* create this dimension */
1053 size = (s4) dims[0];
1054 a = builtin_newarray(size, arrayclass);
1059 /* if this is the last dimension return */
1064 /* get the class of the components to create */
1066 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1068 /* The verifier guarantees that the dimension count is in the range. */
1070 /* create the component arrays */
1072 for (i = 0; i < size; i++) {
1073 java_arrayheader *ea =
1074 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1075 /* we save an s4 to a s8 slot, 8-byte aligned */
1077 builtin_multianewarray_intern(n, componentclass, dims + 2);
1079 builtin_multianewarray_intern(n, componentclass, dims + 1);
1085 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1092 /* builtin_multianewarray ******************************************************
1094 Wrapper for builtin_multianewarray_intern which checks all
1095 dimensions before we start allocating.
1097 ******************************************************************************/
1099 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1105 /* check all dimensions before doing anything */
1107 for (i = 0; i < n; i++) {
1108 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1109 /* we save an s4 to a s8 slot, 8-byte aligned */
1110 size = (s4) dims[i * 2];
1112 size = (s4) dims[i];
1116 exceptions_throw_negativearraysizeexception();
1121 /* now call the real function */
1123 return builtin_multianewarray_intern(n, arrayclass, dims);
1127 /*****************************************************************************
1130 Various functions for printing a message at method entry or exit (for
1133 *****************************************************************************/
1135 #if !defined(NDEBUG)
1136 static s4 methodindent = 0;
1137 static u4 callcount = 0;
1139 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1149 if (opt_verbosecall && indent)
1152 /* calculate message length */
1156 strlen("Exception ") +
1157 utf_strlen(xptr->vftbl->class->name);
1160 logtextlen = strlen("Some Throwable");
1163 logtextlen += strlen(" thrown in ");
1167 utf_strlen(m->class->name) +
1169 utf_strlen(m->name) +
1170 utf_strlen(m->descriptor) +
1171 strlen("(NOSYNC,NATIVE");
1173 #if SIZEOF_VOID_P == 8
1175 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1177 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1180 if (m->class->sourcefile == NULL)
1181 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1183 logtextlen += utf_strlen(m->class->sourcefile);
1185 logtextlen += strlen(":65536)");
1188 logtextlen += strlen("call_java_method");
1190 logtextlen += strlen("0");
1192 /* allocate memory */
1194 dumpsize = dump_size();
1196 logtext = DMNEW(char, logtextlen);
1199 strcpy(logtext, "Exception ");
1200 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1203 strcpy(logtext, "Some Throwable");
1206 strcat(logtext, " thrown in ");
1209 utf_strcat_classname(logtext, m->class->name);
1210 strcat(logtext, ".");
1211 utf_strcat(logtext, m->name);
1212 utf_strcat(logtext, m->descriptor);
1214 if (m->flags & ACC_SYNCHRONIZED)
1215 strcat(logtext, "(SYNC");
1217 strcat(logtext, "(NOSYNC");
1219 if (m->flags & ACC_NATIVE) {
1220 strcat(logtext, ",NATIVE");
1224 #if SIZEOF_VOID_P == 8
1225 sprintf(logtext + strlen(logtext),
1226 ")(0x%016lx) at position 0x%016lx",
1227 (ptrint) code->entrypoint, (ptrint) pos);
1229 sprintf(logtext + strlen(logtext),
1230 ")(0x%08x) at position 0x%08x",
1231 (ptrint) code->entrypoint, (ptrint) pos);
1236 /* XXX preliminary: This should get the actual codeinfo */
1237 /* in which the exception happened. */
1240 #if SIZEOF_VOID_P == 8
1241 sprintf(logtext + strlen(logtext),
1242 ")(0x%016lx) at position 0x%016lx (",
1243 (ptrint) code->entrypoint, (ptrint) pos);
1245 sprintf(logtext + strlen(logtext),
1246 ")(0x%08x) at position 0x%08x (",
1247 (ptrint) code->entrypoint, (ptrint) pos);
1250 if (m->class->sourcefile == NULL)
1251 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1253 utf_strcat(logtext, m->class->sourcefile);
1255 sprintf(logtext + strlen(logtext), ":%d)", 0);
1259 strcat(logtext, "call_java_method");
1263 /* release memory */
1265 dump_release(dumpsize);
1269 #endif /* !defined(NDEBUG) */
1272 /* builtin_trace_args **********************************************************
1276 *******************************************************************************/
1278 #if !defined(NDEBUG)
1280 #ifdef TRACE_ARGS_NUM
1281 void builtin_trace_args(s8 a0, s8 a1,
1282 #if TRACE_ARGS_NUM >= 4
1284 #endif /* TRACE_ARGS_NUM >= 4 */
1285 #if TRACE_ARGS_NUM >= 6
1287 #endif /* TRACE_ARGS_NUM >= 6 */
1288 #if TRACE_ARGS_NUM == 8
1290 #endif /* TRACE_ARGS_NUM == 8 */
1302 /* calculate message length */
1305 strlen("4294967295 ") +
1306 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1308 strlen("called: ") +
1309 utf_strlen(m->class->name) +
1311 utf_strlen(m->name) +
1312 utf_strlen(m->descriptor) +
1313 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1315 /* add maximal argument length */
1317 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1319 /* allocate memory */
1321 dumpsize = dump_size();
1323 logtext = DMNEW(char, logtextlen);
1327 sprintf(logtext, "%10d ", callcount);
1328 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1330 pos = strlen(logtext);
1332 for (i = 0; i < methodindent; i++)
1333 logtext[pos++] = '\t';
1335 strcpy(logtext + pos, "called: ");
1337 utf_strcat_classname(logtext, m->class->name);
1338 strcat(logtext, ".");
1339 utf_strcat(logtext, m->name);
1340 utf_strcat(logtext, m->descriptor);
1342 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1343 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1344 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1345 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1346 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1347 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1348 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1349 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1350 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1351 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1352 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1354 strcat(logtext, "(");
1356 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1357 /* Only Arguments in integer Registers are passed correctly here */
1358 /* long longs spilled on Stack have an wrong offset of +4 */
1359 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1360 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1361 switch (md->paramcount) {
1365 #if SIZEOF_VOID_P == 4
1367 sprintf(logtext + strlen(logtext),
1373 sprintf(logtext + strlen(logtext),
1378 #if TRACE_ARGS_NUM >= 4
1380 sprintf(logtext + strlen(logtext),
1381 "0x%llx, 0x%llx, 0x%llx",
1386 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1388 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1391 #endif /* TRACE_ARGS_NUM >= 4 */
1393 #if TRACE_ARGS_NUM >= 6
1395 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1397 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1402 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1404 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1407 #endif /* TRACE_ARGS_NUM >= 6 */
1409 #if TRACE_ARGS_NUM == 8
1411 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1413 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1415 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1419 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1421 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1423 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1425 #endif /* TRACE_ARGS_NUM == 8 */
1428 #if TRACE_ARGS_NUM == 2
1429 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1431 #elif TRACE_ARGS_NUM == 4
1432 sprintf(logtext + strlen(logtext),
1433 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1434 a0, a1, a2, a3, md->paramcount - 4);
1436 #elif TRACE_ARGS_NUM == 6
1437 sprintf(logtext + strlen(logtext),
1438 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1439 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1441 #elif TRACE_ARGS_NUM == 8
1442 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1444 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1446 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1447 , a6, a7, md->paramcount - 8);
1451 #else /* SIZEOF_VOID_P == 4 */
1454 sprintf(logtext + strlen(logtext),
1460 sprintf(logtext + strlen(logtext),
1466 sprintf(logtext + strlen(logtext),
1467 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1471 sprintf(logtext + strlen(logtext),
1472 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1476 #if TRACE_ARGS_NUM >= 6
1478 sprintf(logtext + strlen(logtext),
1479 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1480 a0, a1, a2, a3, a4);
1484 sprintf(logtext + strlen(logtext),
1485 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1486 a0, a1, a2, a3, a4, a5);
1488 #endif /* TRACE_ARGS_NUM >= 6 */
1490 #if TRACE_ARGS_NUM == 8
1492 sprintf(logtext + strlen(logtext),
1493 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1494 a0, a1, a2, a3, a4, a5, a6);
1498 sprintf(logtext + strlen(logtext),
1499 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1500 a0, a1, a2, a3, a4, a5, a6, a7);
1502 #endif /* TRACE_ARGS_NUM == 8 */
1505 #if TRACE_ARGS_NUM == 4
1506 sprintf(logtext + strlen(logtext),
1507 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1508 a0, a1, a2, a3, md->paramcount - 4);
1510 #elif TRACE_ARGS_NUM == 6
1511 sprintf(logtext + strlen(logtext),
1512 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1513 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1515 #elif TRACE_ARGS_NUM == 8
1516 sprintf(logtext + strlen(logtext),
1517 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1518 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1521 #endif /* SIZEOF_VOID_P == 4 */
1524 strcat(logtext, ")");
1528 /* release memory */
1530 dump_release(dumpsize);
1535 #endif /* !defined(NDEBUG) */
1538 /* builtin_displaymethodstop ***************************************************
1542 *******************************************************************************/
1544 #if !defined(NDEBUG)
1545 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1553 java_objectheader *o;
1554 java_lang_String *s;
1562 /* calculate message length */
1565 strlen("4294967295 ") +
1566 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1568 strlen("finished: ") +
1569 utf_strlen(m->class->name) +
1571 utf_strlen(m->name) +
1572 utf_strlen(m->descriptor) +
1573 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1575 /* add maximal argument length */
1577 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1579 /* allocate memory */
1581 dumpsize = dump_size();
1583 logtext = DMNEW(char, logtextlen);
1585 /* outdent the log message */
1590 log_text("WARNING: unmatched methodindent--");
1592 /* generate the message */
1594 sprintf(logtext, " ");
1595 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1597 pos = strlen(logtext);
1599 for (i = 0; i < methodindent; i++)
1600 logtext[pos++] = '\t';
1602 strcpy(logtext + pos, "finished: ");
1603 utf_strcat_classname(logtext, m->class->name);
1604 strcat(logtext, ".");
1605 utf_strcat(logtext, m->name);
1606 utf_strcat(logtext, m->descriptor);
1608 switch (md->returntype.type) {
1610 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1614 #if SIZEOF_VOID_P == 4
1615 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1617 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1622 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1624 /* check return argument for java.lang.Class or java.lang.String */
1626 o = (java_objectheader *) (ptrint) l;
1629 if (o->vftbl->class == class_java_lang_String) {
1630 /* get java.lang.String object and the length of the
1633 s= (java_lang_String *) (ptrint) l;
1635 len = strlen(", String = \"") + javastring_strlen(s) +
1638 /* realloc memory for string length */
1640 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1642 /* convert to utf8 string and strcat it to the logtext */
1644 u = javastring_toutf(s, false);
1646 strcat(logtext, ", String = \"");
1647 utf_strcat(logtext, u);
1648 strcat(logtext, "\"");
1651 if (o->vftbl->class == class_java_lang_Class) {
1652 /* if the object returned is a java.lang.Class
1653 cast it to classinfo structure and get the name
1656 c = (classinfo *) (ptrint) l;
1661 /* if the object returned is not a java.lang.String or
1662 a java.lang.Class just print the name of the class */
1664 u = o->vftbl->class->name;
1667 len = strlen(", Class = \"") + utf_strlen(u) + strlen("\"");
1669 /* realloc memory for string length */
1671 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1673 /* strcat to the logtext */
1675 strcat(logtext, ", Class = \"");
1676 utf_strcat(logtext, u);
1677 strcat(logtext, "\"");
1684 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1689 #if SIZEOF_VOID_P == 4
1690 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1692 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1699 /* release memory */
1701 dump_release(dumpsize);
1703 #endif /* !defined(NDEBUG) */
1706 /****************************************************************************
1707 SYNCHRONIZATION FUNCTIONS
1708 *****************************************************************************/
1710 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1712 * Lock the mutex of an object.
1714 void internal_lock_mutex_for_object(java_objectheader *object)
1716 mutexHashEntry *entry;
1719 assert(object != 0);
1721 hashValue = MUTEX_HASH_VALUE(object);
1722 entry = &mutexHashTable[hashValue];
1724 if (entry->object != 0) {
1725 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1727 entry->mutex.holder = 0;
1728 entry->mutex.count = 0;
1729 entry->mutex.muxWaiters = 0;
1732 while (entry->next != 0 && entry->object != object)
1733 entry = entry->next;
1735 if (entry->object != object) {
1736 entry->next = firstFreeOverflowEntry;
1737 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1739 entry = entry->next;
1742 assert(entry->conditionCount == 0);
1747 entry->mutex.holder = 0;
1748 entry->mutex.count = 0;
1749 entry->mutex.muxWaiters = 0;
1752 if (entry->object == 0)
1753 entry->object = object;
1755 internal_lock_mutex(&entry->mutex);
1760 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1762 * Unlocks the mutex of an object.
1764 void internal_unlock_mutex_for_object (java_objectheader *object)
1767 mutexHashEntry *entry;
1769 hashValue = MUTEX_HASH_VALUE(object);
1770 entry = &mutexHashTable[hashValue];
1772 if (entry->object == object) {
1773 internal_unlock_mutex(&entry->mutex);
1776 while (entry->next != 0 && entry->next->object != object)
1777 entry = entry->next;
1779 assert(entry->next != 0);
1781 internal_unlock_mutex(&entry->next->mutex);
1783 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1784 mutexHashEntry *unlinked = entry->next;
1786 entry->next = unlinked->next;
1787 unlinked->next = firstFreeOverflowEntry;
1788 firstFreeOverflowEntry = unlinked;
1794 #if defined(ENABLE_CYCLES_STATS)
1795 void builtin_print_cycles_stats(FILE *file)
1797 fprintf(file,"builtin cylce count statistics:\n");
1799 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1800 CYCLES_STATS_PRINT(builtin_monitorenter,file);
1801 CYCLES_STATS_PRINT(builtin_monitorexit ,file);
1802 CYCLES_STATS_PRINT(builtin_new ,file);
1806 #endif /* defined(ENABLE_CYCLES_STATS) */
1808 #if defined(USE_THREADS)
1809 void builtin_monitorenter(java_objectheader *o)
1811 #if defined(ENABLE_CYCLES_STATS)
1812 u8 cycles_start, cycles_overhead, cycles_end;
1815 #if !defined(NATIVE_THREADS)
1820 hashValue = MUTEX_HASH_VALUE(o);
1821 if (mutexHashTable[hashValue].object == o
1822 && mutexHashTable[hashValue].mutex.holder == currentThread)
1823 ++mutexHashTable[hashValue].mutex.count;
1825 internal_lock_mutex_for_object(o);
1828 #else /* defined(NATIVE_THREADS) */
1829 CYCLES_STATS_GET(cycles_start);
1830 CYCLES_STATS_GET(cycles_overhead);
1832 monitorEnter((threadobject *) THREADOBJECT, o);
1834 CYCLES_STATS_GET(cycles_end);
1835 CYCLES_STATS_COUNT(builtin_monitorenter, cycles_end - cycles_overhead);
1836 CYCLES_STATS_COUNT(builtin_overhead , cycles_overhead - cycles_start);
1837 #endif /* defined(NATIVE_THREADS) */
1842 #if defined(USE_THREADS)
1844 * Locks the class object - needed for static synchronized methods.
1846 void builtin_staticmonitorenter(classinfo *c)
1848 builtin_monitorenter(&c->object.header);
1853 #if defined(USE_THREADS)
1854 void builtin_monitorexit(java_objectheader *o)
1856 #if defined(ENABLE_CYCLES_STATS)
1857 u8 cycles_start, cycles_end;
1860 #if !defined(NATIVE_THREADS)
1865 hashValue = MUTEX_HASH_VALUE(o);
1866 if (mutexHashTable[hashValue].object == o) {
1867 if (mutexHashTable[hashValue].mutex.count == 1
1868 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1869 internal_unlock_mutex_for_object(o);
1871 --mutexHashTable[hashValue].mutex.count;
1874 internal_unlock_mutex_for_object(o);
1877 #else /* defined(NATIVE_THREADS) */
1878 CYCLES_STATS_GET(cycles_start);
1880 monitorExit((threadobject *) THREADOBJECT, o);
1882 CYCLES_STATS_GET(cycles_end);
1883 CYCLES_STATS_COUNT(builtin_monitorexit, cycles_end - cycles_start);
1884 #endif /* defined(NATIVE_THREADS) */
1889 /*****************************************************************************
1890 MISCELLANEOUS HELPER FUNCTIONS
1891 *****************************************************************************/
1895 /*********** Functions for integer divisions *****************************
1897 On some systems (eg. DEC ALPHA), integer division is not supported by the
1898 CPU. These helper functions implement the missing functionality.
1900 ******************************************************************************/
1902 #if !SUPPORT_DIVISION
1903 s4 builtin_idiv(s4 a, s4 b)
1912 s4 builtin_irem(s4 a, s4 b)
1920 #endif /* !SUPPORT_DIVISION */
1923 /* functions for long arithmetics **********************************************
1925 On systems where 64 bit Integers are not supported by the CPU,
1926 these functions are needed.
1928 ******************************************************************************/
1930 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1931 s8 builtin_ladd(s8 a, s8 b)
1944 s8 builtin_lsub(s8 a, s8 b)
1957 s8 builtin_lneg(s8 a)
1969 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1972 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1973 s8 builtin_lmul(s8 a, s8 b)
1985 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1988 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1989 s8 builtin_ldiv(s8 a, s8 b)
2002 s8 builtin_lrem(s8 a, s8 b)
2014 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
2017 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
2018 s8 builtin_lshl(s8 a, s4 b)
2031 s8 builtin_lshr(s8 a, s4 b)
2044 s8 builtin_lushr(s8 a, s4 b)
2049 c = ((u8) a) >> (b & 63);
2056 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
2059 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
2060 s8 builtin_land(s8 a, s8 b)
2073 s8 builtin_lor(s8 a, s8 b)
2086 s8 builtin_lxor(s8 a, s8 b)
2098 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2101 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2102 s4 builtin_lcmp(s8 a, s8 b)
2116 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2119 /* functions for unsupported floating instructions ****************************/
2121 /* used to convert FLT_xxx defines into float values */
2123 static inline float intBitsToFloat(s4 i)
2132 /* used to convert DBL_xxx defines into double values */
2134 static inline float longBitsToDouble(s8 l)
2144 float builtin_fadd(float a, float b)
2146 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2147 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2158 if (copysignf(1.0, a) == copysignf(1.0, b))
2161 return intBitsToFloat(FLT_NAN);
2167 float builtin_fsub(float a, float b)
2169 return builtin_fadd(a, builtin_fneg(b));
2173 float builtin_fmul(float a, float b)
2175 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2176 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2178 if (finitef(b)) return a * b;
2180 if (a == 0) return intBitsToFloat(FLT_NAN);
2181 else return copysignf(b, copysignf(1.0, b)*a);
2186 if (b == 0) return intBitsToFloat(FLT_NAN);
2187 else return copysignf(a, copysignf(1.0, a)*b);
2190 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2196 /* builtin_ddiv ****************************************************************
2198 Implementation as described in VM Spec.
2200 *******************************************************************************/
2202 float builtin_fdiv(float a, float b)
2206 /* If neither value1' nor value2' is NaN, the sign of the result */
2207 /* is positive if both values have the same sign, negative if the */
2208 /* values have different signs. */
2214 /* If either value1' or value2' is NaN, the result is NaN. */
2216 return intBitsToFloat(FLT_NAN);
2219 /* Division of a finite value by an infinity results in a */
2220 /* signed zero, with the sign-producing rule just given. */
2222 /* is sign equal? */
2224 if (copysignf(1.0, a) == copysignf(1.0, b))
2233 /* If either value1' or value2' is NaN, the result is NaN. */
2235 return intBitsToFloat(FLT_NAN);
2237 } else if (finitef(b)) {
2238 /* Division of an infinity by a finite value results in a signed */
2239 /* infinity, with the sign-producing rule just given. */
2241 /* is sign equal? */
2243 if (copysignf(1.0, a) == copysignf(1.0, b))
2244 return intBitsToFloat(FLT_POSINF);
2246 return intBitsToFloat(FLT_NEGINF);
2249 /* Division of an infinity by an infinity results in NaN. */
2251 return intBitsToFloat(FLT_NAN);
2257 float builtin_fneg(float a)
2259 if (isnanf(a)) return a;
2261 if (finitef(a)) return -a;
2262 else return copysignf(a, -copysignf(1.0, a));
2265 #endif /* !SUPPORT_FLOAT */
2268 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2269 s4 builtin_fcmpl(float a, float b)
2271 if (isnanf(a)) return -1;
2272 if (isnanf(b)) return -1;
2273 if (!finitef(a) || !finitef(b)) {
2274 a = finitef(a) ? 0 : copysignf(1.0, a);
2275 b = finitef(b) ? 0 : copysignf(1.0, b);
2277 if (a > b) return 1;
2278 if (a == b) return 0;
2283 s4 builtin_fcmpg(float a, float b)
2285 if (isnanf(a)) return 1;
2286 if (isnanf(b)) return 1;
2287 if (!finitef(a) || !finitef(b)) {
2288 a = finitef(a) ? 0 : copysignf(1.0, a);
2289 b = finitef(b) ? 0 : copysignf(1.0, b);
2291 if (a > b) return 1;
2292 if (a == b) return 0;
2295 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2298 float builtin_frem(float a, float b)
2304 /* functions for unsupported double instructions ******************************/
2307 double builtin_dadd(double a, double b)
2309 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2310 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2312 if (finite(b)) return a + b;
2316 if (finite(b)) return a;
2318 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2319 else return longBitsToDouble(DBL_NAN);
2325 double builtin_dsub(double a, double b)
2327 return builtin_dadd(a, builtin_dneg(b));
2331 double builtin_dmul(double a, double b)
2333 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2334 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2336 if (finite(b)) return a * b;
2338 if (a == 0) return longBitsToDouble(DBL_NAN);
2339 else return copysign(b, copysign(1.0, b) * a);
2344 if (b == 0) return longBitsToDouble(DBL_NAN);
2345 else return copysign(a, copysign(1.0, a) * b);
2348 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2354 /* builtin_ddiv ****************************************************************
2356 Implementation as described in VM Spec.
2358 *******************************************************************************/
2360 double builtin_ddiv(double a, double b)
2364 /* If neither value1' nor value2' is NaN, the sign of the result */
2365 /* is positive if both values have the same sign, negative if the */
2366 /* values have different signs. */
2372 /* If either value1' or value2' is NaN, the result is NaN. */
2374 return longBitsToDouble(DBL_NAN);
2377 /* Division of a finite value by an infinity results in a */
2378 /* signed zero, with the sign-producing rule just given. */
2380 /* is sign equal? */
2382 if (copysign(1.0, a) == copysign(1.0, b))
2391 /* If either value1' or value2' is NaN, the result is NaN. */
2393 return longBitsToDouble(DBL_NAN);
2395 } else if (finite(b)) {
2396 /* Division of an infinity by a finite value results in a signed */
2397 /* infinity, with the sign-producing rule just given. */
2399 /* is sign equal? */
2401 if (copysign(1.0, a) == copysign(1.0, b))
2402 return longBitsToDouble(DBL_POSINF);
2404 return longBitsToDouble(DBL_NEGINF);
2407 /* Division of an infinity by an infinity results in NaN. */
2409 return longBitsToDouble(DBL_NAN);
2415 /* builtin_dneg ****************************************************************
2417 Implemented as described in VM Spec.
2419 *******************************************************************************/
2421 double builtin_dneg(double a)
2424 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2431 /* If the operand is a zero, the result is the zero of opposite */
2437 /* If the operand is an infinity, the result is the infinity of */
2438 /* opposite sign. */
2440 return copysign(a, -copysign(1.0, a));
2444 #endif /* !SUPPORT_DOUBLE */
2447 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2448 s4 builtin_dcmpl(double a, double b)
2450 if (isnan(a)) return -1;
2451 if (isnan(b)) return -1;
2452 if (!finite(a) || !finite(b)) {
2453 a = finite(a) ? 0 : copysign(1.0, a);
2454 b = finite(b) ? 0 : copysign(1.0, b);
2456 if (a > b) return 1;
2457 if (a == b) return 0;
2462 s4 builtin_dcmpg(double a, double b)
2464 if (isnan(a)) return 1;
2465 if (isnan(b)) return 1;
2466 if (!finite(a) || !finite(b)) {
2467 a = finite(a) ? 0 : copysign(1.0, a);
2468 b = finite(b) ? 0 : copysign(1.0, b);
2470 if (a > b) return 1;
2471 if (a == b) return 0;
2474 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2477 double builtin_drem(double a, double b)
2483 /* conversion operations ******************************************************/
2486 s8 builtin_i2l(s4 i)
2498 s4 builtin_l2i(s8 l)
2509 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2510 float builtin_i2f(s4 a)
2512 float f = (float) a;
2515 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2518 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2519 double builtin_i2d(s4 a)
2521 double d = (double) a;
2524 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2527 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2528 float builtin_l2f(s8 a)
2531 float f = (float) a;
2537 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2540 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2541 double builtin_l2d(s8 a)
2544 double d = (double) a;
2550 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2553 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2554 s4 builtin_f2i(float a)
2558 i = builtin_d2i((double) a);
2569 if (a < (-2147483648))
2570 return (-2147483648);
2573 f = copysignf((float) 1.0, a);
2576 return (-2147483648); */
2578 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2581 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2582 s8 builtin_f2l(float a)
2586 l = builtin_d2l((double) a);
2593 if (a > 9223372036854775807L)
2594 return 9223372036854775807L;
2595 if (a < (-9223372036854775808L))
2596 return (-9223372036854775808L);
2601 f = copysignf((float) 1.0, a);
2603 return 9223372036854775807L;
2604 return (-9223372036854775808L); */
2606 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2609 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2610 s4 builtin_d2i(double a)
2615 if (a >= 2147483647)
2617 if (a <= (-2147483647-1))
2618 return (-2147483647-1);
2623 d = copysign(1.0, a);
2626 return (-2147483647-1);
2628 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2631 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2632 s8 builtin_d2l(double a)
2637 if (a >= 9223372036854775807LL)
2638 return 9223372036854775807LL;
2639 if (a <= (-9223372036854775807LL-1))
2640 return (-9223372036854775807LL-1);
2645 d = copysign(1.0, a);
2647 return 9223372036854775807LL;
2648 return (-9223372036854775807LL-1);
2650 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2653 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2654 double builtin_f2d(float a)
2656 if (finitef(a)) return (double) a;
2659 return longBitsToDouble(DBL_NAN);
2661 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2665 float builtin_d2f(double a)
2671 return intBitsToFloat(FLT_NAN);
2673 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2676 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2679 /* builtin_clone_array *********************************************************
2681 Wrapper function for cloning arrays.
2683 *******************************************************************************/
2685 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2687 java_arrayheader *ah;
2688 java_lang_Cloneable *c;
2690 c = (java_lang_Cloneable *) o;
2692 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2698 /* builtin_asm_get_exceptionptrptr *********************************************
2700 this is a wrapper for calls from asmpart
2702 *******************************************************************************/
2704 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2705 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2707 return builtin_get_exceptionptrptr();
2713 * These are local overrides for various environment variables in Emacs.
2714 * Please do not remove this and leave it at the end of the file, where
2715 * Emacs will automagically detect them.
2716 * ---------------------------------------------------------------------
2719 * indent-tabs-mode: t
2723 * vim:noexpandtab:sw=4:ts=4: