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 5123 2006-07-12 21:45:34Z twisti $
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(ENABLE_THREADS)
67 # include "threads/native/threads.h"
70 #include "toolbox/logging.h"
71 #include "toolbox/util.h"
72 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/loader.h"
78 #include "vm/options.h"
79 #include "vm/stringlocal.h"
80 #include "vm/jit/asmpart.h"
81 #include "vm/jit/patcher.h"
82 #include "vm/rt-timing.h"
83 #include "vm/cycles-stats.h"
86 /* include builtin tables *****************************************************/
88 #include "vm/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_new ,100,5)
92 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
94 /* builtintable_init ***********************************************************
96 Parse the descriptors of builtin functions and create the parsed
99 *******************************************************************************/
101 static bool builtintable_init(void)
103 descriptor_pool *descpool;
107 s4 entries_automatic;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* calculate table entries statically */
129 sizeof(builtintable_internal) / sizeof(builtintable_entry);
132 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
133 - 1; /* last filler entry (comment see builtintable.inc) */
135 /* first add all descriptors to the pool */
137 for (i = 0; i < entries_internal; i++) {
138 /* create a utf8 string from descriptor */
140 descriptor = utf_new_char(builtintable_internal[i].descriptor);
142 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
143 /* release dump area */
145 dump_release(dumpsize);
151 for (i = 0; i < entries_automatic; i++) {
152 /* create a utf8 string from descriptor */
154 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
156 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
157 /* release dump area */
159 dump_release(dumpsize);
165 /* create the class reference table */
167 (void) descriptor_pool_create_classrefs(descpool, NULL);
169 /* allocate space for the parsed descriptors */
171 descriptor_pool_alloc_parsed_descriptors(descpool);
173 /* now parse all descriptors */
175 for (i = 0; i < entries_internal; i++) {
176 /* create a utf8 string from descriptor */
178 descriptor = utf_new_char(builtintable_internal[i].descriptor);
180 /* parse the descriptor, builtin is always static (no `this' pointer) */
182 builtintable_internal[i].md =
183 descriptor_pool_parse_method_descriptor(descpool, descriptor,
187 for (i = 0; i < entries_automatic; i++) {
188 /* create a utf8 string from descriptor */
190 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
192 /* parse the descriptor, builtin is always static (no `this' pointer) */
194 builtintable_automatic[i].md =
195 descriptor_pool_parse_method_descriptor(descpool, descriptor,
199 /* release dump area */
201 dump_release(dumpsize);
207 /* builtintable_comparator *****************************************************
209 qsort comparator for the automatic builtin table.
211 *******************************************************************************/
213 static int builtintable_comparator(const void *a, const void *b)
215 builtintable_entry *bte1;
216 builtintable_entry *bte2;
218 bte1 = (builtintable_entry *) a;
219 bte2 = (builtintable_entry *) b;
221 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
225 /* builtintable_sort_automatic *************************************************
227 Sorts the automatic builtin table.
229 *******************************************************************************/
231 static void builtintable_sort_automatic(void)
235 /* calculate table size statically (`- 1' comment see builtintable.inc) */
237 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
239 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
240 builtintable_comparator);
244 /* builtin_init ****************************************************************
246 Initialize the global table of builtin functions.
248 *******************************************************************************/
250 bool builtin_init(void)
252 /* initialize the builtin tables */
254 if (!builtintable_init())
257 /* sort builtin tables */
259 builtintable_sort_automatic();
265 /* builtintable_get_internal ***************************************************
267 Finds an entry in the builtintable for internal functions and
268 returns the a pointer to the structure.
270 *******************************************************************************/
272 builtintable_entry *builtintable_get_internal(functionptr fp)
276 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
277 if (builtintable_internal[i].fp == fp)
278 return &builtintable_internal[i];
285 /* builtintable_get_automatic **************************************************
287 Finds an entry in the builtintable for functions which are replaced
288 automatically and returns the a pointer to the structure.
290 *******************************************************************************/
292 builtintable_entry *builtintable_get_automatic(s4 opcode)
294 builtintable_entry *first;
295 builtintable_entry *last;
296 builtintable_entry *middle;
300 /* calculate table size statically (`- 1' comment see builtintable.inc) */
302 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
304 first = builtintable_automatic;
305 last = builtintable_automatic + entries;
307 while (entries > 0) {
309 middle = first + half;
311 if (middle->opcode < opcode) {
318 return (first != last ? first : NULL);
322 /*****************************************************************************
324 *****************************************************************************/
328 /*************** internal function: builtin_isanysubclass *********************
330 Checks a subclass relation between two classes. Implemented interfaces
331 are interpreted as super classes.
332 Return value: 1 ... sub is subclass of super
335 *****************************************************************************/
336 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
339 castinfo classvalues;
344 if (super->flags & ACC_INTERFACE) {
345 res = (sub->vftbl->interfacetablelength > super->index) &&
346 (sub->vftbl->interfacetable[-super->index] != NULL);
349 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
351 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
352 (u4) classvalues.super_diffval;
359 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
363 castinfo classvalues;
368 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
370 if ((base = classvalues.super_baseval) <= 0) {
371 /* super is an interface */
372 res = (sub->interfacetablelength > -base) &&
373 (sub->interfacetable[base] != NULL);
375 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
376 <= (u4) classvalues.super_diffval;
383 /****************** function: builtin_instanceof *****************************
385 Checks if an object is an instance of some given class (or subclass of
386 that class). If class is an interface, checks if the interface is
388 Return value: 1 ... obj is an instance of class or implements the interface
389 0 ... otherwise or if obj == NULL
391 *****************************************************************************/
393 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
398 return builtin_isanysubclass(obj->vftbl->class, class);
403 /**************** function: builtin_checkcast *******************************
405 The same as builtin_instanceof except that 1 is returned when
408 ****************************************************************************/
410 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
415 if (builtin_isanysubclass(obj->vftbl->class, class))
422 /* builtin_descriptorscompatible ***********************************************
424 Checks if two array type descriptors are assignment compatible
426 Return value: 1 ... target = desc is possible
429 *******************************************************************************/
431 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
432 arraydescriptor *target)
437 if (desc->arraytype != target->arraytype)
440 if (desc->arraytype != ARRAYTYPE_OBJECT)
443 /* {both arrays are arrays of references} */
445 if (desc->dimension == target->dimension) {
446 /* an array which contains elements of interface types is
447 allowed to be casted to Object (JOWENN)*/
449 if ((desc->elementvftbl->baseval < 0) &&
450 (target->elementvftbl->baseval == 1))
453 return builtin_isanysubclass_vftbl(desc->elementvftbl,
454 target->elementvftbl);
457 if (desc->dimension < target->dimension)
460 /* {desc has higher dimension than target} */
462 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
463 target->elementvftbl);
467 /* builtin_arraycheckcast ******************************************************
469 Checks if an object is really a subtype of the requested array
470 type. The object has to be an array to begin with. For simple
471 arrays (int, short, double, etc.) the types have to match exactly.
472 For arrays of objects, the type of elements in the array has to be
473 a subtype (or the same type) of the requested element type. For
474 arrays of arrays (which in turn can again be arrays of arrays), the
475 types at the lowest level have to satisfy the corresponding sub
478 *******************************************************************************/
480 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
482 arraydescriptor *desc;
487 if ((desc = o->vftbl->arraydesc) == NULL)
490 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
494 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
499 return builtin_arraycheckcast(o, targetclass);
503 /* builtin_throw_exception *****************************************************
505 Sets the exceptionptr with the thrown exception and prints some
506 debugging information. Called from asm_vm_call_method.
508 *******************************************************************************/
510 void *builtin_throw_exception(java_objectheader *xptr)
513 java_lang_Throwable *t;
519 t = (java_lang_Throwable *) xptr;
521 /* calculate message length */
523 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
527 utf_bytes(xptr->vftbl->class->name);
528 if (t->detailMessage) {
529 logtextlen += strlen(": ") +
530 u2_utflength(t->detailMessage->value->data
531 + t->detailMessage->offset,
532 t->detailMessage->count);
536 logtextlen += strlen("(nil)");
539 /* allocate memory */
541 dumpsize = dump_size();
543 logtext = DMNEW(char, logtextlen);
545 strcpy(logtext, "Builtin exception thrown: ");
548 utf_cat_classname(logtext, xptr->vftbl->class->name);
550 if (t->detailMessage) {
553 buf = javastring_tochar((java_objectheader *) t->detailMessage);
554 strcat(logtext, ": ");
555 strcat(logtext, buf);
556 MFREE(buf, char, strlen(buf) + 1);
560 strcat(logtext, "(nil)");
567 dump_release(dumpsize);
569 #endif /* !defined(NDEBUG) */
571 /* actually set the exception */
573 *exceptionptr = xptr;
575 /* Return a NULL pointer. This is required for vm_call_method to
576 check for an exception. This is for convenience. */
582 /* builtin_canstore ************************************************************
584 Checks, if an object can be stored in an array.
586 Return value: 1 ... possible
589 *******************************************************************************/
591 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
593 arraydescriptor *desc;
594 arraydescriptor *valuedesc;
595 vftbl_t *componentvftbl;
598 castinfo classvalues;
603 /* The following is guaranteed (by verifier checks):
605 * *) oa->...vftbl->arraydesc != NULL
606 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
607 * *) o->vftbl is not an interface vftbl
610 desc = oa->header.objheader.vftbl->arraydesc;
611 componentvftbl = desc->componentvftbl;
612 valuevftbl = o->vftbl;
614 if ((desc->dimension - 1) == 0) {
617 /* {oa is a one-dimensional array} */
618 /* {oa is an array of references} */
620 if (valuevftbl == componentvftbl)
623 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
625 if ((base = classvalues.super_baseval) <= 0)
626 /* an array of interface references */
627 return (valuevftbl->interfacetablelength > -base &&
628 valuevftbl->interfacetable[base] != NULL);
630 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
631 <= (unsigned) classvalues.super_diffval);
636 /* {oa has dimension > 1} */
637 /* {componentvftbl->arraydesc != NULL} */
639 /* check if o is an array */
641 if ((valuedesc = valuevftbl->arraydesc) == NULL)
644 /* {o is an array} */
646 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
650 /* This is an optimized version where a is guaranteed to be one-dimensional */
651 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
653 arraydescriptor *desc;
654 vftbl_t *elementvftbl;
658 castinfo classvalues;
662 /* The following is guaranteed (by verifier checks):
664 * *) a->...vftbl->arraydesc != NULL
665 * *) a->...vftbl->arraydesc->elementvftbl != NULL
666 * *) a->...vftbl->arraydesc->dimension == 1
667 * *) o->vftbl is not an interface vftbl
670 desc = a->header.objheader.vftbl->arraydesc;
671 elementvftbl = desc->elementvftbl;
672 valuevftbl = o->vftbl;
674 /* {a is a one-dimensional array} */
676 if (valuevftbl == elementvftbl)
679 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
681 if ((base = classvalues.super_baseval) <= 0)
682 /* an array of interface references */
683 return (valuevftbl->interfacetablelength > -base &&
684 valuevftbl->interfacetable[base] != NULL);
686 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
687 <= (unsigned) classvalues.super_diffval;
693 /* This is an optimized version where a is guaranteed to be a
694 * one-dimensional array of a class type */
695 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
697 vftbl_t *elementvftbl;
700 castinfo classvalues;
704 /* The following is guaranteed (by verifier checks):
706 * *) a->...vftbl->arraydesc != NULL
707 * *) a->...vftbl->arraydesc->elementvftbl != NULL
708 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
709 * *) a->...vftbl->arraydesc->dimension == 1
710 * *) o->vftbl is not an interface vftbl
713 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
714 valuevftbl = o->vftbl;
716 /* {a is a one-dimensional array} */
718 if (valuevftbl == elementvftbl)
721 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
723 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
724 <= (unsigned) classvalues.super_diffval;
730 /* builtin_new *****************************************************************
732 Creates a new instance of class c on the heap.
734 Return value: pointer to the object or NULL if no memory is
737 *******************************************************************************/
739 java_objectheader *builtin_new(classinfo *c)
741 java_objectheader *o;
742 #if defined(ENABLE_RT_TIMING)
743 struct timespec time_start, time_end;
745 #if defined(ENABLE_CYCLES_STATS)
746 u8 cycles_start, cycles_end;
749 RT_TIMING_GET_TIME(time_start);
750 CYCLES_STATS_GET(cycles_start);
752 /* is the class loaded */
754 assert(c->state & CLASS_LOADED);
756 /* check if we can instantiate this class */
758 if (c->flags & ACC_ABSTRACT) {
760 new_exception_utfmessage(string_java_lang_InstantiationError,
765 /* is the class linked */
767 if (!(c->state & CLASS_LINKED))
771 if (!(c->state & CLASS_INITIALIZED)) {
774 log_message_class("Initialize class (from builtin_new): ", c);
777 if (!initialize_class(c))
781 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
789 #if defined(ENABLE_THREADS)
790 lock_init_object_lock(o);
793 CYCLES_STATS_GET(cycles_end);
794 RT_TIMING_GET_TIME(time_end);
796 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
797 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
803 /* builtin_newarray ************************************************************
805 Creates an array with the given vftbl on the heap. This function
806 takes as class argument an array class.
808 Return value: pointer to the array or NULL if no memory is available
810 *******************************************************************************/
812 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
814 arraydescriptor *desc;
819 #if defined(ENABLE_RT_TIMING)
820 struct timespec time_start, time_end;
823 RT_TIMING_GET_TIME(time_start);
825 desc = arrayclass->vftbl->arraydesc;
826 dataoffset = desc->dataoffset;
827 componentsize = desc->componentsize;
830 exceptions_throw_negativearraysizeexception();
834 actualsize = dataoffset + size * componentsize;
836 if (((u4) actualsize) < ((u4) size)) { /* overflow */
837 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
841 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
846 a->objheader.vftbl = arrayclass->vftbl;
848 #if defined(ENABLE_THREADS)
849 lock_init_object_lock(&a->objheader);
854 RT_TIMING_GET_TIME(time_end);
855 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
861 /* builtin_anewarray ***********************************************************
863 Creates an array of references to the given class type on the heap.
865 Return value: pointer to the array or NULL if no memory is
868 *******************************************************************************/
870 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
872 classinfo *arrayclass;
874 /* is class loaded */
876 assert(componentclass->state & CLASS_LOADED);
878 /* is class linked */
880 if (!(componentclass->state & CLASS_LINKED))
881 if (!link_class(componentclass))
884 arrayclass = class_array_of(componentclass, true);
889 return (java_objectarray *) builtin_newarray(size, arrayclass);
893 /* builtin_newarray_boolean ****************************************************
895 Creates an array of bytes on the heap. The array is designated as
896 an array of booleans (important for casts)
898 Return value: pointer to the array or NULL if no memory is
901 *******************************************************************************/
903 java_booleanarray *builtin_newarray_boolean(s4 size)
905 return (java_booleanarray *)
906 builtin_newarray(size,
907 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
911 /* builtin_newarray_byte *******************************************************
913 Creates an array of 8 bit Integers on the heap.
915 Return value: pointer to the array or NULL if no memory is
918 *******************************************************************************/
920 java_bytearray *builtin_newarray_byte(s4 size)
922 return (java_bytearray *)
923 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
927 /* builtin_newarray_char *******************************************************
929 Creates an array of characters on the heap.
931 Return value: pointer to the array or NULL if no memory is
934 *******************************************************************************/
936 java_chararray *builtin_newarray_char(s4 size)
938 return (java_chararray *)
939 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
943 /* builtin_newarray_short ******************************************************
945 Creates an array of 16 bit Integers on the heap.
947 Return value: pointer to the array or NULL if no memory is
950 *******************************************************************************/
952 java_shortarray *builtin_newarray_short(s4 size)
954 return (java_shortarray *)
955 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
959 /* builtin_newarray_int ********************************************************
961 Creates an array of 32 bit Integers on the heap.
963 Return value: pointer to the array or NULL if no memory is
966 *******************************************************************************/
968 java_intarray *builtin_newarray_int(s4 size)
970 return (java_intarray *)
971 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
975 /* builtin_newarray_long *******************************************************
977 Creates an array of 64 bit Integers on the heap.
979 Return value: pointer to the array or NULL if no memory is
982 *******************************************************************************/
984 java_longarray *builtin_newarray_long(s4 size)
986 return (java_longarray *)
987 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
991 /* builtin_newarray_float ******************************************************
993 Creates an array of 32 bit IEEE floats on the heap.
995 Return value: pointer to the array or NULL if no memory is
998 *******************************************************************************/
1000 java_floatarray *builtin_newarray_float(s4 size)
1002 return (java_floatarray *)
1003 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1007 /* builtin_newarray_double *****************************************************
1009 Creates an array of 64 bit IEEE floats on the heap.
1011 Return value: pointer to the array or NULL if no memory is
1014 *******************************************************************************/
1016 java_doublearray *builtin_newarray_double(s4 size)
1018 return (java_doublearray *)
1019 builtin_newarray(size,
1020 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1024 /* builtin_multianewarray_intern ***********************************************
1026 Creates a multi-dimensional array on the heap. The dimensions are
1027 passed in an array of longs.
1030 n............number of dimensions to create
1031 arrayvftbl...vftbl of the array class
1032 dims.........array containing the size of each dimension to create
1034 Return value: pointer to the array or NULL if no memory is
1037 ******************************************************************************/
1039 static java_arrayheader *builtin_multianewarray_intern(int n,
1040 classinfo *arrayclass,
1044 java_arrayheader *a;
1045 classinfo *componentclass;
1048 /* create this dimension */
1050 size = (s4) dims[0];
1051 a = builtin_newarray(size, arrayclass);
1056 /* if this is the last dimension return */
1061 /* get the class of the components to create */
1063 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1065 /* The verifier guarantees that the dimension count is in the range. */
1067 /* create the component arrays */
1069 for (i = 0; i < size; i++) {
1070 java_arrayheader *ea =
1071 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1072 /* we save an s4 to a s8 slot, 8-byte aligned */
1074 builtin_multianewarray_intern(n, componentclass, dims + 2);
1076 builtin_multianewarray_intern(n, componentclass, dims + 1);
1082 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1089 /* builtin_multianewarray ******************************************************
1091 Wrapper for builtin_multianewarray_intern which checks all
1092 dimensions before we start allocating.
1094 ******************************************************************************/
1096 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1102 /* check all dimensions before doing anything */
1104 for (i = 0; i < n; i++) {
1105 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1106 /* we save an s4 to a s8 slot, 8-byte aligned */
1107 size = (s4) dims[i * 2];
1109 size = (s4) dims[i];
1113 exceptions_throw_negativearraysizeexception();
1118 /* now call the real function */
1120 return builtin_multianewarray_intern(n, arrayclass, dims);
1124 /*****************************************************************************
1127 Various functions for printing a message at method entry or exit (for
1130 *****************************************************************************/
1132 #if !defined(NDEBUG)
1133 static s4 methodindent = 0;
1134 static u4 callcount = 0;
1136 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1146 if (opt_verbosecall && indent)
1149 /* calculate message length */
1153 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1156 logtextlen = strlen("Some Throwable");
1159 logtextlen += strlen(" thrown in ");
1163 utf_bytes(m->class->name) +
1165 utf_bytes(m->name) +
1166 utf_bytes(m->descriptor) +
1167 strlen("(NOSYNC,NATIVE");
1169 #if SIZEOF_VOID_P == 8
1171 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1173 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1176 if (m->class->sourcefile == NULL)
1177 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1179 logtextlen += utf_bytes(m->class->sourcefile);
1181 logtextlen += strlen(":65536)");
1185 logtextlen += strlen("call_java_method");
1188 logtextlen += strlen("0");
1190 /* allocate memory */
1192 dumpsize = dump_size();
1194 logtext = DMNEW(char, logtextlen);
1197 strcpy(logtext, "Exception ");
1198 utf_cat_classname(logtext, xptr->vftbl->class->name);
1201 strcpy(logtext, "Some Throwable");
1204 strcat(logtext, " thrown in ");
1207 utf_cat_classname(logtext, m->class->name);
1208 strcat(logtext, ".");
1209 utf_cat(logtext, m->name);
1210 utf_cat(logtext, m->descriptor);
1212 if (m->flags & ACC_SYNCHRONIZED)
1213 strcat(logtext, "(SYNC");
1215 strcat(logtext, "(NOSYNC");
1217 if (m->flags & ACC_NATIVE) {
1218 strcat(logtext, ",NATIVE");
1222 #if SIZEOF_VOID_P == 8
1223 sprintf(logtext + strlen(logtext),
1224 ")(0x%016lx) at position 0x%016lx",
1225 (ptrint) code->entrypoint, (ptrint) pos);
1227 sprintf(logtext + strlen(logtext),
1228 ")(0x%08x) at position 0x%08x",
1229 (ptrint) code->entrypoint, (ptrint) pos);
1234 /* XXX preliminary: This should get the actual codeinfo */
1235 /* in which the exception happened. */
1238 #if SIZEOF_VOID_P == 8
1239 sprintf(logtext + strlen(logtext),
1240 ")(0x%016lx) at position 0x%016lx (",
1241 (ptrint) code->entrypoint, (ptrint) pos);
1243 sprintf(logtext + strlen(logtext),
1244 ")(0x%08x) at position 0x%08x (",
1245 (ptrint) code->entrypoint, (ptrint) pos);
1248 if (m->class->sourcefile == NULL)
1249 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1251 utf_cat(logtext, m->class->sourcefile);
1253 sprintf(logtext + strlen(logtext), ":%d)", 0);
1257 strcat(logtext, "call_java_method");
1261 /* release memory */
1263 dump_release(dumpsize);
1267 #endif /* !defined(NDEBUG) */
1270 /* builtin_trace_args **********************************************************
1272 Print method call with arguments for -verbose:call.
1274 *******************************************************************************/
1276 #if !defined(NDEBUG)
1278 #ifdef TRACE_ARGS_NUM
1279 void builtin_trace_args(s8 a0, s8 a1,
1280 #if TRACE_ARGS_NUM >= 4
1282 #endif /* TRACE_ARGS_NUM >= 4 */
1283 #if TRACE_ARGS_NUM >= 6
1285 #endif /* TRACE_ARGS_NUM >= 6 */
1286 #if TRACE_ARGS_NUM == 8
1288 #endif /* TRACE_ARGS_NUM == 8 */
1300 /* calculate message length */
1303 strlen("4294967295 ") +
1304 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1306 strlen("called: ") +
1307 utf_bytes(m->class->name) +
1309 utf_bytes(m->name) +
1310 utf_bytes(m->descriptor) +
1311 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1313 /* add maximal argument length */
1315 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1317 /* allocate memory */
1319 dumpsize = dump_size();
1321 logtext = DMNEW(char, logtextlen);
1325 sprintf(logtext, "%10d ", callcount);
1326 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1328 pos = strlen(logtext);
1330 for (i = 0; i < methodindent; i++)
1331 logtext[pos++] = '\t';
1333 strcpy(logtext + pos, "called: ");
1335 utf_cat_classname(logtext, m->class->name);
1336 strcat(logtext, ".");
1337 utf_cat(logtext, m->name);
1338 utf_cat(logtext, m->descriptor);
1340 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1341 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1342 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1343 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1344 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1345 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1346 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1347 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1348 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1349 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1350 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1352 strcat(logtext, "(");
1354 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1355 /* Only Arguments in integer Registers are passed correctly here */
1356 /* long longs spilled on Stack have an wrong offset of +4 */
1357 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1358 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1359 switch (md->paramcount) {
1363 #if SIZEOF_VOID_P == 4
1365 sprintf(logtext + strlen(logtext),
1371 sprintf(logtext + strlen(logtext),
1376 #if TRACE_ARGS_NUM >= 4
1378 sprintf(logtext + strlen(logtext),
1379 "0x%llx, 0x%llx, 0x%llx",
1384 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1386 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1389 #endif /* TRACE_ARGS_NUM >= 4 */
1391 #if TRACE_ARGS_NUM >= 6
1393 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1395 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1400 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1402 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1405 #endif /* TRACE_ARGS_NUM >= 6 */
1407 #if TRACE_ARGS_NUM == 8
1409 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1411 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1413 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1417 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1419 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1421 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1423 #endif /* TRACE_ARGS_NUM == 8 */
1426 #if TRACE_ARGS_NUM == 2
1427 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1429 #elif TRACE_ARGS_NUM == 4
1430 sprintf(logtext + strlen(logtext),
1431 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1432 a0, a1, a2, a3, md->paramcount - 4);
1434 #elif TRACE_ARGS_NUM == 6
1435 sprintf(logtext + strlen(logtext),
1436 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1437 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1439 #elif TRACE_ARGS_NUM == 8
1440 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1442 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1444 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1445 , a6, a7, md->paramcount - 8);
1449 #else /* SIZEOF_VOID_P == 4 */
1452 sprintf(logtext + strlen(logtext),
1458 sprintf(logtext + strlen(logtext),
1464 sprintf(logtext + strlen(logtext),
1465 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1469 sprintf(logtext + strlen(logtext),
1470 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1474 #if TRACE_ARGS_NUM >= 6
1476 sprintf(logtext + strlen(logtext),
1477 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1478 a0, a1, a2, a3, a4);
1482 sprintf(logtext + strlen(logtext),
1483 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1484 a0, a1, a2, a3, a4, a5);
1486 #endif /* TRACE_ARGS_NUM >= 6 */
1488 #if TRACE_ARGS_NUM == 8
1490 sprintf(logtext + strlen(logtext),
1491 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1492 a0, a1, a2, a3, a4, a5, a6);
1496 sprintf(logtext + strlen(logtext),
1497 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1498 a0, a1, a2, a3, a4, a5, a6, a7);
1500 #endif /* TRACE_ARGS_NUM == 8 */
1503 #if TRACE_ARGS_NUM == 4
1504 sprintf(logtext + strlen(logtext),
1505 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1506 a0, a1, a2, a3, md->paramcount - 4);
1508 #elif TRACE_ARGS_NUM == 6
1509 sprintf(logtext + strlen(logtext),
1510 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1511 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1513 #elif TRACE_ARGS_NUM == 8
1514 sprintf(logtext + strlen(logtext),
1515 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1516 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1519 #endif /* SIZEOF_VOID_P == 4 */
1522 strcat(logtext, ")");
1526 /* release memory */
1528 dump_release(dumpsize);
1533 #endif /* !defined(NDEBUG) */
1536 /* builtin_displaymethodstop ***************************************************
1538 Print method exit for -verbose:call.
1540 *******************************************************************************/
1542 #if !defined(NDEBUG)
1543 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1551 java_objectheader *o;
1552 java_lang_String *s;
1560 /* calculate message length */
1563 strlen("4294967295 ") +
1564 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1566 strlen("finished: ") +
1567 utf_bytes(m->class->name) +
1569 utf_bytes(m->name) +
1570 utf_bytes(m->descriptor) +
1571 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1573 /* add maximal argument length */
1575 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1577 /* allocate memory */
1579 dumpsize = dump_size();
1581 logtext = DMNEW(char, logtextlen);
1583 /* outdent the log message */
1588 log_text("WARNING: unmatched methodindent--");
1590 /* generate the message */
1592 sprintf(logtext, " ");
1593 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1595 pos = strlen(logtext);
1597 for (i = 0; i < methodindent; i++)
1598 logtext[pos++] = '\t';
1600 strcpy(logtext + pos, "finished: ");
1601 utf_cat_classname(logtext, m->class->name);
1602 strcat(logtext, ".");
1603 utf_cat(logtext, m->name);
1604 utf_cat(logtext, m->descriptor);
1606 switch (md->returntype.type) {
1608 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1612 #if SIZEOF_VOID_P == 4
1613 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1615 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1620 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1622 /* check return argument for java.lang.Class or java.lang.String */
1624 o = (java_objectheader *) (ptrint) l;
1627 if (o->vftbl->class == class_java_lang_String) {
1628 /* get java.lang.String object and the length of the
1631 s = (java_lang_String *) (ptrint) l;
1633 u = javastring_toutf(s, false);
1635 len = strlen(", String = \"") + utf_bytes(u) + strlen("\"");
1637 /* realloc memory for string length */
1639 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1641 /* convert to utf8 string and strcat it to the logtext */
1643 strcat(logtext, ", String = \"");
1644 utf_cat(logtext, u);
1645 strcat(logtext, "\"");
1648 if (o->vftbl->class == class_java_lang_Class) {
1649 /* if the object returned is a java.lang.Class
1650 cast it to classinfo structure and get the name
1653 c = (classinfo *) (ptrint) l;
1658 /* if the object returned is not a java.lang.String or
1659 a java.lang.Class just print the name of the class */
1661 u = o->vftbl->class->name;
1664 len = strlen(", Class = \"") + utf_bytes(u) + strlen("\"");
1666 /* realloc memory for string length */
1668 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1670 /* strcat to the logtext */
1672 strcat(logtext, ", Class = \"");
1673 utf_cat_classname(logtext, u);
1674 strcat(logtext, "\"");
1681 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1686 #if SIZEOF_VOID_P == 4
1687 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1689 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1696 /* release memory */
1698 dump_release(dumpsize);
1700 #endif /* !defined(NDEBUG) */
1703 #if defined(ENABLE_CYCLES_STATS)
1704 void builtin_print_cycles_stats(FILE *file)
1706 fprintf(file,"builtin cylce count statistics:\n");
1708 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1709 CYCLES_STATS_PRINT(builtin_new ,file);
1713 #endif /* defined(ENABLE_CYCLES_STATS) */
1716 /*****************************************************************************
1717 MISCELLANEOUS HELPER FUNCTIONS
1718 *****************************************************************************/
1722 /*********** Functions for integer divisions *****************************
1724 On some systems (eg. DEC ALPHA), integer division is not supported by the
1725 CPU. These helper functions implement the missing functionality.
1727 ******************************************************************************/
1729 #if !SUPPORT_DIVISION
1730 s4 builtin_idiv(s4 a, s4 b)
1739 s4 builtin_irem(s4 a, s4 b)
1747 #endif /* !SUPPORT_DIVISION */
1750 /* functions for long arithmetics **********************************************
1752 On systems where 64 bit Integers are not supported by the CPU,
1753 these functions are needed.
1755 ******************************************************************************/
1757 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1758 s8 builtin_ladd(s8 a, s8 b)
1771 s8 builtin_lsub(s8 a, s8 b)
1784 s8 builtin_lneg(s8 a)
1796 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1799 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1800 s8 builtin_lmul(s8 a, s8 b)
1812 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1815 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1816 s8 builtin_ldiv(s8 a, s8 b)
1829 s8 builtin_lrem(s8 a, s8 b)
1841 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1844 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1845 s8 builtin_lshl(s8 a, s4 b)
1858 s8 builtin_lshr(s8 a, s4 b)
1871 s8 builtin_lushr(s8 a, s4 b)
1876 c = ((u8) a) >> (b & 63);
1883 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1886 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1887 s8 builtin_land(s8 a, s8 b)
1900 s8 builtin_lor(s8 a, s8 b)
1913 s8 builtin_lxor(s8 a, s8 b)
1925 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1928 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1929 s4 builtin_lcmp(s8 a, s8 b)
1943 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1946 /* functions for unsupported floating instructions ****************************/
1948 /* used to convert FLT_xxx defines into float values */
1950 static inline float intBitsToFloat(s4 i)
1959 /* used to convert DBL_xxx defines into double values */
1961 static inline float longBitsToDouble(s8 l)
1971 float builtin_fadd(float a, float b)
1973 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1974 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1985 if (copysignf(1.0, a) == copysignf(1.0, b))
1988 return intBitsToFloat(FLT_NAN);
1994 float builtin_fsub(float a, float b)
1996 return builtin_fadd(a, builtin_fneg(b));
2000 float builtin_fmul(float a, float b)
2002 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2003 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2005 if (finitef(b)) return a * b;
2007 if (a == 0) return intBitsToFloat(FLT_NAN);
2008 else return copysignf(b, copysignf(1.0, b)*a);
2013 if (b == 0) return intBitsToFloat(FLT_NAN);
2014 else return copysignf(a, copysignf(1.0, a)*b);
2017 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2023 /* builtin_ddiv ****************************************************************
2025 Implementation as described in VM Spec.
2027 *******************************************************************************/
2029 float builtin_fdiv(float a, float b)
2033 /* If neither value1' nor value2' is NaN, the sign of the result */
2034 /* is positive if both values have the same sign, negative if the */
2035 /* values have different signs. */
2041 /* If either value1' or value2' is NaN, the result is NaN. */
2043 return intBitsToFloat(FLT_NAN);
2046 /* Division of a finite value by an infinity results in a */
2047 /* signed zero, with the sign-producing rule just given. */
2049 /* is sign equal? */
2051 if (copysignf(1.0, a) == copysignf(1.0, b))
2060 /* If either value1' or value2' is NaN, the result is NaN. */
2062 return intBitsToFloat(FLT_NAN);
2064 } else if (finitef(b)) {
2065 /* Division of an infinity by a finite value results in a signed */
2066 /* infinity, with the sign-producing rule just given. */
2068 /* is sign equal? */
2070 if (copysignf(1.0, a) == copysignf(1.0, b))
2071 return intBitsToFloat(FLT_POSINF);
2073 return intBitsToFloat(FLT_NEGINF);
2076 /* Division of an infinity by an infinity results in NaN. */
2078 return intBitsToFloat(FLT_NAN);
2084 float builtin_fneg(float a)
2086 if (isnanf(a)) return a;
2088 if (finitef(a)) return -a;
2089 else return copysignf(a, -copysignf(1.0, a));
2092 #endif /* !SUPPORT_FLOAT */
2095 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2096 s4 builtin_fcmpl(float a, float b)
2098 if (isnanf(a)) return -1;
2099 if (isnanf(b)) return -1;
2100 if (!finitef(a) || !finitef(b)) {
2101 a = finitef(a) ? 0 : copysignf(1.0, a);
2102 b = finitef(b) ? 0 : copysignf(1.0, b);
2104 if (a > b) return 1;
2105 if (a == b) return 0;
2110 s4 builtin_fcmpg(float a, float b)
2112 if (isnanf(a)) return 1;
2113 if (isnanf(b)) return 1;
2114 if (!finitef(a) || !finitef(b)) {
2115 a = finitef(a) ? 0 : copysignf(1.0, a);
2116 b = finitef(b) ? 0 : copysignf(1.0, b);
2118 if (a > b) return 1;
2119 if (a == b) return 0;
2122 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2125 float builtin_frem(float a, float b)
2131 /* functions for unsupported double instructions ******************************/
2134 double builtin_dadd(double a, double b)
2136 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2137 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2139 if (finite(b)) return a + b;
2143 if (finite(b)) return a;
2145 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2146 else return longBitsToDouble(DBL_NAN);
2152 double builtin_dsub(double a, double b)
2154 return builtin_dadd(a, builtin_dneg(b));
2158 double builtin_dmul(double a, double b)
2160 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2161 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2163 if (finite(b)) return a * b;
2165 if (a == 0) return longBitsToDouble(DBL_NAN);
2166 else return copysign(b, copysign(1.0, b) * a);
2171 if (b == 0) return longBitsToDouble(DBL_NAN);
2172 else return copysign(a, copysign(1.0, a) * b);
2175 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2181 /* builtin_ddiv ****************************************************************
2183 Implementation as described in VM Spec.
2185 *******************************************************************************/
2187 double builtin_ddiv(double a, double b)
2191 /* If neither value1' nor value2' is NaN, the sign of the result */
2192 /* is positive if both values have the same sign, negative if the */
2193 /* values have different signs. */
2199 /* If either value1' or value2' is NaN, the result is NaN. */
2201 return longBitsToDouble(DBL_NAN);
2204 /* Division of a finite value by an infinity results in a */
2205 /* signed zero, with the sign-producing rule just given. */
2207 /* is sign equal? */
2209 if (copysign(1.0, a) == copysign(1.0, b))
2218 /* If either value1' or value2' is NaN, the result is NaN. */
2220 return longBitsToDouble(DBL_NAN);
2222 } else if (finite(b)) {
2223 /* Division of an infinity by a finite value results in a signed */
2224 /* infinity, with the sign-producing rule just given. */
2226 /* is sign equal? */
2228 if (copysign(1.0, a) == copysign(1.0, b))
2229 return longBitsToDouble(DBL_POSINF);
2231 return longBitsToDouble(DBL_NEGINF);
2234 /* Division of an infinity by an infinity results in NaN. */
2236 return longBitsToDouble(DBL_NAN);
2242 /* builtin_dneg ****************************************************************
2244 Implemented as described in VM Spec.
2246 *******************************************************************************/
2248 double builtin_dneg(double a)
2251 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2258 /* If the operand is a zero, the result is the zero of opposite */
2264 /* If the operand is an infinity, the result is the infinity of */
2265 /* opposite sign. */
2267 return copysign(a, -copysign(1.0, a));
2271 #endif /* !SUPPORT_DOUBLE */
2274 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2275 s4 builtin_dcmpl(double a, double b)
2277 if (isnan(a)) return -1;
2278 if (isnan(b)) return -1;
2279 if (!finite(a) || !finite(b)) {
2280 a = finite(a) ? 0 : copysign(1.0, a);
2281 b = finite(b) ? 0 : copysign(1.0, b);
2283 if (a > b) return 1;
2284 if (a == b) return 0;
2289 s4 builtin_dcmpg(double a, double b)
2291 if (isnan(a)) return 1;
2292 if (isnan(b)) return 1;
2293 if (!finite(a) || !finite(b)) {
2294 a = finite(a) ? 0 : copysign(1.0, a);
2295 b = finite(b) ? 0 : copysign(1.0, b);
2297 if (a > b) return 1;
2298 if (a == b) return 0;
2301 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2304 double builtin_drem(double a, double b)
2310 /* conversion operations ******************************************************/
2313 s8 builtin_i2l(s4 i)
2325 s4 builtin_l2i(s8 l)
2336 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2337 float builtin_i2f(s4 a)
2339 float f = (float) a;
2342 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2345 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2346 double builtin_i2d(s4 a)
2348 double d = (double) a;
2351 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2354 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2355 float builtin_l2f(s8 a)
2358 float f = (float) a;
2364 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2367 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2368 double builtin_l2d(s8 a)
2371 double d = (double) a;
2377 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2380 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2381 s4 builtin_f2i(float a)
2385 i = builtin_d2i((double) a);
2396 if (a < (-2147483648))
2397 return (-2147483648);
2400 f = copysignf((float) 1.0, a);
2403 return (-2147483648); */
2405 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2408 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2409 s8 builtin_f2l(float a)
2413 l = builtin_d2l((double) a);
2420 if (a > 9223372036854775807L)
2421 return 9223372036854775807L;
2422 if (a < (-9223372036854775808L))
2423 return (-9223372036854775808L);
2428 f = copysignf((float) 1.0, a);
2430 return 9223372036854775807L;
2431 return (-9223372036854775808L); */
2433 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2436 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2437 s4 builtin_d2i(double a)
2442 if (a >= 2147483647)
2444 if (a <= (-2147483647-1))
2445 return (-2147483647-1);
2450 d = copysign(1.0, a);
2453 return (-2147483647-1);
2455 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2458 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2459 s8 builtin_d2l(double a)
2464 if (a >= 9223372036854775807LL)
2465 return 9223372036854775807LL;
2466 if (a <= (-9223372036854775807LL-1))
2467 return (-9223372036854775807LL-1);
2472 d = copysign(1.0, a);
2474 return 9223372036854775807LL;
2475 return (-9223372036854775807LL-1);
2477 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2480 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2481 double builtin_f2d(float a)
2483 if (finitef(a)) return (double) a;
2486 return longBitsToDouble(DBL_NAN);
2488 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2492 float builtin_d2f(double a)
2498 return intBitsToFloat(FLT_NAN);
2500 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2503 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2506 /* builtin_clone_array *********************************************************
2508 Wrapper function for cloning arrays.
2510 *******************************************************************************/
2512 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2514 java_arrayheader *ah;
2515 java_lang_Cloneable *c;
2517 c = (java_lang_Cloneable *) o;
2519 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2525 /* builtin_asm_get_exceptionptrptr *********************************************
2527 this is a wrapper for calls from asmpart
2529 *******************************************************************************/
2531 #if defined(ENABLE_THREADS)
2532 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2534 return builtin_get_exceptionptrptr();
2540 * These are local overrides for various environment variables in Emacs.
2541 * Please do not remove this and leave it at the end of the file, where
2542 * Emacs will automagically detect them.
2543 * ---------------------------------------------------------------------
2546 * indent-tabs-mode: t
2550 * vim:noexpandtab:sw=4:ts=4: