1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007 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 Contains C functions for JavaVM Instructions that cannot be
26 translated to machine language directly. Consequently, the
27 generated machine code for these instructions contains function
28 calls instead of machine instructions, using the C calling
31 $Id: builtin.c 7535 2007-03-17 12:57:32Z twisti $
50 #include "fdlibm/fdlibm.h"
51 #if defined(__CYGWIN__) && defined(Bias)
55 #include "mm/gc-common.h"
56 #include "mm/memory.h"
58 #include "native/jni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #if defined(ENABLE_THREADS)
63 # include "threads/native/lock.h"
66 #include "toolbox/logging.h"
67 #include "toolbox/util.h"
69 #include "vm/builtin.h"
70 #include "vm/cycles-stats.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/stringlocal.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/options.h"
82 #include "vmcore/rt-timing.h"
85 /* include builtin tables *****************************************************/
87 #include "vm/builtintable.inc"
90 CYCLES_STATS_DECLARE(builtin_new ,100,5)
91 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
93 /* builtintable_init ***********************************************************
95 Parse the descriptors of builtin functions and create the parsed
98 *******************************************************************************/
100 static bool builtintable_init(void)
102 descriptor_pool *descpool;
104 builtintable_entry *bte;
106 /* mark start of dump memory area */
108 dumpsize = dump_size();
110 /* create a new descriptor pool */
112 descpool = descriptor_pool_new(class_java_lang_Object);
114 /* add some entries we need */
116 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
119 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
122 /* first add all descriptors to the pool */
124 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
125 /* create a utf8 string from descriptor */
127 bte->descriptor = utf_new_char(bte->cdescriptor);
129 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
130 /* release dump area */
132 dump_release(dumpsize);
138 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
139 bte->descriptor = utf_new_char(bte->cdescriptor);
141 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
142 dump_release(dumpsize);
147 for (bte = builtintable_function; bte->fp != NULL; bte++) {
148 bte->classname = utf_new_char(bte->cclassname);
149 bte->name = utf_new_char(bte->cname);
150 bte->descriptor = utf_new_char(bte->cdescriptor);
152 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
153 dump_release(dumpsize);
158 /* create the class reference table */
160 (void) descriptor_pool_create_classrefs(descpool, NULL);
162 /* allocate space for the parsed descriptors */
164 descriptor_pool_alloc_parsed_descriptors(descpool);
166 /* now parse all descriptors */
168 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
169 /* parse the descriptor, builtin is always static (no `this' pointer) */
171 bte->md = descriptor_pool_parse_method_descriptor(descpool,
176 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
177 bte->md = descriptor_pool_parse_method_descriptor(descpool,
182 for (bte = builtintable_function; bte->fp != NULL; bte++) {
183 bte->md = descriptor_pool_parse_method_descriptor(descpool,
188 /* release dump area */
190 dump_release(dumpsize);
196 /* builtintable_comparator *****************************************************
198 qsort comparator for the automatic builtin table.
200 *******************************************************************************/
202 static int builtintable_comparator(const void *a, const void *b)
204 builtintable_entry *bte1;
205 builtintable_entry *bte2;
207 bte1 = (builtintable_entry *) a;
208 bte2 = (builtintable_entry *) b;
210 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
214 /* builtintable_sort_automatic *************************************************
216 Sorts the automatic builtin table.
218 *******************************************************************************/
220 static void builtintable_sort_automatic(void)
224 /* calculate table size statically (`- 1' comment see builtintable.inc) */
226 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
228 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
229 builtintable_comparator);
233 /* builtin_init ****************************************************************
235 Initialize the global table of builtin functions.
237 *******************************************************************************/
239 bool builtin_init(void)
241 /* initialize the builtin tables */
243 if (!builtintable_init())
246 /* sort builtin tables */
248 builtintable_sort_automatic();
254 /* builtintable_get_internal ***************************************************
256 Finds an entry in the builtintable for internal functions and
257 returns the a pointer to the structure.
259 *******************************************************************************/
261 builtintable_entry *builtintable_get_internal(functionptr fp)
263 builtintable_entry *bte;
265 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
274 /* builtintable_get_automatic **************************************************
276 Finds an entry in the builtintable for functions which are replaced
277 automatically and returns the a pointer to the structure.
279 *******************************************************************************/
281 builtintable_entry *builtintable_get_automatic(s4 opcode)
283 builtintable_entry *first;
284 builtintable_entry *last;
285 builtintable_entry *middle;
289 /* calculate table size statically (`- 1' comment see builtintable.inc) */
291 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
293 first = builtintable_automatic;
294 last = builtintable_automatic + entries;
296 while (entries > 0) {
298 middle = first + half;
300 if (middle->opcode < opcode) {
307 return (first != last ? first : NULL);
311 /* builtintable_replace_function ***********************************************
315 *******************************************************************************/
317 #if defined(ENABLE_JIT)
318 bool builtintable_replace_function(void *iptr_)
321 builtintable_entry *bte;
324 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
326 /* get name and descriptor of the function */
329 case ICMD_INVOKESTATIC:
330 /* The instruction MUST be resolved, otherwise we run into
331 lazy loading troubles. Anyway, we should/can only replace
332 very VM-close functions. */
334 if (INSTRUCTION_IS_UNRESOLVED(iptr))
337 mr = iptr->sx.s23.s3.fmiref;
344 /* search the function table */
346 for (bte = builtintable_function; bte->fp != NULL; bte++) {
347 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
348 (mr->name == bte->name) &&
349 (mr->descriptor == bte->descriptor)) {
351 /* set the values in the instruction */
353 iptr->opc = bte->opcode;
354 iptr->sx.s23.s3.bte = bte;
355 if (bte->checkexception)
356 iptr->flags.bits |= INS_FLAG_CHECK;
358 iptr->flags.bits &= ~INS_FLAG_CHECK;
366 #endif /* defined(ENABLE_JIT) */
369 /*****************************************************************************
371 *****************************************************************************/
375 /* builtin_isanysubclass ********************************************************
377 Checks a subclass relation between two classes. Implemented
378 interfaces are interpreted as super classes.
380 Return value: 1 ... sub is subclass of super
383 ********************************************************************************/
385 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
388 castinfo classvalues;
390 /* This is the trivial case. */
395 /* Check for interfaces. */
397 if (super->flags & ACC_INTERFACE) {
398 res = (sub->vftbl->interfacetablelength > super->index) &&
399 (sub->vftbl->interfacetable[-super->index] != NULL);
402 /* java.lang.Object is the only super_class_ of any interface */
404 if (sub->flags & ACC_INTERFACE)
405 return (super == class_java_lang_Object);
407 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
409 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
410 (u4) classvalues.super_diffval;
417 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
421 castinfo classvalues;
426 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
428 if ((base = classvalues.super_baseval) <= 0) {
429 /* super is an interface */
431 res = (sub->interfacetablelength > -base) &&
432 (sub->interfacetable[base] != NULL);
435 /* java.lang.Object is the only super_class_ of any interface */
437 if (classvalues.sub_baseval <= 0)
438 return classvalues.super_baseval == 1;
440 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
441 <= (u4) classvalues.super_diffval;
448 /****************** function: builtin_instanceof *****************************
450 Checks if an object is an instance of some given class (or subclass of
451 that class). If class is an interface, checks if the interface is
453 Return value: 1 ... obj is an instance of class or implements the interface
454 0 ... otherwise or if obj == NULL
456 *****************************************************************************/
458 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
463 return builtin_isanysubclass(obj->vftbl->class, class);
468 /**************** function: builtin_checkcast *******************************
470 The same as builtin_instanceof except that 1 is returned when
473 ****************************************************************************/
475 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
480 if (builtin_isanysubclass(obj->vftbl->class, class))
487 /* builtin_descriptorscompatible ***********************************************
489 Checks if two array type descriptors are assignment compatible
491 Return value: 1 ... target = desc is possible
494 *******************************************************************************/
496 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
497 arraydescriptor *target)
502 if (desc->arraytype != target->arraytype)
505 if (desc->arraytype != ARRAYTYPE_OBJECT)
508 /* {both arrays are arrays of references} */
510 if (desc->dimension == target->dimension) {
511 /* an array which contains elements of interface types is
512 allowed to be casted to Object (JOWENN)*/
514 if ((desc->elementvftbl->baseval < 0) &&
515 (target->elementvftbl->baseval == 1))
518 return builtin_isanysubclass_vftbl(desc->elementvftbl,
519 target->elementvftbl);
522 if (desc->dimension < target->dimension)
525 /* {desc has higher dimension than target} */
527 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
528 target->elementvftbl);
532 /* builtin_arraycheckcast ******************************************************
534 Checks if an object is really a subtype of the requested array
535 type. The object has to be an array to begin with. For simple
536 arrays (int, short, double, etc.) the types have to match exactly.
537 For arrays of objects, the type of elements in the array has to be
538 a subtype (or the same type) of the requested element type. For
539 arrays of arrays (which in turn can again be arrays of arrays), the
540 types at the lowest level have to satisfy the corresponding sub
543 *******************************************************************************/
545 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
547 arraydescriptor *desc;
552 if ((desc = o->vftbl->arraydesc) == NULL)
555 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
559 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
564 return builtin_arraycheckcast(o, targetclass);
568 /* builtin_throw_exception *****************************************************
570 Sets the exceptionptr with the thrown exception and prints some
571 debugging information. Called from asm_vm_call_method.
573 *******************************************************************************/
575 void *builtin_throw_exception(java_objectheader *xptr)
578 java_lang_Throwable *t;
584 t = (java_lang_Throwable *) xptr;
586 /* calculate message length */
588 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
592 utf_bytes(xptr->vftbl->class->name);
593 if (t->detailMessage) {
594 logtextlen += strlen(": ") +
595 u2_utflength(t->detailMessage->value->data
596 + t->detailMessage->offset,
597 t->detailMessage->count);
601 logtextlen += strlen("(nil)");
604 /* allocate memory */
606 dumpsize = dump_size();
608 logtext = DMNEW(char, logtextlen);
610 strcpy(logtext, "Builtin exception thrown: ");
613 utf_cat_classname(logtext, xptr->vftbl->class->name);
615 if (t->detailMessage) {
618 buf = javastring_tochar((java_objectheader *) t->detailMessage);
619 strcat(logtext, ": ");
620 strcat(logtext, buf);
621 MFREE(buf, char, strlen(buf) + 1);
625 strcat(logtext, "(nil)");
632 dump_release(dumpsize);
634 #endif /* !defined(NDEBUG) */
636 /* actually set the exception */
638 exceptions_set_exception(xptr);
640 /* Return a NULL pointer. This is required for vm_call_method to
641 check for an exception. This is for convenience. */
647 /* builtin_canstore ************************************************************
649 Checks, if an object can be stored in an array.
651 Return value: 1 ... possible
654 *******************************************************************************/
656 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
658 arraydescriptor *desc;
659 arraydescriptor *valuedesc;
660 vftbl_t *componentvftbl;
663 castinfo classvalues;
668 /* The following is guaranteed (by verifier checks):
670 * *) oa->...vftbl->arraydesc != NULL
671 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
672 * *) o->vftbl is not an interface vftbl
675 desc = oa->header.objheader.vftbl->arraydesc;
676 componentvftbl = desc->componentvftbl;
677 valuevftbl = o->vftbl;
679 if ((desc->dimension - 1) == 0) {
682 /* {oa is a one-dimensional array} */
683 /* {oa is an array of references} */
685 if (valuevftbl == componentvftbl)
688 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
690 if ((base = classvalues.super_baseval) <= 0)
691 /* an array of interface references */
692 return (valuevftbl->interfacetablelength > -base &&
693 valuevftbl->interfacetable[base] != NULL);
695 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
696 <= (unsigned) classvalues.super_diffval);
701 /* {oa has dimension > 1} */
702 /* {componentvftbl->arraydesc != NULL} */
704 /* check if o is an array */
706 if ((valuedesc = valuevftbl->arraydesc) == NULL)
709 /* {o is an array} */
711 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
715 /* This is an optimized version where a is guaranteed to be one-dimensional */
716 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
718 arraydescriptor *desc;
719 vftbl_t *elementvftbl;
723 castinfo classvalues;
727 /* The following is guaranteed (by verifier checks):
729 * *) a->...vftbl->arraydesc != NULL
730 * *) a->...vftbl->arraydesc->elementvftbl != NULL
731 * *) a->...vftbl->arraydesc->dimension == 1
732 * *) o->vftbl is not an interface vftbl
735 desc = a->header.objheader.vftbl->arraydesc;
736 elementvftbl = desc->elementvftbl;
737 valuevftbl = o->vftbl;
739 /* {a is a one-dimensional array} */
741 if (valuevftbl == elementvftbl)
744 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
746 if ((base = classvalues.super_baseval) <= 0)
747 /* an array of interface references */
748 return (valuevftbl->interfacetablelength > -base &&
749 valuevftbl->interfacetable[base] != NULL);
751 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
752 <= (unsigned) classvalues.super_diffval;
758 /* This is an optimized version where a is guaranteed to be a
759 * one-dimensional array of a class type */
760 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
762 vftbl_t *elementvftbl;
765 castinfo classvalues;
769 /* The following is guaranteed (by verifier checks):
771 * *) a->...vftbl->arraydesc != NULL
772 * *) a->...vftbl->arraydesc->elementvftbl != NULL
773 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
774 * *) a->...vftbl->arraydesc->dimension == 1
775 * *) o->vftbl is not an interface vftbl
778 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
779 valuevftbl = o->vftbl;
781 /* {a is a one-dimensional array} */
783 if (valuevftbl == elementvftbl)
786 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
788 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
789 <= (unsigned) classvalues.super_diffval;
795 /* builtin_new *****************************************************************
797 Creates a new instance of class c on the heap.
799 Return value: pointer to the object or NULL if no memory is
802 *******************************************************************************/
804 java_objectheader *builtin_new(classinfo *c)
806 java_objectheader *o;
807 #if defined(ENABLE_RT_TIMING)
808 struct timespec time_start, time_end;
810 #if defined(ENABLE_CYCLES_STATS)
811 u8 cycles_start, cycles_end;
814 RT_TIMING_GET_TIME(time_start);
815 CYCLES_STATS_GET(cycles_start);
817 /* is the class loaded */
819 assert(c->state & CLASS_LOADED);
821 /* check if we can instantiate this class */
823 if (c->flags & ACC_ABSTRACT) {
824 exceptions_throw_instantiationerror(c);
828 /* is the class linked */
830 if (!(c->state & CLASS_LINKED))
834 if (!(c->state & CLASS_INITIALIZED)) {
837 log_message_class("Initialize class (from builtin_new): ", c);
840 if (!initialize_class(c))
844 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
852 #if defined(ENABLE_THREADS)
853 lock_init_object_lock(o);
856 CYCLES_STATS_GET(cycles_end);
857 RT_TIMING_GET_TIME(time_end);
859 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
860 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
866 /* builtin_newarray ************************************************************
868 Creates an array with the given vftbl on the heap. This function
869 takes as class argument an array class.
871 Return value: pointer to the array or NULL if no memory is available
873 *******************************************************************************/
875 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
877 arraydescriptor *desc;
882 #if defined(ENABLE_RT_TIMING)
883 struct timespec time_start, time_end;
886 RT_TIMING_GET_TIME(time_start);
888 desc = arrayclass->vftbl->arraydesc;
889 dataoffset = desc->dataoffset;
890 componentsize = desc->componentsize;
893 exceptions_throw_negativearraysizeexception();
897 actualsize = dataoffset + size * componentsize;
899 /* check for overflow */
901 if (((u4) actualsize) < ((u4) size)) {
902 exceptions_throw_outofmemoryerror();
906 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
911 a->objheader.vftbl = arrayclass->vftbl;
913 #if defined(ENABLE_THREADS)
914 lock_init_object_lock(&a->objheader);
919 RT_TIMING_GET_TIME(time_end);
920 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
926 /* builtin_anewarray ***********************************************************
928 Creates an array of references to the given class type on the heap.
930 Return value: pointer to the array or NULL if no memory is
933 *******************************************************************************/
935 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
937 classinfo *arrayclass;
939 /* is class loaded */
941 assert(componentclass->state & CLASS_LOADED);
943 /* is class linked */
945 if (!(componentclass->state & CLASS_LINKED))
946 if (!link_class(componentclass))
949 arrayclass = class_array_of(componentclass, true);
954 return (java_objectarray *) builtin_newarray(size, arrayclass);
958 /* builtin_newarray_boolean ****************************************************
960 Creates an array of bytes on the heap. The array is designated as
961 an array of booleans (important for casts)
963 Return value: pointer to the array or NULL if no memory is
966 *******************************************************************************/
968 java_booleanarray *builtin_newarray_boolean(s4 size)
970 return (java_booleanarray *)
971 builtin_newarray(size,
972 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
976 /* builtin_newarray_byte *******************************************************
978 Creates an array of 8 bit Integers on the heap.
980 Return value: pointer to the array or NULL if no memory is
983 *******************************************************************************/
985 java_bytearray *builtin_newarray_byte(s4 size)
987 return (java_bytearray *)
988 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
992 /* builtin_newarray_char *******************************************************
994 Creates an array of characters on the heap.
996 Return value: pointer to the array or NULL if no memory is
999 *******************************************************************************/
1001 java_chararray *builtin_newarray_char(s4 size)
1003 return (java_chararray *)
1004 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1008 /* builtin_newarray_short ******************************************************
1010 Creates an array of 16 bit Integers on the heap.
1012 Return value: pointer to the array or NULL if no memory is
1015 *******************************************************************************/
1017 java_shortarray *builtin_newarray_short(s4 size)
1019 return (java_shortarray *)
1020 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1024 /* builtin_newarray_int ********************************************************
1026 Creates an array of 32 bit Integers on the heap.
1028 Return value: pointer to the array or NULL if no memory is
1031 *******************************************************************************/
1033 java_intarray *builtin_newarray_int(s4 size)
1035 return (java_intarray *)
1036 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1040 /* builtin_newarray_long *******************************************************
1042 Creates an array of 64 bit Integers on the heap.
1044 Return value: pointer to the array or NULL if no memory is
1047 *******************************************************************************/
1049 java_longarray *builtin_newarray_long(s4 size)
1051 return (java_longarray *)
1052 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1056 /* builtin_newarray_float ******************************************************
1058 Creates an array of 32 bit IEEE floats on the heap.
1060 Return value: pointer to the array or NULL if no memory is
1063 *******************************************************************************/
1065 java_floatarray *builtin_newarray_float(s4 size)
1067 return (java_floatarray *)
1068 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1072 /* builtin_newarray_double *****************************************************
1074 Creates an array of 64 bit IEEE floats on the heap.
1076 Return value: pointer to the array or NULL if no memory is
1079 *******************************************************************************/
1081 java_doublearray *builtin_newarray_double(s4 size)
1083 return (java_doublearray *)
1084 builtin_newarray(size,
1085 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1089 /* builtin_multianewarray_intern ***********************************************
1091 Creates a multi-dimensional array on the heap. The dimensions are
1092 passed in an array of longs.
1095 n............number of dimensions to create
1096 arrayvftbl...vftbl of the array class
1097 dims.........array containing the size of each dimension to create
1099 Return value: pointer to the array or NULL if no memory is
1102 ******************************************************************************/
1104 static java_arrayheader *builtin_multianewarray_intern(int n,
1105 classinfo *arrayclass,
1109 java_arrayheader *a;
1110 classinfo *componentclass;
1113 /* create this dimension */
1115 size = (s4) dims[0];
1116 a = builtin_newarray(size, arrayclass);
1121 /* if this is the last dimension return */
1126 /* get the class of the components to create */
1128 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1130 /* The verifier guarantees that the dimension count is in the range. */
1132 /* create the component arrays */
1134 for (i = 0; i < size; i++) {
1135 java_arrayheader *ea =
1136 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1137 /* we save an s4 to a s8 slot, 8-byte aligned */
1139 builtin_multianewarray_intern(n, componentclass, dims + 2);
1141 builtin_multianewarray_intern(n, componentclass, dims + 1);
1147 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1154 /* builtin_multianewarray ******************************************************
1156 Wrapper for builtin_multianewarray_intern which checks all
1157 dimensions before we start allocating.
1159 ******************************************************************************/
1161 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1167 /* check all dimensions before doing anything */
1169 for (i = 0; i < n; i++) {
1170 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1171 /* we save an s4 to a s8 slot, 8-byte aligned */
1172 size = (s4) dims[i * 2];
1174 size = (s4) dims[i];
1178 exceptions_throw_negativearraysizeexception();
1183 /* now call the real function */
1185 return builtin_multianewarray_intern(n, arrayclass, dims);
1189 /*****************************************************************************
1192 Various functions for printing a message at method entry or exit (for
1195 *****************************************************************************/
1197 #if !defined(NDEBUG)
1198 static s4 methodindent = 0;
1199 static u4 callcount = 0;
1201 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1211 if (opt_verbosecall && indent)
1214 /* calculate message length */
1218 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1221 logtextlen = strlen("Some Throwable");
1224 logtextlen += strlen(" thrown in ");
1228 utf_bytes(m->class->name) +
1230 utf_bytes(m->name) +
1231 utf_bytes(m->descriptor) +
1232 strlen("(NOSYNC,NATIVE");
1234 #if SIZEOF_VOID_P == 8
1236 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1238 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1241 if (m->class->sourcefile == NULL)
1242 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1244 logtextlen += utf_bytes(m->class->sourcefile);
1246 logtextlen += strlen(":65536)");
1250 logtextlen += strlen("call_java_method");
1253 logtextlen += strlen("0");
1255 /* allocate memory */
1257 dumpsize = dump_size();
1259 logtext = DMNEW(char, logtextlen);
1262 strcpy(logtext, "Exception ");
1263 utf_cat_classname(logtext, xptr->vftbl->class->name);
1266 strcpy(logtext, "Some Throwable");
1269 strcat(logtext, " thrown in ");
1272 utf_cat_classname(logtext, m->class->name);
1273 strcat(logtext, ".");
1274 utf_cat(logtext, m->name);
1275 utf_cat(logtext, m->descriptor);
1277 if (m->flags & ACC_SYNCHRONIZED)
1278 strcat(logtext, "(SYNC");
1280 strcat(logtext, "(NOSYNC");
1282 if (m->flags & ACC_NATIVE) {
1283 strcat(logtext, ",NATIVE");
1287 #if SIZEOF_VOID_P == 8
1288 sprintf(logtext + strlen(logtext),
1289 ")(0x%016lx) at position 0x%016lx",
1290 (ptrint) code->entrypoint, (ptrint) pos);
1292 sprintf(logtext + strlen(logtext),
1293 ")(0x%08x) at position 0x%08x",
1294 (ptrint) code->entrypoint, (ptrint) pos);
1299 /* XXX preliminary: This should get the actual codeinfo */
1300 /* in which the exception happened. */
1303 #if SIZEOF_VOID_P == 8
1304 sprintf(logtext + strlen(logtext),
1305 ")(0x%016lx) at position 0x%016lx (",
1306 (ptrint) code->entrypoint, (ptrint) pos);
1308 sprintf(logtext + strlen(logtext),
1309 ")(0x%08x) at position 0x%08x (",
1310 (ptrint) code->entrypoint, (ptrint) pos);
1313 if (m->class->sourcefile == NULL)
1314 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1316 utf_cat(logtext, m->class->sourcefile);
1318 sprintf(logtext + strlen(logtext), ":%d)", 0);
1322 strcat(logtext, "call_java_method");
1326 /* release memory */
1328 dump_release(dumpsize);
1332 #endif /* !defined(NDEBUG) */
1335 /* builtin_print_argument ******************************************************
1337 Prints arguments and return values for the call trace.
1339 *******************************************************************************/
1341 #if !defined(NDEBUG)
1342 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1343 typedesc *paramtype, s8 value)
1346 java_objectheader *o;
1347 java_lang_String *s;
1352 switch (paramtype->type) {
1355 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1360 #if SIZEOF_VOID_P == 4
1361 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1363 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1369 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1374 #if SIZEOF_VOID_P == 4
1375 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1377 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1382 #if SIZEOF_VOID_P == 4
1383 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1385 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1388 /* cast to java.lang.Object */
1390 o = (java_objectheader *) (ptrint) value;
1392 /* check return argument for java.lang.Class or java.lang.String */
1395 if (o->vftbl->class == class_java_lang_String) {
1396 /* get java.lang.String object and the length of the
1399 s = (java_lang_String *) o;
1401 u = javastring_toutf(s, false);
1403 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1405 /* realloc memory for string length */
1407 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1410 /* convert to utf8 string and strcat it to the logtext */
1412 strcat(logtext, " (String = \"");
1413 utf_cat(logtext, u);
1414 strcat(logtext, "\")");
1417 if (o->vftbl->class == class_java_lang_Class) {
1418 /* if the object returned is a java.lang.Class
1419 cast it to classinfo structure and get the name
1422 c = (classinfo *) o;
1427 /* if the object returned is not a java.lang.String or
1428 a java.lang.Class just print the name of the class */
1430 u = o->vftbl->class->name;
1433 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1435 /* realloc memory for string length */
1437 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1440 /* strcat to the logtext */
1442 strcat(logtext, " (Class = \"");
1443 utf_cat_classname(logtext, u);
1444 strcat(logtext, "\")");
1451 #endif /* !defined(NDEBUG) */
1454 /* builtin_verbosecall_enter ***************************************************
1456 Print method call with arguments for -verbose:call.
1458 *******************************************************************************/
1460 #if !defined(NDEBUG)
1462 #ifdef TRACE_ARGS_NUM
1463 void builtin_verbosecall_enter(s8 a0, s8 a1,
1464 # if TRACE_ARGS_NUM >= 4
1467 # if TRACE_ARGS_NUM >= 6
1470 # if TRACE_ARGS_NUM == 8
1484 /* calculate message length */
1487 strlen("4294967295 ") +
1488 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1490 strlen("called: ") +
1491 utf_bytes(m->class->name) +
1493 utf_bytes(m->name) +
1494 utf_bytes(m->descriptor);
1496 /* Actually it's not possible to have all flags printed, but:
1501 strlen(" PRIVATE") +
1502 strlen(" PROTECTED") +
1505 strlen(" SYNCHRONIZED") +
1506 strlen(" VOLATILE") +
1507 strlen(" TRANSIENT") +
1509 strlen(" INTERFACE") +
1510 strlen(" ABSTRACT");
1512 /* add maximal argument length */
1516 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1517 strlen("...(255)") +
1520 /* allocate memory */
1522 dumpsize = dump_size();
1524 logtext = DMNEW(char, logtextlen);
1528 sprintf(logtext, "%10d ", callcount);
1529 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1531 pos = strlen(logtext);
1533 for (i = 0; i < methodindent; i++)
1534 logtext[pos++] = '\t';
1536 strcpy(logtext + pos, "called: ");
1538 utf_cat_classname(logtext, m->class->name);
1539 strcat(logtext, ".");
1540 utf_cat(logtext, m->name);
1541 utf_cat(logtext, m->descriptor);
1543 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1544 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1545 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1546 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1547 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1548 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1549 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1550 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1551 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1552 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1553 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1555 strcat(logtext, "(");
1557 if (md->paramcount >= 1) {
1558 logtext = builtin_print_argument(logtext, &logtextlen,
1559 &md->paramtypes[0], a0);
1562 if (md->paramcount >= 2) {
1563 strcat(logtext, ", ");
1565 logtext = builtin_print_argument(logtext, &logtextlen,
1566 &md->paramtypes[1], a1);
1569 #if TRACE_ARGS_NUM >= 4
1570 if (md->paramcount >= 3) {
1571 strcat(logtext, ", ");
1573 logtext = builtin_print_argument(logtext, &logtextlen,
1574 &md->paramtypes[2], a2);
1577 if (md->paramcount >= 4) {
1578 strcat(logtext, ", ");
1580 logtext = builtin_print_argument(logtext, &logtextlen,
1581 &md->paramtypes[3], a3);
1585 #if TRACE_ARGS_NUM >= 6
1586 if (md->paramcount >= 5) {
1587 strcat(logtext, ", ");
1589 logtext = builtin_print_argument(logtext, &logtextlen,
1590 &md->paramtypes[4], a4);
1593 if (md->paramcount >= 6) {
1594 strcat(logtext, ", ");
1596 logtext = builtin_print_argument(logtext, &logtextlen,
1597 &md->paramtypes[5], a5);
1601 #if TRACE_ARGS_NUM == 8
1602 if (md->paramcount >= 7) {
1603 strcat(logtext, ", ");
1605 logtext = builtin_print_argument(logtext, &logtextlen,
1606 &md->paramtypes[6], a6);
1609 if (md->paramcount >= 8) {
1610 strcat(logtext, ", ");
1612 logtext = builtin_print_argument(logtext, &logtextlen,
1613 &md->paramtypes[7], a7);
1617 if (md->paramcount > 8) {
1618 sprintf(logtext + strlen(logtext), ", ...(%d)",
1619 md->paramcount - TRACE_ARGS_NUM);
1622 strcat(logtext, ")");
1626 /* release memory */
1628 dump_release(dumpsize);
1633 #endif /* !defined(NDEBUG) */
1636 /* builtin_verbosecall_exit ****************************************************
1638 Print method exit for -verbose:call.
1640 *******************************************************************************/
1642 #if !defined(NDEBUG)
1643 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1655 /* calculate message length */
1658 strlen("4294967295 ") +
1659 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1661 strlen("finished: ") +
1662 utf_bytes(m->class->name) +
1664 utf_bytes(m->name) +
1665 utf_bytes(m->descriptor) +
1666 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1668 /* add maximal argument length */
1670 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1672 /* allocate memory */
1674 dumpsize = dump_size();
1676 logtext = DMNEW(char, logtextlen);
1678 /* outdent the log message */
1683 log_text("WARNING: unmatched methodindent--");
1685 /* generate the message */
1687 sprintf(logtext, " ");
1688 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1690 pos = strlen(logtext);
1692 for (i = 0; i < methodindent; i++)
1693 logtext[pos++] = '\t';
1695 strcpy(logtext + pos, "finished: ");
1696 utf_cat_classname(logtext, m->class->name);
1697 strcat(logtext, ".");
1698 utf_cat(logtext, m->name);
1699 utf_cat(logtext, m->descriptor);
1701 if (!IS_VOID_TYPE(md->returntype.type)) {
1702 strcat(logtext, "->");
1704 switch (md->returntype.type) {
1721 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1726 /* release memory */
1728 dump_release(dumpsize);
1730 #endif /* !defined(NDEBUG) */
1733 #if defined(ENABLE_CYCLES_STATS)
1734 void builtin_print_cycles_stats(FILE *file)
1736 fprintf(file,"builtin cylce count statistics:\n");
1738 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1739 CYCLES_STATS_PRINT(builtin_new ,file);
1743 #endif /* defined(ENABLE_CYCLES_STATS) */
1746 /*****************************************************************************
1747 MISCELLANEOUS HELPER FUNCTIONS
1748 *****************************************************************************/
1752 /*********** Functions for integer divisions *****************************
1754 On some systems (eg. DEC ALPHA), integer division is not supported by the
1755 CPU. These helper functions implement the missing functionality.
1757 ******************************************************************************/
1759 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1760 s4 builtin_idiv(s4 a, s4 b)
1769 s4 builtin_irem(s4 a, s4 b)
1777 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1780 /* functions for long arithmetics **********************************************
1782 On systems where 64 bit Integers are not supported by the CPU,
1783 these functions are needed.
1785 ******************************************************************************/
1787 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1788 s8 builtin_ladd(s8 a, s8 b)
1801 s8 builtin_lsub(s8 a, s8 b)
1814 s8 builtin_lneg(s8 a)
1826 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1829 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1830 s8 builtin_lmul(s8 a, s8 b)
1842 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1845 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1846 s8 builtin_ldiv(s8 a, s8 b)
1859 s8 builtin_lrem(s8 a, s8 b)
1871 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1874 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1875 s8 builtin_lshl(s8 a, s4 b)
1888 s8 builtin_lshr(s8 a, s4 b)
1901 s8 builtin_lushr(s8 a, s4 b)
1906 c = ((u8) a) >> (b & 63);
1913 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1916 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1917 s8 builtin_land(s8 a, s8 b)
1930 s8 builtin_lor(s8 a, s8 b)
1943 s8 builtin_lxor(s8 a, s8 b)
1955 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1958 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1959 s4 builtin_lcmp(s8 a, s8 b)
1973 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1976 /* functions for unsupported floating instructions ****************************/
1978 /* used to convert FLT_xxx defines into float values */
1980 static inline float intBitsToFloat(s4 i)
1989 /* used to convert DBL_xxx defines into double values */
1991 static inline float longBitsToDouble(s8 l)
2001 float builtin_fadd(float a, float b)
2003 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2004 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2015 if (copysignf(1.0, a) == copysignf(1.0, b))
2018 return intBitsToFloat(FLT_NAN);
2024 float builtin_fsub(float a, float b)
2026 return builtin_fadd(a, builtin_fneg(b));
2030 float builtin_fmul(float a, float b)
2032 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2033 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2035 if (finitef(b)) return a * b;
2037 if (a == 0) return intBitsToFloat(FLT_NAN);
2038 else return copysignf(b, copysignf(1.0, b)*a);
2043 if (b == 0) return intBitsToFloat(FLT_NAN);
2044 else return copysignf(a, copysignf(1.0, a)*b);
2047 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2053 /* builtin_ddiv ****************************************************************
2055 Implementation as described in VM Spec.
2057 *******************************************************************************/
2059 float builtin_fdiv(float a, float b)
2063 /* If neither value1' nor value2' is NaN, the sign of the result */
2064 /* is positive if both values have the same sign, negative if the */
2065 /* values have different signs. */
2071 /* If either value1' or value2' is NaN, the result is NaN. */
2073 return intBitsToFloat(FLT_NAN);
2076 /* Division of a finite value by an infinity results in a */
2077 /* signed zero, with the sign-producing rule just given. */
2079 /* is sign equal? */
2081 if (copysignf(1.0, a) == copysignf(1.0, b))
2090 /* If either value1' or value2' is NaN, the result is NaN. */
2092 return intBitsToFloat(FLT_NAN);
2094 } else if (finitef(b)) {
2095 /* Division of an infinity by a finite value results in a signed */
2096 /* infinity, with the sign-producing rule just given. */
2098 /* is sign equal? */
2100 if (copysignf(1.0, a) == copysignf(1.0, b))
2101 return intBitsToFloat(FLT_POSINF);
2103 return intBitsToFloat(FLT_NEGINF);
2106 /* Division of an infinity by an infinity results in NaN. */
2108 return intBitsToFloat(FLT_NAN);
2114 float builtin_fneg(float a)
2116 if (isnanf(a)) return a;
2118 if (finitef(a)) return -a;
2119 else return copysignf(a, -copysignf(1.0, a));
2122 #endif /* !SUPPORT_FLOAT */
2125 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2126 s4 builtin_fcmpl(float a, float b)
2134 if (!finitef(a) || !finitef(b)) {
2135 a = finitef(a) ? 0 : copysignf(1.0, a);
2136 b = finitef(b) ? 0 : copysignf(1.0, b);
2149 s4 builtin_fcmpg(float a, float b)
2151 if (isnanf(a)) return 1;
2152 if (isnanf(b)) return 1;
2153 if (!finitef(a) || !finitef(b)) {
2154 a = finitef(a) ? 0 : copysignf(1.0, a);
2155 b = finitef(b) ? 0 : copysignf(1.0, b);
2157 if (a > b) return 1;
2158 if (a == b) return 0;
2161 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2164 float builtin_frem(float a, float b)
2170 /* functions for unsupported double instructions ******************************/
2173 double builtin_dadd(double a, double b)
2175 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2176 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2178 if (finite(b)) return a + b;
2182 if (finite(b)) return a;
2184 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2185 else return longBitsToDouble(DBL_NAN);
2191 double builtin_dsub(double a, double b)
2193 return builtin_dadd(a, builtin_dneg(b));
2197 double builtin_dmul(double a, double b)
2199 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2200 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2202 if (finite(b)) return a * b;
2204 if (a == 0) return longBitsToDouble(DBL_NAN);
2205 else return copysign(b, copysign(1.0, b) * a);
2210 if (b == 0) return longBitsToDouble(DBL_NAN);
2211 else return copysign(a, copysign(1.0, a) * b);
2214 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2220 /* builtin_ddiv ****************************************************************
2222 Implementation as described in VM Spec.
2224 *******************************************************************************/
2226 double builtin_ddiv(double a, double b)
2230 /* If neither value1' nor value2' is NaN, the sign of the result */
2231 /* is positive if both values have the same sign, negative if the */
2232 /* values have different signs. */
2238 /* If either value1' or value2' is NaN, the result is NaN. */
2240 return longBitsToDouble(DBL_NAN);
2243 /* Division of a finite value by an infinity results in a */
2244 /* signed zero, with the sign-producing rule just given. */
2246 /* is sign equal? */
2248 if (copysign(1.0, a) == copysign(1.0, b))
2257 /* If either value1' or value2' is NaN, the result is NaN. */
2259 return longBitsToDouble(DBL_NAN);
2261 } else if (finite(b)) {
2262 /* Division of an infinity by a finite value results in a signed */
2263 /* infinity, with the sign-producing rule just given. */
2265 /* is sign equal? */
2267 if (copysign(1.0, a) == copysign(1.0, b))
2268 return longBitsToDouble(DBL_POSINF);
2270 return longBitsToDouble(DBL_NEGINF);
2273 /* Division of an infinity by an infinity results in NaN. */
2275 return longBitsToDouble(DBL_NAN);
2281 /* builtin_dneg ****************************************************************
2283 Implemented as described in VM Spec.
2285 *******************************************************************************/
2287 double builtin_dneg(double a)
2290 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2297 /* If the operand is a zero, the result is the zero of opposite */
2303 /* If the operand is an infinity, the result is the infinity of */
2304 /* opposite sign. */
2306 return copysign(a, -copysign(1.0, a));
2310 #endif /* !SUPPORT_DOUBLE */
2313 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2314 s4 builtin_dcmpl(double a, double b)
2322 if (!finite(a) || !finite(b)) {
2323 a = finite(a) ? 0 : copysign(1.0, a);
2324 b = finite(b) ? 0 : copysign(1.0, b);
2337 s4 builtin_dcmpg(double a, double b)
2345 if (!finite(a) || !finite(b)) {
2346 a = finite(a) ? 0 : copysign(1.0, a);
2347 b = finite(b) ? 0 : copysign(1.0, b);
2358 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2361 double builtin_drem(double a, double b)
2367 /* conversion operations ******************************************************/
2370 s8 builtin_i2l(s4 i)
2382 s4 builtin_l2i(s8 l)
2393 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2394 float builtin_i2f(s4 a)
2396 float f = (float) a;
2399 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2402 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2403 double builtin_i2d(s4 a)
2405 double d = (double) a;
2408 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2411 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2412 float builtin_l2f(s8 a)
2415 float f = (float) a;
2421 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2424 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2425 double builtin_l2d(s8 a)
2428 double d = (double) a;
2434 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2437 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2438 s4 builtin_f2i(float a)
2442 i = builtin_d2i((double) a);
2453 if (a < (-2147483648))
2454 return (-2147483648);
2457 f = copysignf((float) 1.0, a);
2460 return (-2147483648); */
2462 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2465 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2466 s8 builtin_f2l(float a)
2470 l = builtin_d2l((double) a);
2477 if (a > 9223372036854775807L)
2478 return 9223372036854775807L;
2479 if (a < (-9223372036854775808L))
2480 return (-9223372036854775808L);
2485 f = copysignf((float) 1.0, a);
2487 return 9223372036854775807L;
2488 return (-9223372036854775808L); */
2490 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2493 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2494 s4 builtin_d2i(double a)
2499 if (a >= 2147483647)
2501 if (a <= (-2147483647-1))
2502 return (-2147483647-1);
2507 d = copysign(1.0, a);
2510 return (-2147483647-1);
2512 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2515 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2516 s8 builtin_d2l(double a)
2521 if (a >= 9223372036854775807LL)
2522 return 9223372036854775807LL;
2523 if (a <= (-9223372036854775807LL-1))
2524 return (-9223372036854775807LL-1);
2529 d = copysign(1.0, a);
2531 return 9223372036854775807LL;
2532 return (-9223372036854775807LL-1);
2534 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2537 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2538 double builtin_f2d(float a)
2540 if (finitef(a)) return (double) a;
2543 return longBitsToDouble(DBL_NAN);
2545 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2549 float builtin_d2f(double a)
2555 return intBitsToFloat(FLT_NAN);
2557 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2560 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2563 /* builtin_arraycopy ***********************************************************
2565 Builtin for java.lang.System.arraycopy.
2567 ATTENTION: This builtin function returns a boolean value to signal
2568 the ICMD_BUILTIN if there was an exception.
2570 *******************************************************************************/
2572 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2573 java_arrayheader *dest, s4 destStart, s4 len)
2575 arraydescriptor *sdesc;
2576 arraydescriptor *ddesc;
2579 if ((src == NULL) || (dest == NULL)) {
2580 exceptions_throw_nullpointerexception();
2584 sdesc = src->objheader.vftbl->arraydesc;
2585 ddesc = dest->objheader.vftbl->arraydesc;
2587 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2588 exceptions_throw_arraystoreexception();
2592 /* we try to throw exception with the same message as SUN does */
2594 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2595 (srcStart + len < 0) || (srcStart + len > src->size) ||
2596 (destStart + len < 0) || (destStart + len > dest->size)) {
2597 exceptions_throw_arrayindexoutofboundsexception();
2601 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2602 /* We copy primitive values or references of exactly the same type */
2604 s4 dataoffset = sdesc->dataoffset;
2605 s4 componentsize = sdesc->componentsize;
2607 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2608 ((u1 *) src) + dataoffset + componentsize * srcStart,
2609 (size_t) len * componentsize);
2612 /* We copy references of different type */
2614 java_objectarray *oas = (java_objectarray *) src;
2615 java_objectarray *oad = (java_objectarray *) dest;
2617 if (destStart <= srcStart) {
2618 for (i = 0; i < len; i++) {
2619 java_objectheader *o = oas->data[srcStart + i];
2621 if (!builtin_canstore(oad, o)) {
2622 exceptions_throw_arraystoreexception();
2626 oad->data[destStart + i] = o;
2630 /* XXX this does not completely obey the specification!
2631 If an exception is thrown only the elements above the
2632 current index have been copied. The specification
2633 requires that only the elements *below* the current
2634 index have been copied before the throw. */
2636 for (i = len - 1; i >= 0; i--) {
2637 java_objectheader *o = oas->data[srcStart + i];
2639 if (!builtin_canstore(oad, o)) {
2640 exceptions_throw_arraystoreexception();
2644 oad->data[destStart + i] = o;
2653 /* builtin_currenttimemillis ***************************************************
2655 Return the current time in milliseconds.
2657 *******************************************************************************/
2659 s8 builtin_currenttimemillis(void)
2664 if (gettimeofday(&tv, NULL) == -1)
2665 vm_abort("gettimeofday failed: %s", strerror(errno));
2667 result = (s8) tv.tv_sec;
2669 result += (tv.tv_usec / 1000);
2675 /* builtin_clone ***************************************************************
2677 Function for cloning objects or arrays.
2679 *******************************************************************************/
2681 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2683 arraydescriptor *ad;
2684 java_arrayheader *ah;
2687 java_objectheader *co; /* cloned object header */
2689 /* get the array descriptor */
2691 ad = o->vftbl->arraydesc;
2693 /* we are cloning an array */
2696 ah = (java_arrayheader *) o;
2698 size = ad->dataoffset + ad->componentsize * ah->size;
2700 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2705 MCOPY(co, o, u1, size);
2707 #if defined(ENABLE_GC_CACAO)
2708 heap_init_objectheader(co, size);
2711 #if defined(ENABLE_THREADS)
2712 lock_init_object_lock(co);
2718 /* we are cloning a non-array */
2720 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2721 exceptions_throw_clonenotsupportedexception();
2725 /* get the class of the object */
2727 c = o->vftbl->class;
2729 /* create new object */
2731 co = builtin_new(c);
2736 MCOPY(co, o, u1, c->instancesize);
2738 #if defined(ENABLE_GC_CACAO)
2739 heap_init_objectheader(co, c->instancesize);
2742 #if defined(ENABLE_THREADS)
2743 lock_init_object_lock(co);
2751 * These are local overrides for various environment variables in Emacs.
2752 * Please do not remove this and leave it at the end of the file, where
2753 * Emacs will automagically detect them.
2754 * ---------------------------------------------------------------------
2757 * indent-tabs-mode: t
2761 * vim:noexpandtab:sw=4:ts=4: