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 7316 2007-02-10 19:06:54Z 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(instruction *iptr)
321 builtintable_entry *bte;
323 /* get name and descriptor of the function */
326 case ICMD_INVOKESTATIC:
327 /* The instruction MUST be resolved, otherwise we run into
328 lazy loading troubles. Anyway, we should/can only replace
329 very VM-close functions. */
331 if (INSTRUCTION_IS_UNRESOLVED(iptr))
334 mr = iptr->sx.s23.s3.fmiref;
341 /* search the function table */
343 for (bte = builtintable_function; bte->fp != NULL; bte++) {
344 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
345 (mr->name == bte->name) &&
346 (mr->descriptor == bte->descriptor)) {
348 /* set the values in the instruction */
350 iptr->opc = bte->opcode;
351 iptr->sx.s23.s3.bte = bte;
352 if (bte->checkexception)
353 iptr->flags.bits |= INS_FLAG_CHECK;
355 iptr->flags.bits &= ~INS_FLAG_CHECK;
363 #endif /* defined(ENABLE_JIT) */
366 /*****************************************************************************
368 *****************************************************************************/
372 /*************** internal function: builtin_isanysubclass *********************
374 Checks a subclass relation between two classes. Implemented interfaces
375 are interpreted as super classes.
376 Return value: 1 ... sub is subclass of super
379 ******************************************************************************/
381 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
384 castinfo classvalues;
389 if (super->flags & ACC_INTERFACE) {
390 res = (sub->vftbl->interfacetablelength > super->index) &&
391 (sub->vftbl->interfacetable[-super->index] != NULL);
394 /* java.lang.Object is the only super_class_ of any interface */
395 if (sub->flags & ACC_INTERFACE)
396 return (super == class_java_lang_Object);
398 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
400 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
401 (u4) classvalues.super_diffval;
408 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
412 castinfo classvalues;
417 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
419 if ((base = classvalues.super_baseval) <= 0) {
420 /* super is an interface */
421 res = (sub->interfacetablelength > -base) &&
422 (sub->interfacetable[base] != NULL);
425 /* java.lang.Object is the only super_class_ of any interface */
426 if (classvalues.sub_baseval <= 0)
427 return classvalues.super_baseval == 1;
429 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
430 <= (u4) classvalues.super_diffval;
437 /****************** function: builtin_instanceof *****************************
439 Checks if an object is an instance of some given class (or subclass of
440 that class). If class is an interface, checks if the interface is
442 Return value: 1 ... obj is an instance of class or implements the interface
443 0 ... otherwise or if obj == NULL
445 *****************************************************************************/
447 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
452 return builtin_isanysubclass(obj->vftbl->class, class);
457 /**************** function: builtin_checkcast *******************************
459 The same as builtin_instanceof except that 1 is returned when
462 ****************************************************************************/
464 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
469 if (builtin_isanysubclass(obj->vftbl->class, class))
476 /* builtin_descriptorscompatible ***********************************************
478 Checks if two array type descriptors are assignment compatible
480 Return value: 1 ... target = desc is possible
483 *******************************************************************************/
485 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
486 arraydescriptor *target)
491 if (desc->arraytype != target->arraytype)
494 if (desc->arraytype != ARRAYTYPE_OBJECT)
497 /* {both arrays are arrays of references} */
499 if (desc->dimension == target->dimension) {
500 /* an array which contains elements of interface types is
501 allowed to be casted to Object (JOWENN)*/
503 if ((desc->elementvftbl->baseval < 0) &&
504 (target->elementvftbl->baseval == 1))
507 return builtin_isanysubclass_vftbl(desc->elementvftbl,
508 target->elementvftbl);
511 if (desc->dimension < target->dimension)
514 /* {desc has higher dimension than target} */
516 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
517 target->elementvftbl);
521 /* builtin_arraycheckcast ******************************************************
523 Checks if an object is really a subtype of the requested array
524 type. The object has to be an array to begin with. For simple
525 arrays (int, short, double, etc.) the types have to match exactly.
526 For arrays of objects, the type of elements in the array has to be
527 a subtype (or the same type) of the requested element type. For
528 arrays of arrays (which in turn can again be arrays of arrays), the
529 types at the lowest level have to satisfy the corresponding sub
532 *******************************************************************************/
534 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
536 arraydescriptor *desc;
541 if ((desc = o->vftbl->arraydesc) == NULL)
544 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
548 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
553 return builtin_arraycheckcast(o, targetclass);
557 /* builtin_throw_exception *****************************************************
559 Sets the exceptionptr with the thrown exception and prints some
560 debugging information. Called from asm_vm_call_method.
562 *******************************************************************************/
564 void *builtin_throw_exception(java_objectheader *xptr)
567 java_lang_Throwable *t;
573 t = (java_lang_Throwable *) xptr;
575 /* calculate message length */
577 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
581 utf_bytes(xptr->vftbl->class->name);
582 if (t->detailMessage) {
583 logtextlen += strlen(": ") +
584 u2_utflength(t->detailMessage->value->data
585 + t->detailMessage->offset,
586 t->detailMessage->count);
590 logtextlen += strlen("(nil)");
593 /* allocate memory */
595 dumpsize = dump_size();
597 logtext = DMNEW(char, logtextlen);
599 strcpy(logtext, "Builtin exception thrown: ");
602 utf_cat_classname(logtext, xptr->vftbl->class->name);
604 if (t->detailMessage) {
607 buf = javastring_tochar((java_objectheader *) t->detailMessage);
608 strcat(logtext, ": ");
609 strcat(logtext, buf);
610 MFREE(buf, char, strlen(buf) + 1);
614 strcat(logtext, "(nil)");
621 dump_release(dumpsize);
623 #endif /* !defined(NDEBUG) */
625 /* actually set the exception */
627 exceptions_set_exception(xptr);
629 /* Return a NULL pointer. This is required for vm_call_method to
630 check for an exception. This is for convenience. */
636 /* builtin_canstore ************************************************************
638 Checks, if an object can be stored in an array.
640 Return value: 1 ... possible
643 *******************************************************************************/
645 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
647 arraydescriptor *desc;
648 arraydescriptor *valuedesc;
649 vftbl_t *componentvftbl;
652 castinfo classvalues;
657 /* The following is guaranteed (by verifier checks):
659 * *) oa->...vftbl->arraydesc != NULL
660 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
661 * *) o->vftbl is not an interface vftbl
664 desc = oa->header.objheader.vftbl->arraydesc;
665 componentvftbl = desc->componentvftbl;
666 valuevftbl = o->vftbl;
668 if ((desc->dimension - 1) == 0) {
671 /* {oa is a one-dimensional array} */
672 /* {oa is an array of references} */
674 if (valuevftbl == componentvftbl)
677 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
679 if ((base = classvalues.super_baseval) <= 0)
680 /* an array of interface references */
681 return (valuevftbl->interfacetablelength > -base &&
682 valuevftbl->interfacetable[base] != NULL);
684 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
685 <= (unsigned) classvalues.super_diffval);
690 /* {oa has dimension > 1} */
691 /* {componentvftbl->arraydesc != NULL} */
693 /* check if o is an array */
695 if ((valuedesc = valuevftbl->arraydesc) == NULL)
698 /* {o is an array} */
700 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
704 /* This is an optimized version where a is guaranteed to be one-dimensional */
705 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
707 arraydescriptor *desc;
708 vftbl_t *elementvftbl;
712 castinfo classvalues;
716 /* The following is guaranteed (by verifier checks):
718 * *) a->...vftbl->arraydesc != NULL
719 * *) a->...vftbl->arraydesc->elementvftbl != NULL
720 * *) a->...vftbl->arraydesc->dimension == 1
721 * *) o->vftbl is not an interface vftbl
724 desc = a->header.objheader.vftbl->arraydesc;
725 elementvftbl = desc->elementvftbl;
726 valuevftbl = o->vftbl;
728 /* {a is a one-dimensional array} */
730 if (valuevftbl == elementvftbl)
733 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
735 if ((base = classvalues.super_baseval) <= 0)
736 /* an array of interface references */
737 return (valuevftbl->interfacetablelength > -base &&
738 valuevftbl->interfacetable[base] != NULL);
740 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
741 <= (unsigned) classvalues.super_diffval;
747 /* This is an optimized version where a is guaranteed to be a
748 * one-dimensional array of a class type */
749 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
751 vftbl_t *elementvftbl;
754 castinfo classvalues;
758 /* The following is guaranteed (by verifier checks):
760 * *) a->...vftbl->arraydesc != NULL
761 * *) a->...vftbl->arraydesc->elementvftbl != NULL
762 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
763 * *) a->...vftbl->arraydesc->dimension == 1
764 * *) o->vftbl is not an interface vftbl
767 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
768 valuevftbl = o->vftbl;
770 /* {a is a one-dimensional array} */
772 if (valuevftbl == elementvftbl)
775 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
777 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
778 <= (unsigned) classvalues.super_diffval;
784 /* builtin_new *****************************************************************
786 Creates a new instance of class c on the heap.
788 Return value: pointer to the object or NULL if no memory is
791 *******************************************************************************/
793 java_objectheader *builtin_new(classinfo *c)
795 java_objectheader *o;
796 #if defined(ENABLE_RT_TIMING)
797 struct timespec time_start, time_end;
799 #if defined(ENABLE_CYCLES_STATS)
800 u8 cycles_start, cycles_end;
803 RT_TIMING_GET_TIME(time_start);
804 CYCLES_STATS_GET(cycles_start);
806 /* is the class loaded */
808 assert(c->state & CLASS_LOADED);
810 /* check if we can instantiate this class */
812 if (c->flags & ACC_ABSTRACT) {
813 exceptions_throw_instantiationerror(c);
817 /* is the class linked */
819 if (!(c->state & CLASS_LINKED))
823 if (!(c->state & CLASS_INITIALIZED)) {
826 log_message_class("Initialize class (from builtin_new): ", c);
829 if (!initialize_class(c))
833 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
841 #if defined(ENABLE_THREADS)
842 lock_init_object_lock(o);
845 CYCLES_STATS_GET(cycles_end);
846 RT_TIMING_GET_TIME(time_end);
848 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
849 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
855 /* builtin_newarray ************************************************************
857 Creates an array with the given vftbl on the heap. This function
858 takes as class argument an array class.
860 Return value: pointer to the array or NULL if no memory is available
862 *******************************************************************************/
864 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
866 arraydescriptor *desc;
871 #if defined(ENABLE_RT_TIMING)
872 struct timespec time_start, time_end;
875 RT_TIMING_GET_TIME(time_start);
877 desc = arrayclass->vftbl->arraydesc;
878 dataoffset = desc->dataoffset;
879 componentsize = desc->componentsize;
882 exceptions_throw_negativearraysizeexception();
886 actualsize = dataoffset + size * componentsize;
888 /* check for overflow */
890 if (((u4) actualsize) < ((u4) size)) {
891 exceptions_throw_outofmemoryerror();
895 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
900 a->objheader.vftbl = arrayclass->vftbl;
902 #if defined(ENABLE_THREADS)
903 lock_init_object_lock(&a->objheader);
908 RT_TIMING_GET_TIME(time_end);
909 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
915 /* builtin_anewarray ***********************************************************
917 Creates an array of references to the given class type on the heap.
919 Return value: pointer to the array or NULL if no memory is
922 *******************************************************************************/
924 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
926 classinfo *arrayclass;
928 /* is class loaded */
930 assert(componentclass->state & CLASS_LOADED);
932 /* is class linked */
934 if (!(componentclass->state & CLASS_LINKED))
935 if (!link_class(componentclass))
938 arrayclass = class_array_of(componentclass, true);
943 return (java_objectarray *) builtin_newarray(size, arrayclass);
947 /* builtin_newarray_boolean ****************************************************
949 Creates an array of bytes on the heap. The array is designated as
950 an array of booleans (important for casts)
952 Return value: pointer to the array or NULL if no memory is
955 *******************************************************************************/
957 java_booleanarray *builtin_newarray_boolean(s4 size)
959 return (java_booleanarray *)
960 builtin_newarray(size,
961 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
965 /* builtin_newarray_byte *******************************************************
967 Creates an array of 8 bit Integers on the heap.
969 Return value: pointer to the array or NULL if no memory is
972 *******************************************************************************/
974 java_bytearray *builtin_newarray_byte(s4 size)
976 return (java_bytearray *)
977 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
981 /* builtin_newarray_char *******************************************************
983 Creates an array of characters on the heap.
985 Return value: pointer to the array or NULL if no memory is
988 *******************************************************************************/
990 java_chararray *builtin_newarray_char(s4 size)
992 return (java_chararray *)
993 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
997 /* builtin_newarray_short ******************************************************
999 Creates an array of 16 bit Integers on the heap.
1001 Return value: pointer to the array or NULL if no memory is
1004 *******************************************************************************/
1006 java_shortarray *builtin_newarray_short(s4 size)
1008 return (java_shortarray *)
1009 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1013 /* builtin_newarray_int ********************************************************
1015 Creates an array of 32 bit Integers on the heap.
1017 Return value: pointer to the array or NULL if no memory is
1020 *******************************************************************************/
1022 java_intarray *builtin_newarray_int(s4 size)
1024 return (java_intarray *)
1025 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1029 /* builtin_newarray_long *******************************************************
1031 Creates an array of 64 bit Integers on the heap.
1033 Return value: pointer to the array or NULL if no memory is
1036 *******************************************************************************/
1038 java_longarray *builtin_newarray_long(s4 size)
1040 return (java_longarray *)
1041 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1045 /* builtin_newarray_float ******************************************************
1047 Creates an array of 32 bit IEEE floats on the heap.
1049 Return value: pointer to the array or NULL if no memory is
1052 *******************************************************************************/
1054 java_floatarray *builtin_newarray_float(s4 size)
1056 return (java_floatarray *)
1057 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1061 /* builtin_newarray_double *****************************************************
1063 Creates an array of 64 bit IEEE floats on the heap.
1065 Return value: pointer to the array or NULL if no memory is
1068 *******************************************************************************/
1070 java_doublearray *builtin_newarray_double(s4 size)
1072 return (java_doublearray *)
1073 builtin_newarray(size,
1074 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1078 /* builtin_multianewarray_intern ***********************************************
1080 Creates a multi-dimensional array on the heap. The dimensions are
1081 passed in an array of longs.
1084 n............number of dimensions to create
1085 arrayvftbl...vftbl of the array class
1086 dims.........array containing the size of each dimension to create
1088 Return value: pointer to the array or NULL if no memory is
1091 ******************************************************************************/
1093 static java_arrayheader *builtin_multianewarray_intern(int n,
1094 classinfo *arrayclass,
1098 java_arrayheader *a;
1099 classinfo *componentclass;
1102 /* create this dimension */
1104 size = (s4) dims[0];
1105 a = builtin_newarray(size, arrayclass);
1110 /* if this is the last dimension return */
1115 /* get the class of the components to create */
1117 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1119 /* The verifier guarantees that the dimension count is in the range. */
1121 /* create the component arrays */
1123 for (i = 0; i < size; i++) {
1124 java_arrayheader *ea =
1125 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1126 /* we save an s4 to a s8 slot, 8-byte aligned */
1128 builtin_multianewarray_intern(n, componentclass, dims + 2);
1130 builtin_multianewarray_intern(n, componentclass, dims + 1);
1136 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1143 /* builtin_multianewarray ******************************************************
1145 Wrapper for builtin_multianewarray_intern which checks all
1146 dimensions before we start allocating.
1148 ******************************************************************************/
1150 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1156 /* check all dimensions before doing anything */
1158 for (i = 0; i < n; i++) {
1159 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1160 /* we save an s4 to a s8 slot, 8-byte aligned */
1161 size = (s4) dims[i * 2];
1163 size = (s4) dims[i];
1167 exceptions_throw_negativearraysizeexception();
1172 /* now call the real function */
1174 return builtin_multianewarray_intern(n, arrayclass, dims);
1178 /*****************************************************************************
1181 Various functions for printing a message at method entry or exit (for
1184 *****************************************************************************/
1186 #if !defined(NDEBUG)
1187 static s4 methodindent = 0;
1188 static u4 callcount = 0;
1190 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1200 if (opt_verbosecall && indent)
1203 /* calculate message length */
1207 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1210 logtextlen = strlen("Some Throwable");
1213 logtextlen += strlen(" thrown in ");
1217 utf_bytes(m->class->name) +
1219 utf_bytes(m->name) +
1220 utf_bytes(m->descriptor) +
1221 strlen("(NOSYNC,NATIVE");
1223 #if SIZEOF_VOID_P == 8
1225 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1227 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1230 if (m->class->sourcefile == NULL)
1231 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1233 logtextlen += utf_bytes(m->class->sourcefile);
1235 logtextlen += strlen(":65536)");
1239 logtextlen += strlen("call_java_method");
1242 logtextlen += strlen("0");
1244 /* allocate memory */
1246 dumpsize = dump_size();
1248 logtext = DMNEW(char, logtextlen);
1251 strcpy(logtext, "Exception ");
1252 utf_cat_classname(logtext, xptr->vftbl->class->name);
1255 strcpy(logtext, "Some Throwable");
1258 strcat(logtext, " thrown in ");
1261 utf_cat_classname(logtext, m->class->name);
1262 strcat(logtext, ".");
1263 utf_cat(logtext, m->name);
1264 utf_cat(logtext, m->descriptor);
1266 if (m->flags & ACC_SYNCHRONIZED)
1267 strcat(logtext, "(SYNC");
1269 strcat(logtext, "(NOSYNC");
1271 if (m->flags & ACC_NATIVE) {
1272 strcat(logtext, ",NATIVE");
1276 #if SIZEOF_VOID_P == 8
1277 sprintf(logtext + strlen(logtext),
1278 ")(0x%016lx) at position 0x%016lx",
1279 (ptrint) code->entrypoint, (ptrint) pos);
1281 sprintf(logtext + strlen(logtext),
1282 ")(0x%08x) at position 0x%08x",
1283 (ptrint) code->entrypoint, (ptrint) pos);
1288 /* XXX preliminary: This should get the actual codeinfo */
1289 /* in which the exception happened. */
1292 #if SIZEOF_VOID_P == 8
1293 sprintf(logtext + strlen(logtext),
1294 ")(0x%016lx) at position 0x%016lx (",
1295 (ptrint) code->entrypoint, (ptrint) pos);
1297 sprintf(logtext + strlen(logtext),
1298 ")(0x%08x) at position 0x%08x (",
1299 (ptrint) code->entrypoint, (ptrint) pos);
1302 if (m->class->sourcefile == NULL)
1303 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1305 utf_cat(logtext, m->class->sourcefile);
1307 sprintf(logtext + strlen(logtext), ":%d)", 0);
1311 strcat(logtext, "call_java_method");
1315 /* release memory */
1317 dump_release(dumpsize);
1321 #endif /* !defined(NDEBUG) */
1324 /* builtin_print_argument ******************************************************
1326 Prints arguments and return values for the call trace.
1328 *******************************************************************************/
1330 #if !defined(NDEBUG)
1331 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1332 typedesc *paramtype, s8 value)
1335 java_objectheader *o;
1336 java_lang_String *s;
1341 switch (paramtype->type) {
1344 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1349 #if SIZEOF_VOID_P == 4
1350 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1352 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1358 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1363 #if SIZEOF_VOID_P == 4
1364 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1366 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1371 #if SIZEOF_VOID_P == 4
1372 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1374 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1377 /* cast to java.lang.Object */
1379 o = (java_objectheader *) (ptrint) value;
1381 /* check return argument for java.lang.Class or java.lang.String */
1384 if (o->vftbl->class == class_java_lang_String) {
1385 /* get java.lang.String object and the length of the
1388 s = (java_lang_String *) o;
1390 u = javastring_toutf(s, false);
1392 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1394 /* realloc memory for string length */
1396 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1399 /* convert to utf8 string and strcat it to the logtext */
1401 strcat(logtext, " (String = \"");
1402 utf_cat(logtext, u);
1403 strcat(logtext, "\")");
1406 if (o->vftbl->class == class_java_lang_Class) {
1407 /* if the object returned is a java.lang.Class
1408 cast it to classinfo structure and get the name
1411 c = (classinfo *) o;
1416 /* if the object returned is not a java.lang.String or
1417 a java.lang.Class just print the name of the class */
1419 u = o->vftbl->class->name;
1422 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1424 /* realloc memory for string length */
1426 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1429 /* strcat to the logtext */
1431 strcat(logtext, " (Class = \"");
1432 utf_cat_classname(logtext, u);
1433 strcat(logtext, "\")");
1440 #endif /* !defined(NDEBUG) */
1443 /* builtin_verbosecall_enter ***************************************************
1445 Print method call with arguments for -verbose:call.
1447 *******************************************************************************/
1449 #if !defined(NDEBUG)
1451 #ifdef TRACE_ARGS_NUM
1452 void builtin_verbosecall_enter(s8 a0, s8 a1,
1453 # if TRACE_ARGS_NUM >= 4
1456 # if TRACE_ARGS_NUM >= 6
1459 # if TRACE_ARGS_NUM == 8
1473 /* calculate message length */
1476 strlen("4294967295 ") +
1477 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1479 strlen("called: ") +
1480 utf_bytes(m->class->name) +
1482 utf_bytes(m->name) +
1483 utf_bytes(m->descriptor);
1485 /* Actually it's not possible to have all flags printed, but:
1490 strlen(" PRIVATE") +
1491 strlen(" PROTECTED") +
1494 strlen(" SYNCHRONIZED") +
1495 strlen(" VOLATILE") +
1496 strlen(" TRANSIENT") +
1498 strlen(" INTERFACE") +
1499 strlen(" ABSTRACT");
1501 /* add maximal argument length */
1505 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1506 strlen("...(255)") +
1509 /* allocate memory */
1511 dumpsize = dump_size();
1513 logtext = DMNEW(char, logtextlen);
1517 sprintf(logtext, "%10d ", callcount);
1518 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1520 pos = strlen(logtext);
1522 for (i = 0; i < methodindent; i++)
1523 logtext[pos++] = '\t';
1525 strcpy(logtext + pos, "called: ");
1527 utf_cat_classname(logtext, m->class->name);
1528 strcat(logtext, ".");
1529 utf_cat(logtext, m->name);
1530 utf_cat(logtext, m->descriptor);
1532 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1533 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1534 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1535 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1536 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1537 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1538 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1539 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1540 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1541 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1542 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1544 strcat(logtext, "(");
1546 if (md->paramcount >= 1) {
1547 logtext = builtin_print_argument(logtext, &logtextlen,
1548 &md->paramtypes[0], a0);
1551 if (md->paramcount >= 2) {
1552 strcat(logtext, ", ");
1554 logtext = builtin_print_argument(logtext, &logtextlen,
1555 &md->paramtypes[1], a1);
1558 #if TRACE_ARGS_NUM >= 4
1559 if (md->paramcount >= 3) {
1560 strcat(logtext, ", ");
1562 logtext = builtin_print_argument(logtext, &logtextlen,
1563 &md->paramtypes[2], a2);
1566 if (md->paramcount >= 4) {
1567 strcat(logtext, ", ");
1569 logtext = builtin_print_argument(logtext, &logtextlen,
1570 &md->paramtypes[3], a3);
1574 #if TRACE_ARGS_NUM >= 6
1575 if (md->paramcount >= 5) {
1576 strcat(logtext, ", ");
1578 logtext = builtin_print_argument(logtext, &logtextlen,
1579 &md->paramtypes[4], a4);
1582 if (md->paramcount >= 6) {
1583 strcat(logtext, ", ");
1585 logtext = builtin_print_argument(logtext, &logtextlen,
1586 &md->paramtypes[5], a5);
1590 #if TRACE_ARGS_NUM == 8
1591 if (md->paramcount >= 7) {
1592 strcat(logtext, ", ");
1594 logtext = builtin_print_argument(logtext, &logtextlen,
1595 &md->paramtypes[6], a6);
1598 if (md->paramcount >= 8) {
1599 strcat(logtext, ", ");
1601 logtext = builtin_print_argument(logtext, &logtextlen,
1602 &md->paramtypes[7], a7);
1606 if (md->paramcount > 8) {
1607 sprintf(logtext + strlen(logtext), ", ...(%d)",
1608 md->paramcount - TRACE_ARGS_NUM);
1611 strcat(logtext, ")");
1615 /* release memory */
1617 dump_release(dumpsize);
1622 #endif /* !defined(NDEBUG) */
1625 /* builtin_verbosecall_exit ****************************************************
1627 Print method exit for -verbose:call.
1629 *******************************************************************************/
1631 #if !defined(NDEBUG)
1632 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1644 /* calculate message length */
1647 strlen("4294967295 ") +
1648 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1650 strlen("finished: ") +
1651 utf_bytes(m->class->name) +
1653 utf_bytes(m->name) +
1654 utf_bytes(m->descriptor) +
1655 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1657 /* add maximal argument length */
1659 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1661 /* allocate memory */
1663 dumpsize = dump_size();
1665 logtext = DMNEW(char, logtextlen);
1667 /* outdent the log message */
1672 log_text("WARNING: unmatched methodindent--");
1674 /* generate the message */
1676 sprintf(logtext, " ");
1677 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1679 pos = strlen(logtext);
1681 for (i = 0; i < methodindent; i++)
1682 logtext[pos++] = '\t';
1684 strcpy(logtext + pos, "finished: ");
1685 utf_cat_classname(logtext, m->class->name);
1686 strcat(logtext, ".");
1687 utf_cat(logtext, m->name);
1688 utf_cat(logtext, m->descriptor);
1690 if (!IS_VOID_TYPE(md->returntype.type)) {
1691 strcat(logtext, "->");
1693 switch (md->returntype.type) {
1710 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1715 /* release memory */
1717 dump_release(dumpsize);
1719 #endif /* !defined(NDEBUG) */
1722 #if defined(ENABLE_CYCLES_STATS)
1723 void builtin_print_cycles_stats(FILE *file)
1725 fprintf(file,"builtin cylce count statistics:\n");
1727 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1728 CYCLES_STATS_PRINT(builtin_new ,file);
1732 #endif /* defined(ENABLE_CYCLES_STATS) */
1735 /*****************************************************************************
1736 MISCELLANEOUS HELPER FUNCTIONS
1737 *****************************************************************************/
1741 /*********** Functions for integer divisions *****************************
1743 On some systems (eg. DEC ALPHA), integer division is not supported by the
1744 CPU. These helper functions implement the missing functionality.
1746 ******************************************************************************/
1748 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1749 s4 builtin_idiv(s4 a, s4 b)
1758 s4 builtin_irem(s4 a, s4 b)
1766 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1769 /* functions for long arithmetics **********************************************
1771 On systems where 64 bit Integers are not supported by the CPU,
1772 these functions are needed.
1774 ******************************************************************************/
1776 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1777 s8 builtin_ladd(s8 a, s8 b)
1790 s8 builtin_lsub(s8 a, s8 b)
1803 s8 builtin_lneg(s8 a)
1815 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1818 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1819 s8 builtin_lmul(s8 a, s8 b)
1831 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1834 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1835 s8 builtin_ldiv(s8 a, s8 b)
1848 s8 builtin_lrem(s8 a, s8 b)
1860 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1863 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1864 s8 builtin_lshl(s8 a, s4 b)
1877 s8 builtin_lshr(s8 a, s4 b)
1890 s8 builtin_lushr(s8 a, s4 b)
1895 c = ((u8) a) >> (b & 63);
1902 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1905 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1906 s8 builtin_land(s8 a, s8 b)
1919 s8 builtin_lor(s8 a, s8 b)
1932 s8 builtin_lxor(s8 a, s8 b)
1944 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1947 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1948 s4 builtin_lcmp(s8 a, s8 b)
1962 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1965 /* functions for unsupported floating instructions ****************************/
1967 /* used to convert FLT_xxx defines into float values */
1969 static inline float intBitsToFloat(s4 i)
1978 /* used to convert DBL_xxx defines into double values */
1980 static inline float longBitsToDouble(s8 l)
1990 float builtin_fadd(float a, float b)
1992 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1993 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2004 if (copysignf(1.0, a) == copysignf(1.0, b))
2007 return intBitsToFloat(FLT_NAN);
2013 float builtin_fsub(float a, float b)
2015 return builtin_fadd(a, builtin_fneg(b));
2019 float builtin_fmul(float a, float b)
2021 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2022 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2024 if (finitef(b)) return a * b;
2026 if (a == 0) return intBitsToFloat(FLT_NAN);
2027 else return copysignf(b, copysignf(1.0, b)*a);
2032 if (b == 0) return intBitsToFloat(FLT_NAN);
2033 else return copysignf(a, copysignf(1.0, a)*b);
2036 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2042 /* builtin_ddiv ****************************************************************
2044 Implementation as described in VM Spec.
2046 *******************************************************************************/
2048 float builtin_fdiv(float a, float b)
2052 /* If neither value1' nor value2' is NaN, the sign of the result */
2053 /* is positive if both values have the same sign, negative if the */
2054 /* values have different signs. */
2060 /* If either value1' or value2' is NaN, the result is NaN. */
2062 return intBitsToFloat(FLT_NAN);
2065 /* Division of a finite value by an infinity results in a */
2066 /* signed zero, with the sign-producing rule just given. */
2068 /* is sign equal? */
2070 if (copysignf(1.0, a) == copysignf(1.0, b))
2079 /* If either value1' or value2' is NaN, the result is NaN. */
2081 return intBitsToFloat(FLT_NAN);
2083 } else if (finitef(b)) {
2084 /* Division of an infinity by a finite value results in a signed */
2085 /* infinity, with the sign-producing rule just given. */
2087 /* is sign equal? */
2089 if (copysignf(1.0, a) == copysignf(1.0, b))
2090 return intBitsToFloat(FLT_POSINF);
2092 return intBitsToFloat(FLT_NEGINF);
2095 /* Division of an infinity by an infinity results in NaN. */
2097 return intBitsToFloat(FLT_NAN);
2103 float builtin_fneg(float a)
2105 if (isnanf(a)) return a;
2107 if (finitef(a)) return -a;
2108 else return copysignf(a, -copysignf(1.0, a));
2111 #endif /* !SUPPORT_FLOAT */
2114 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2115 s4 builtin_fcmpl(float a, float b)
2123 if (!finitef(a) || !finitef(b)) {
2124 a = finitef(a) ? 0 : copysignf(1.0, a);
2125 b = finitef(b) ? 0 : copysignf(1.0, b);
2138 s4 builtin_fcmpg(float a, float b)
2140 if (isnanf(a)) return 1;
2141 if (isnanf(b)) return 1;
2142 if (!finitef(a) || !finitef(b)) {
2143 a = finitef(a) ? 0 : copysignf(1.0, a);
2144 b = finitef(b) ? 0 : copysignf(1.0, b);
2146 if (a > b) return 1;
2147 if (a == b) return 0;
2150 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2153 float builtin_frem(float a, float b)
2159 /* functions for unsupported double instructions ******************************/
2162 double builtin_dadd(double a, double b)
2164 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2165 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2167 if (finite(b)) return a + b;
2171 if (finite(b)) return a;
2173 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2174 else return longBitsToDouble(DBL_NAN);
2180 double builtin_dsub(double a, double b)
2182 return builtin_dadd(a, builtin_dneg(b));
2186 double builtin_dmul(double a, double b)
2188 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2189 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2191 if (finite(b)) return a * b;
2193 if (a == 0) return longBitsToDouble(DBL_NAN);
2194 else return copysign(b, copysign(1.0, b) * a);
2199 if (b == 0) return longBitsToDouble(DBL_NAN);
2200 else return copysign(a, copysign(1.0, a) * b);
2203 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2209 /* builtin_ddiv ****************************************************************
2211 Implementation as described in VM Spec.
2213 *******************************************************************************/
2215 double builtin_ddiv(double a, double b)
2219 /* If neither value1' nor value2' is NaN, the sign of the result */
2220 /* is positive if both values have the same sign, negative if the */
2221 /* values have different signs. */
2227 /* If either value1' or value2' is NaN, the result is NaN. */
2229 return longBitsToDouble(DBL_NAN);
2232 /* Division of a finite value by an infinity results in a */
2233 /* signed zero, with the sign-producing rule just given. */
2235 /* is sign equal? */
2237 if (copysign(1.0, a) == copysign(1.0, b))
2246 /* If either value1' or value2' is NaN, the result is NaN. */
2248 return longBitsToDouble(DBL_NAN);
2250 } else if (finite(b)) {
2251 /* Division of an infinity by a finite value results in a signed */
2252 /* infinity, with the sign-producing rule just given. */
2254 /* is sign equal? */
2256 if (copysign(1.0, a) == copysign(1.0, b))
2257 return longBitsToDouble(DBL_POSINF);
2259 return longBitsToDouble(DBL_NEGINF);
2262 /* Division of an infinity by an infinity results in NaN. */
2264 return longBitsToDouble(DBL_NAN);
2270 /* builtin_dneg ****************************************************************
2272 Implemented as described in VM Spec.
2274 *******************************************************************************/
2276 double builtin_dneg(double a)
2279 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2286 /* If the operand is a zero, the result is the zero of opposite */
2292 /* If the operand is an infinity, the result is the infinity of */
2293 /* opposite sign. */
2295 return copysign(a, -copysign(1.0, a));
2299 #endif /* !SUPPORT_DOUBLE */
2302 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2303 s4 builtin_dcmpl(double a, double b)
2311 if (!finite(a) || !finite(b)) {
2312 a = finite(a) ? 0 : copysign(1.0, a);
2313 b = finite(b) ? 0 : copysign(1.0, b);
2326 s4 builtin_dcmpg(double a, double b)
2334 if (!finite(a) || !finite(b)) {
2335 a = finite(a) ? 0 : copysign(1.0, a);
2336 b = finite(b) ? 0 : copysign(1.0, b);
2347 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2350 double builtin_drem(double a, double b)
2356 /* conversion operations ******************************************************/
2359 s8 builtin_i2l(s4 i)
2371 s4 builtin_l2i(s8 l)
2382 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2383 float builtin_i2f(s4 a)
2385 float f = (float) a;
2388 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2391 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2392 double builtin_i2d(s4 a)
2394 double d = (double) a;
2397 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2400 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2401 float builtin_l2f(s8 a)
2404 float f = (float) a;
2410 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2413 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2414 double builtin_l2d(s8 a)
2417 double d = (double) a;
2423 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2426 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2427 s4 builtin_f2i(float a)
2431 i = builtin_d2i((double) a);
2442 if (a < (-2147483648))
2443 return (-2147483648);
2446 f = copysignf((float) 1.0, a);
2449 return (-2147483648); */
2451 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2454 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2455 s8 builtin_f2l(float a)
2459 l = builtin_d2l((double) a);
2466 if (a > 9223372036854775807L)
2467 return 9223372036854775807L;
2468 if (a < (-9223372036854775808L))
2469 return (-9223372036854775808L);
2474 f = copysignf((float) 1.0, a);
2476 return 9223372036854775807L;
2477 return (-9223372036854775808L); */
2479 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2482 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2483 s4 builtin_d2i(double a)
2488 if (a >= 2147483647)
2490 if (a <= (-2147483647-1))
2491 return (-2147483647-1);
2496 d = copysign(1.0, a);
2499 return (-2147483647-1);
2501 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2504 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2505 s8 builtin_d2l(double a)
2510 if (a >= 9223372036854775807LL)
2511 return 9223372036854775807LL;
2512 if (a <= (-9223372036854775807LL-1))
2513 return (-9223372036854775807LL-1);
2518 d = copysign(1.0, a);
2520 return 9223372036854775807LL;
2521 return (-9223372036854775807LL-1);
2523 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2526 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2527 double builtin_f2d(float a)
2529 if (finitef(a)) return (double) a;
2532 return longBitsToDouble(DBL_NAN);
2534 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2538 float builtin_d2f(double a)
2544 return intBitsToFloat(FLT_NAN);
2546 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2549 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2552 /* builtin_arraycopy ***********************************************************
2554 Builtin for java.lang.System.arraycopy.
2556 ATTENTION: This builtin function returns a boolean value to signal
2557 the ICMD_BUILTIN if there was an exception.
2559 *******************************************************************************/
2561 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2562 java_arrayheader *dest, s4 destStart, s4 len)
2564 arraydescriptor *sdesc;
2565 arraydescriptor *ddesc;
2568 if ((src == NULL) || (dest == NULL)) {
2569 exceptions_throw_nullpointerexception();
2573 sdesc = src->objheader.vftbl->arraydesc;
2574 ddesc = dest->objheader.vftbl->arraydesc;
2576 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2577 exceptions_throw_arraystoreexception();
2581 /* we try to throw exception with the same message as SUN does */
2583 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2584 (srcStart + len < 0) || (srcStart + len > src->size) ||
2585 (destStart + len < 0) || (destStart + len > dest->size)) {
2586 exceptions_throw_arrayindexoutofboundsexception();
2590 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2591 /* We copy primitive values or references of exactly the same type */
2593 s4 dataoffset = sdesc->dataoffset;
2594 s4 componentsize = sdesc->componentsize;
2596 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2597 ((u1 *) src) + dataoffset + componentsize * srcStart,
2598 (size_t) len * componentsize);
2601 /* We copy references of different type */
2603 java_objectarray *oas = (java_objectarray *) src;
2604 java_objectarray *oad = (java_objectarray *) dest;
2606 if (destStart <= srcStart) {
2607 for (i = 0; i < len; i++) {
2608 java_objectheader *o = oas->data[srcStart + i];
2610 if (!builtin_canstore(oad, o)) {
2611 exceptions_throw_arraystoreexception();
2615 oad->data[destStart + i] = o;
2619 /* XXX this does not completely obey the specification!
2620 If an exception is thrown only the elements above the
2621 current index have been copied. The specification
2622 requires that only the elements *below* the current
2623 index have been copied before the throw. */
2625 for (i = len - 1; i >= 0; i--) {
2626 java_objectheader *o = oas->data[srcStart + i];
2628 if (!builtin_canstore(oad, o)) {
2629 exceptions_throw_arraystoreexception();
2633 oad->data[destStart + i] = o;
2642 /* builtin_currenttimemillis ***************************************************
2644 Return the current time in milliseconds.
2646 *******************************************************************************/
2648 s8 builtin_currenttimemillis(void)
2653 if (gettimeofday(&tv, NULL) == -1)
2654 vm_abort("gettimeofday failed: %s", strerror(errno));
2656 result = (s8) tv.tv_sec;
2658 result += (tv.tv_usec / 1000);
2664 /* builtin_clone ***************************************************************
2666 Function for cloning objects or arrays.
2668 *******************************************************************************/
2670 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2672 arraydescriptor *ad;
2673 java_arrayheader *ah;
2676 java_objectheader *co; /* cloned object header */
2678 /* get the array descriptor */
2680 ad = o->vftbl->arraydesc;
2682 /* we are cloning an array */
2685 ah = (java_arrayheader *) o;
2687 size = ad->dataoffset + ad->componentsize * ah->size;
2689 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2694 MCOPY(co, o, u1, size);
2696 #if defined(ENABLE_GC_CACAO)
2697 heap_init_objectheader(co, size);
2700 #if defined(ENABLE_THREADS)
2701 lock_init_object_lock(co);
2707 /* we are cloning a non-array */
2709 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2710 exceptions_throw_clonenotsupportedexception();
2714 /* get the class of the object */
2716 c = o->vftbl->class;
2718 /* create new object */
2720 co = builtin_new(c);
2725 MCOPY(co, o, u1, c->instancesize);
2727 #if defined(ENABLE_GC_CACAO)
2728 heap_init_objectheader(co, c->instancesize);
2731 #if defined(ENABLE_THREADS)
2732 lock_init_object_lock(co);
2740 * These are local overrides for various environment variables in Emacs.
2741 * Please do not remove this and leave it at the end of the file, where
2742 * Emacs will automagically detect them.
2743 * ---------------------------------------------------------------------
2746 * indent-tabs-mode: t
2750 * vim:noexpandtab:sw=4:ts=4: