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 7483 2007-03-08 13:17:40Z michi $
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 /*************** internal function: builtin_isanysubclass *********************
377 Checks a subclass relation between two classes. Implemented interfaces
378 are interpreted as super classes.
379 Return value: 1 ... sub is subclass of super
382 ******************************************************************************/
384 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
387 castinfo classvalues;
392 if (super->flags & ACC_INTERFACE) {
393 res = (sub->vftbl->interfacetablelength > super->index) &&
394 (sub->vftbl->interfacetable[-super->index] != NULL);
397 /* java.lang.Object is the only super_class_ of any interface */
398 if (sub->flags & ACC_INTERFACE)
399 return (super == class_java_lang_Object);
401 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
403 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
404 (u4) classvalues.super_diffval;
411 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
415 castinfo classvalues;
420 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
422 if ((base = classvalues.super_baseval) <= 0) {
423 /* super is an interface */
424 res = (sub->interfacetablelength > -base) &&
425 (sub->interfacetable[base] != NULL);
428 /* java.lang.Object is the only super_class_ of any interface */
429 if (classvalues.sub_baseval <= 0)
430 return classvalues.super_baseval == 1;
432 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
433 <= (u4) classvalues.super_diffval;
440 /****************** function: builtin_instanceof *****************************
442 Checks if an object is an instance of some given class (or subclass of
443 that class). If class is an interface, checks if the interface is
445 Return value: 1 ... obj is an instance of class or implements the interface
446 0 ... otherwise or if obj == NULL
448 *****************************************************************************/
450 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
455 return builtin_isanysubclass(obj->vftbl->class, class);
460 /**************** function: builtin_checkcast *******************************
462 The same as builtin_instanceof except that 1 is returned when
465 ****************************************************************************/
467 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
472 if (builtin_isanysubclass(obj->vftbl->class, class))
479 /* builtin_descriptorscompatible ***********************************************
481 Checks if two array type descriptors are assignment compatible
483 Return value: 1 ... target = desc is possible
486 *******************************************************************************/
488 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
489 arraydescriptor *target)
494 if (desc->arraytype != target->arraytype)
497 if (desc->arraytype != ARRAYTYPE_OBJECT)
500 /* {both arrays are arrays of references} */
502 if (desc->dimension == target->dimension) {
503 /* an array which contains elements of interface types is
504 allowed to be casted to Object (JOWENN)*/
506 if ((desc->elementvftbl->baseval < 0) &&
507 (target->elementvftbl->baseval == 1))
510 return builtin_isanysubclass_vftbl(desc->elementvftbl,
511 target->elementvftbl);
514 if (desc->dimension < target->dimension)
517 /* {desc has higher dimension than target} */
519 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
520 target->elementvftbl);
524 /* builtin_arraycheckcast ******************************************************
526 Checks if an object is really a subtype of the requested array
527 type. The object has to be an array to begin with. For simple
528 arrays (int, short, double, etc.) the types have to match exactly.
529 For arrays of objects, the type of elements in the array has to be
530 a subtype (or the same type) of the requested element type. For
531 arrays of arrays (which in turn can again be arrays of arrays), the
532 types at the lowest level have to satisfy the corresponding sub
535 *******************************************************************************/
537 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
539 arraydescriptor *desc;
544 if ((desc = o->vftbl->arraydesc) == NULL)
547 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
551 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
556 return builtin_arraycheckcast(o, targetclass);
560 /* builtin_throw_exception *****************************************************
562 Sets the exceptionptr with the thrown exception and prints some
563 debugging information. Called from asm_vm_call_method.
565 *******************************************************************************/
567 void *builtin_throw_exception(java_objectheader *xptr)
570 java_lang_Throwable *t;
576 t = (java_lang_Throwable *) xptr;
578 /* calculate message length */
580 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
584 utf_bytes(xptr->vftbl->class->name);
585 if (t->detailMessage) {
586 logtextlen += strlen(": ") +
587 u2_utflength(t->detailMessage->value->data
588 + t->detailMessage->offset,
589 t->detailMessage->count);
593 logtextlen += strlen("(nil)");
596 /* allocate memory */
598 dumpsize = dump_size();
600 logtext = DMNEW(char, logtextlen);
602 strcpy(logtext, "Builtin exception thrown: ");
605 utf_cat_classname(logtext, xptr->vftbl->class->name);
607 if (t->detailMessage) {
610 buf = javastring_tochar((java_objectheader *) t->detailMessage);
611 strcat(logtext, ": ");
612 strcat(logtext, buf);
613 MFREE(buf, char, strlen(buf) + 1);
617 strcat(logtext, "(nil)");
624 dump_release(dumpsize);
626 #endif /* !defined(NDEBUG) */
628 /* actually set the exception */
630 exceptions_set_exception(xptr);
632 /* Return a NULL pointer. This is required for vm_call_method to
633 check for an exception. This is for convenience. */
639 /* builtin_canstore ************************************************************
641 Checks, if an object can be stored in an array.
643 Return value: 1 ... possible
646 *******************************************************************************/
648 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
650 arraydescriptor *desc;
651 arraydescriptor *valuedesc;
652 vftbl_t *componentvftbl;
655 castinfo classvalues;
660 /* The following is guaranteed (by verifier checks):
662 * *) oa->...vftbl->arraydesc != NULL
663 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
664 * *) o->vftbl is not an interface vftbl
667 desc = oa->header.objheader.vftbl->arraydesc;
668 componentvftbl = desc->componentvftbl;
669 valuevftbl = o->vftbl;
671 if ((desc->dimension - 1) == 0) {
674 /* {oa is a one-dimensional array} */
675 /* {oa is an array of references} */
677 if (valuevftbl == componentvftbl)
680 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
682 if ((base = classvalues.super_baseval) <= 0)
683 /* an array of interface references */
684 return (valuevftbl->interfacetablelength > -base &&
685 valuevftbl->interfacetable[base] != NULL);
687 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
688 <= (unsigned) classvalues.super_diffval);
693 /* {oa has dimension > 1} */
694 /* {componentvftbl->arraydesc != NULL} */
696 /* check if o is an array */
698 if ((valuedesc = valuevftbl->arraydesc) == NULL)
701 /* {o is an array} */
703 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
707 /* This is an optimized version where a is guaranteed to be one-dimensional */
708 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
710 arraydescriptor *desc;
711 vftbl_t *elementvftbl;
715 castinfo classvalues;
719 /* The following is guaranteed (by verifier checks):
721 * *) a->...vftbl->arraydesc != NULL
722 * *) a->...vftbl->arraydesc->elementvftbl != NULL
723 * *) a->...vftbl->arraydesc->dimension == 1
724 * *) o->vftbl is not an interface vftbl
727 desc = a->header.objheader.vftbl->arraydesc;
728 elementvftbl = desc->elementvftbl;
729 valuevftbl = o->vftbl;
731 /* {a is a one-dimensional array} */
733 if (valuevftbl == elementvftbl)
736 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
738 if ((base = classvalues.super_baseval) <= 0)
739 /* an array of interface references */
740 return (valuevftbl->interfacetablelength > -base &&
741 valuevftbl->interfacetable[base] != NULL);
743 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
744 <= (unsigned) classvalues.super_diffval;
750 /* This is an optimized version where a is guaranteed to be a
751 * one-dimensional array of a class type */
752 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
754 vftbl_t *elementvftbl;
757 castinfo classvalues;
761 /* The following is guaranteed (by verifier checks):
763 * *) a->...vftbl->arraydesc != NULL
764 * *) a->...vftbl->arraydesc->elementvftbl != NULL
765 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
766 * *) a->...vftbl->arraydesc->dimension == 1
767 * *) o->vftbl is not an interface vftbl
770 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
771 valuevftbl = o->vftbl;
773 /* {a is a one-dimensional array} */
775 if (valuevftbl == elementvftbl)
778 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
780 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
781 <= (unsigned) classvalues.super_diffval;
787 /* builtin_new *****************************************************************
789 Creates a new instance of class c on the heap.
791 Return value: pointer to the object or NULL if no memory is
794 *******************************************************************************/
796 java_objectheader *builtin_new(classinfo *c)
798 java_objectheader *o;
799 #if defined(ENABLE_RT_TIMING)
800 struct timespec time_start, time_end;
802 #if defined(ENABLE_CYCLES_STATS)
803 u8 cycles_start, cycles_end;
806 RT_TIMING_GET_TIME(time_start);
807 CYCLES_STATS_GET(cycles_start);
809 /* is the class loaded */
811 assert(c->state & CLASS_LOADED);
813 /* check if we can instantiate this class */
815 if (c->flags & ACC_ABSTRACT) {
816 exceptions_throw_instantiationerror(c);
820 /* is the class linked */
822 if (!(c->state & CLASS_LINKED))
826 if (!(c->state & CLASS_INITIALIZED)) {
829 log_message_class("Initialize class (from builtin_new): ", c);
832 if (!initialize_class(c))
836 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
844 #if defined(ENABLE_THREADS)
845 lock_init_object_lock(o);
848 CYCLES_STATS_GET(cycles_end);
849 RT_TIMING_GET_TIME(time_end);
851 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
852 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
858 /* builtin_newarray ************************************************************
860 Creates an array with the given vftbl on the heap. This function
861 takes as class argument an array class.
863 Return value: pointer to the array or NULL if no memory is available
865 *******************************************************************************/
867 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
869 arraydescriptor *desc;
874 #if defined(ENABLE_RT_TIMING)
875 struct timespec time_start, time_end;
878 RT_TIMING_GET_TIME(time_start);
880 desc = arrayclass->vftbl->arraydesc;
881 dataoffset = desc->dataoffset;
882 componentsize = desc->componentsize;
885 exceptions_throw_negativearraysizeexception();
889 actualsize = dataoffset + size * componentsize;
891 /* check for overflow */
893 if (((u4) actualsize) < ((u4) size)) {
894 exceptions_throw_outofmemoryerror();
898 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
903 a->objheader.vftbl = arrayclass->vftbl;
905 #if defined(ENABLE_THREADS)
906 lock_init_object_lock(&a->objheader);
911 RT_TIMING_GET_TIME(time_end);
912 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
918 /* builtin_anewarray ***********************************************************
920 Creates an array of references to the given class type on the heap.
922 Return value: pointer to the array or NULL if no memory is
925 *******************************************************************************/
927 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
929 classinfo *arrayclass;
931 /* is class loaded */
933 assert(componentclass->state & CLASS_LOADED);
935 /* is class linked */
937 if (!(componentclass->state & CLASS_LINKED))
938 if (!link_class(componentclass))
941 arrayclass = class_array_of(componentclass, true);
946 return (java_objectarray *) builtin_newarray(size, arrayclass);
950 /* builtin_newarray_boolean ****************************************************
952 Creates an array of bytes on the heap. The array is designated as
953 an array of booleans (important for casts)
955 Return value: pointer to the array or NULL if no memory is
958 *******************************************************************************/
960 java_booleanarray *builtin_newarray_boolean(s4 size)
962 return (java_booleanarray *)
963 builtin_newarray(size,
964 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
968 /* builtin_newarray_byte *******************************************************
970 Creates an array of 8 bit Integers on the heap.
972 Return value: pointer to the array or NULL if no memory is
975 *******************************************************************************/
977 java_bytearray *builtin_newarray_byte(s4 size)
979 return (java_bytearray *)
980 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
984 /* builtin_newarray_char *******************************************************
986 Creates an array of characters on the heap.
988 Return value: pointer to the array or NULL if no memory is
991 *******************************************************************************/
993 java_chararray *builtin_newarray_char(s4 size)
995 return (java_chararray *)
996 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1000 /* builtin_newarray_short ******************************************************
1002 Creates an array of 16 bit Integers on the heap.
1004 Return value: pointer to the array or NULL if no memory is
1007 *******************************************************************************/
1009 java_shortarray *builtin_newarray_short(s4 size)
1011 return (java_shortarray *)
1012 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1016 /* builtin_newarray_int ********************************************************
1018 Creates an array of 32 bit Integers on the heap.
1020 Return value: pointer to the array or NULL if no memory is
1023 *******************************************************************************/
1025 java_intarray *builtin_newarray_int(s4 size)
1027 return (java_intarray *)
1028 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1032 /* builtin_newarray_long *******************************************************
1034 Creates an array of 64 bit Integers on the heap.
1036 Return value: pointer to the array or NULL if no memory is
1039 *******************************************************************************/
1041 java_longarray *builtin_newarray_long(s4 size)
1043 return (java_longarray *)
1044 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1048 /* builtin_newarray_float ******************************************************
1050 Creates an array of 32 bit IEEE floats on the heap.
1052 Return value: pointer to the array or NULL if no memory is
1055 *******************************************************************************/
1057 java_floatarray *builtin_newarray_float(s4 size)
1059 return (java_floatarray *)
1060 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1064 /* builtin_newarray_double *****************************************************
1066 Creates an array of 64 bit IEEE floats on the heap.
1068 Return value: pointer to the array or NULL if no memory is
1071 *******************************************************************************/
1073 java_doublearray *builtin_newarray_double(s4 size)
1075 return (java_doublearray *)
1076 builtin_newarray(size,
1077 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1081 /* builtin_multianewarray_intern ***********************************************
1083 Creates a multi-dimensional array on the heap. The dimensions are
1084 passed in an array of longs.
1087 n............number of dimensions to create
1088 arrayvftbl...vftbl of the array class
1089 dims.........array containing the size of each dimension to create
1091 Return value: pointer to the array or NULL if no memory is
1094 ******************************************************************************/
1096 static java_arrayheader *builtin_multianewarray_intern(int n,
1097 classinfo *arrayclass,
1101 java_arrayheader *a;
1102 classinfo *componentclass;
1105 /* create this dimension */
1107 size = (s4) dims[0];
1108 a = builtin_newarray(size, arrayclass);
1113 /* if this is the last dimension return */
1118 /* get the class of the components to create */
1120 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1122 /* The verifier guarantees that the dimension count is in the range. */
1124 /* create the component arrays */
1126 for (i = 0; i < size; i++) {
1127 java_arrayheader *ea =
1128 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1129 /* we save an s4 to a s8 slot, 8-byte aligned */
1131 builtin_multianewarray_intern(n, componentclass, dims + 2);
1133 builtin_multianewarray_intern(n, componentclass, dims + 1);
1139 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1146 /* builtin_multianewarray ******************************************************
1148 Wrapper for builtin_multianewarray_intern which checks all
1149 dimensions before we start allocating.
1151 ******************************************************************************/
1153 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1159 /* check all dimensions before doing anything */
1161 for (i = 0; i < n; i++) {
1162 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1163 /* we save an s4 to a s8 slot, 8-byte aligned */
1164 size = (s4) dims[i * 2];
1166 size = (s4) dims[i];
1170 exceptions_throw_negativearraysizeexception();
1175 /* now call the real function */
1177 return builtin_multianewarray_intern(n, arrayclass, dims);
1181 /*****************************************************************************
1184 Various functions for printing a message at method entry or exit (for
1187 *****************************************************************************/
1189 #if !defined(NDEBUG)
1190 static s4 methodindent = 0;
1191 static u4 callcount = 0;
1193 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1203 if (opt_verbosecall && indent)
1206 /* calculate message length */
1210 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1213 logtextlen = strlen("Some Throwable");
1216 logtextlen += strlen(" thrown in ");
1220 utf_bytes(m->class->name) +
1222 utf_bytes(m->name) +
1223 utf_bytes(m->descriptor) +
1224 strlen("(NOSYNC,NATIVE");
1226 #if SIZEOF_VOID_P == 8
1228 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1230 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1233 if (m->class->sourcefile == NULL)
1234 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1236 logtextlen += utf_bytes(m->class->sourcefile);
1238 logtextlen += strlen(":65536)");
1242 logtextlen += strlen("call_java_method");
1245 logtextlen += strlen("0");
1247 /* allocate memory */
1249 dumpsize = dump_size();
1251 logtext = DMNEW(char, logtextlen);
1254 strcpy(logtext, "Exception ");
1255 utf_cat_classname(logtext, xptr->vftbl->class->name);
1258 strcpy(logtext, "Some Throwable");
1261 strcat(logtext, " thrown in ");
1264 utf_cat_classname(logtext, m->class->name);
1265 strcat(logtext, ".");
1266 utf_cat(logtext, m->name);
1267 utf_cat(logtext, m->descriptor);
1269 if (m->flags & ACC_SYNCHRONIZED)
1270 strcat(logtext, "(SYNC");
1272 strcat(logtext, "(NOSYNC");
1274 if (m->flags & ACC_NATIVE) {
1275 strcat(logtext, ",NATIVE");
1279 #if SIZEOF_VOID_P == 8
1280 sprintf(logtext + strlen(logtext),
1281 ")(0x%016lx) at position 0x%016lx",
1282 (ptrint) code->entrypoint, (ptrint) pos);
1284 sprintf(logtext + strlen(logtext),
1285 ")(0x%08x) at position 0x%08x",
1286 (ptrint) code->entrypoint, (ptrint) pos);
1291 /* XXX preliminary: This should get the actual codeinfo */
1292 /* in which the exception happened. */
1295 #if SIZEOF_VOID_P == 8
1296 sprintf(logtext + strlen(logtext),
1297 ")(0x%016lx) at position 0x%016lx (",
1298 (ptrint) code->entrypoint, (ptrint) pos);
1300 sprintf(logtext + strlen(logtext),
1301 ")(0x%08x) at position 0x%08x (",
1302 (ptrint) code->entrypoint, (ptrint) pos);
1305 if (m->class->sourcefile == NULL)
1306 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1308 utf_cat(logtext, m->class->sourcefile);
1310 sprintf(logtext + strlen(logtext), ":%d)", 0);
1314 strcat(logtext, "call_java_method");
1318 /* release memory */
1320 dump_release(dumpsize);
1324 #endif /* !defined(NDEBUG) */
1327 /* builtin_print_argument ******************************************************
1329 Prints arguments and return values for the call trace.
1331 *******************************************************************************/
1333 #if !defined(NDEBUG)
1334 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1335 typedesc *paramtype, s8 value)
1338 java_objectheader *o;
1339 java_lang_String *s;
1344 switch (paramtype->type) {
1347 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1352 #if SIZEOF_VOID_P == 4
1353 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1355 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1361 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1366 #if SIZEOF_VOID_P == 4
1367 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1369 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1374 #if SIZEOF_VOID_P == 4
1375 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1377 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1380 /* cast to java.lang.Object */
1382 o = (java_objectheader *) (ptrint) value;
1384 /* check return argument for java.lang.Class or java.lang.String */
1387 if (o->vftbl->class == class_java_lang_String) {
1388 /* get java.lang.String object and the length of the
1391 s = (java_lang_String *) o;
1393 u = javastring_toutf(s, false);
1395 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1397 /* realloc memory for string length */
1399 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1402 /* convert to utf8 string and strcat it to the logtext */
1404 strcat(logtext, " (String = \"");
1405 utf_cat(logtext, u);
1406 strcat(logtext, "\")");
1409 if (o->vftbl->class == class_java_lang_Class) {
1410 /* if the object returned is a java.lang.Class
1411 cast it to classinfo structure and get the name
1414 c = (classinfo *) o;
1419 /* if the object returned is not a java.lang.String or
1420 a java.lang.Class just print the name of the class */
1422 u = o->vftbl->class->name;
1425 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1427 /* realloc memory for string length */
1429 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1432 /* strcat to the logtext */
1434 strcat(logtext, " (Class = \"");
1435 utf_cat_classname(logtext, u);
1436 strcat(logtext, "\")");
1443 #endif /* !defined(NDEBUG) */
1446 /* builtin_verbosecall_enter ***************************************************
1448 Print method call with arguments for -verbose:call.
1450 *******************************************************************************/
1452 #if !defined(NDEBUG)
1454 #ifdef TRACE_ARGS_NUM
1455 void builtin_verbosecall_enter(s8 a0, s8 a1,
1456 # if TRACE_ARGS_NUM >= 4
1459 # if TRACE_ARGS_NUM >= 6
1462 # if TRACE_ARGS_NUM == 8
1476 /* calculate message length */
1479 strlen("4294967295 ") +
1480 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1482 strlen("called: ") +
1483 utf_bytes(m->class->name) +
1485 utf_bytes(m->name) +
1486 utf_bytes(m->descriptor);
1488 /* Actually it's not possible to have all flags printed, but:
1493 strlen(" PRIVATE") +
1494 strlen(" PROTECTED") +
1497 strlen(" SYNCHRONIZED") +
1498 strlen(" VOLATILE") +
1499 strlen(" TRANSIENT") +
1501 strlen(" INTERFACE") +
1502 strlen(" ABSTRACT");
1504 /* add maximal argument length */
1508 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1509 strlen("...(255)") +
1512 /* allocate memory */
1514 dumpsize = dump_size();
1516 logtext = DMNEW(char, logtextlen);
1520 sprintf(logtext, "%10d ", callcount);
1521 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1523 pos = strlen(logtext);
1525 for (i = 0; i < methodindent; i++)
1526 logtext[pos++] = '\t';
1528 strcpy(logtext + pos, "called: ");
1530 utf_cat_classname(logtext, m->class->name);
1531 strcat(logtext, ".");
1532 utf_cat(logtext, m->name);
1533 utf_cat(logtext, m->descriptor);
1535 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1536 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1537 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1538 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1539 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1540 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1541 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1542 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1543 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1544 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1545 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1547 strcat(logtext, "(");
1549 if (md->paramcount >= 1) {
1550 logtext = builtin_print_argument(logtext, &logtextlen,
1551 &md->paramtypes[0], a0);
1554 if (md->paramcount >= 2) {
1555 strcat(logtext, ", ");
1557 logtext = builtin_print_argument(logtext, &logtextlen,
1558 &md->paramtypes[1], a1);
1561 #if TRACE_ARGS_NUM >= 4
1562 if (md->paramcount >= 3) {
1563 strcat(logtext, ", ");
1565 logtext = builtin_print_argument(logtext, &logtextlen,
1566 &md->paramtypes[2], a2);
1569 if (md->paramcount >= 4) {
1570 strcat(logtext, ", ");
1572 logtext = builtin_print_argument(logtext, &logtextlen,
1573 &md->paramtypes[3], a3);
1577 #if TRACE_ARGS_NUM >= 6
1578 if (md->paramcount >= 5) {
1579 strcat(logtext, ", ");
1581 logtext = builtin_print_argument(logtext, &logtextlen,
1582 &md->paramtypes[4], a4);
1585 if (md->paramcount >= 6) {
1586 strcat(logtext, ", ");
1588 logtext = builtin_print_argument(logtext, &logtextlen,
1589 &md->paramtypes[5], a5);
1593 #if TRACE_ARGS_NUM == 8
1594 if (md->paramcount >= 7) {
1595 strcat(logtext, ", ");
1597 logtext = builtin_print_argument(logtext, &logtextlen,
1598 &md->paramtypes[6], a6);
1601 if (md->paramcount >= 8) {
1602 strcat(logtext, ", ");
1604 logtext = builtin_print_argument(logtext, &logtextlen,
1605 &md->paramtypes[7], a7);
1609 if (md->paramcount > 8) {
1610 sprintf(logtext + strlen(logtext), ", ...(%d)",
1611 md->paramcount - TRACE_ARGS_NUM);
1614 strcat(logtext, ")");
1618 /* release memory */
1620 dump_release(dumpsize);
1625 #endif /* !defined(NDEBUG) */
1628 /* builtin_verbosecall_exit ****************************************************
1630 Print method exit for -verbose:call.
1632 *******************************************************************************/
1634 #if !defined(NDEBUG)
1635 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1647 /* calculate message length */
1650 strlen("4294967295 ") +
1651 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1653 strlen("finished: ") +
1654 utf_bytes(m->class->name) +
1656 utf_bytes(m->name) +
1657 utf_bytes(m->descriptor) +
1658 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1660 /* add maximal argument length */
1662 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1664 /* allocate memory */
1666 dumpsize = dump_size();
1668 logtext = DMNEW(char, logtextlen);
1670 /* outdent the log message */
1675 log_text("WARNING: unmatched methodindent--");
1677 /* generate the message */
1679 sprintf(logtext, " ");
1680 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1682 pos = strlen(logtext);
1684 for (i = 0; i < methodindent; i++)
1685 logtext[pos++] = '\t';
1687 strcpy(logtext + pos, "finished: ");
1688 utf_cat_classname(logtext, m->class->name);
1689 strcat(logtext, ".");
1690 utf_cat(logtext, m->name);
1691 utf_cat(logtext, m->descriptor);
1693 if (!IS_VOID_TYPE(md->returntype.type)) {
1694 strcat(logtext, "->");
1696 switch (md->returntype.type) {
1713 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1718 /* release memory */
1720 dump_release(dumpsize);
1722 #endif /* !defined(NDEBUG) */
1725 #if defined(ENABLE_CYCLES_STATS)
1726 void builtin_print_cycles_stats(FILE *file)
1728 fprintf(file,"builtin cylce count statistics:\n");
1730 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1731 CYCLES_STATS_PRINT(builtin_new ,file);
1735 #endif /* defined(ENABLE_CYCLES_STATS) */
1738 /*****************************************************************************
1739 MISCELLANEOUS HELPER FUNCTIONS
1740 *****************************************************************************/
1744 /*********** Functions for integer divisions *****************************
1746 On some systems (eg. DEC ALPHA), integer division is not supported by the
1747 CPU. These helper functions implement the missing functionality.
1749 ******************************************************************************/
1751 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1752 s4 builtin_idiv(s4 a, s4 b)
1761 s4 builtin_irem(s4 a, s4 b)
1769 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1772 /* functions for long arithmetics **********************************************
1774 On systems where 64 bit Integers are not supported by the CPU,
1775 these functions are needed.
1777 ******************************************************************************/
1779 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1780 s8 builtin_ladd(s8 a, s8 b)
1793 s8 builtin_lsub(s8 a, s8 b)
1806 s8 builtin_lneg(s8 a)
1818 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1821 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1822 s8 builtin_lmul(s8 a, s8 b)
1834 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1837 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1838 s8 builtin_ldiv(s8 a, s8 b)
1851 s8 builtin_lrem(s8 a, s8 b)
1863 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1866 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1867 s8 builtin_lshl(s8 a, s4 b)
1880 s8 builtin_lshr(s8 a, s4 b)
1893 s8 builtin_lushr(s8 a, s4 b)
1898 c = ((u8) a) >> (b & 63);
1905 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1908 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1909 s8 builtin_land(s8 a, s8 b)
1922 s8 builtin_lor(s8 a, s8 b)
1935 s8 builtin_lxor(s8 a, s8 b)
1947 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1950 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1951 s4 builtin_lcmp(s8 a, s8 b)
1965 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1968 /* functions for unsupported floating instructions ****************************/
1970 /* used to convert FLT_xxx defines into float values */
1972 static inline float intBitsToFloat(s4 i)
1981 /* used to convert DBL_xxx defines into double values */
1983 static inline float longBitsToDouble(s8 l)
1993 float builtin_fadd(float a, float b)
1995 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1996 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2007 if (copysignf(1.0, a) == copysignf(1.0, b))
2010 return intBitsToFloat(FLT_NAN);
2016 float builtin_fsub(float a, float b)
2018 return builtin_fadd(a, builtin_fneg(b));
2022 float builtin_fmul(float a, float b)
2024 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2025 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2027 if (finitef(b)) return a * b;
2029 if (a == 0) return intBitsToFloat(FLT_NAN);
2030 else return copysignf(b, copysignf(1.0, b)*a);
2035 if (b == 0) return intBitsToFloat(FLT_NAN);
2036 else return copysignf(a, copysignf(1.0, a)*b);
2039 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2045 /* builtin_ddiv ****************************************************************
2047 Implementation as described in VM Spec.
2049 *******************************************************************************/
2051 float builtin_fdiv(float a, float b)
2055 /* If neither value1' nor value2' is NaN, the sign of the result */
2056 /* is positive if both values have the same sign, negative if the */
2057 /* values have different signs. */
2063 /* If either value1' or value2' is NaN, the result is NaN. */
2065 return intBitsToFloat(FLT_NAN);
2068 /* Division of a finite value by an infinity results in a */
2069 /* signed zero, with the sign-producing rule just given. */
2071 /* is sign equal? */
2073 if (copysignf(1.0, a) == copysignf(1.0, b))
2082 /* If either value1' or value2' is NaN, the result is NaN. */
2084 return intBitsToFloat(FLT_NAN);
2086 } else if (finitef(b)) {
2087 /* Division of an infinity by a finite value results in a signed */
2088 /* infinity, with the sign-producing rule just given. */
2090 /* is sign equal? */
2092 if (copysignf(1.0, a) == copysignf(1.0, b))
2093 return intBitsToFloat(FLT_POSINF);
2095 return intBitsToFloat(FLT_NEGINF);
2098 /* Division of an infinity by an infinity results in NaN. */
2100 return intBitsToFloat(FLT_NAN);
2106 float builtin_fneg(float a)
2108 if (isnanf(a)) return a;
2110 if (finitef(a)) return -a;
2111 else return copysignf(a, -copysignf(1.0, a));
2114 #endif /* !SUPPORT_FLOAT */
2117 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2118 s4 builtin_fcmpl(float a, float b)
2126 if (!finitef(a) || !finitef(b)) {
2127 a = finitef(a) ? 0 : copysignf(1.0, a);
2128 b = finitef(b) ? 0 : copysignf(1.0, b);
2141 s4 builtin_fcmpg(float a, float b)
2143 if (isnanf(a)) return 1;
2144 if (isnanf(b)) return 1;
2145 if (!finitef(a) || !finitef(b)) {
2146 a = finitef(a) ? 0 : copysignf(1.0, a);
2147 b = finitef(b) ? 0 : copysignf(1.0, b);
2149 if (a > b) return 1;
2150 if (a == b) return 0;
2153 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2156 float builtin_frem(float a, float b)
2162 /* functions for unsupported double instructions ******************************/
2165 double builtin_dadd(double a, double b)
2167 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2168 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2170 if (finite(b)) return a + b;
2174 if (finite(b)) return a;
2176 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2177 else return longBitsToDouble(DBL_NAN);
2183 double builtin_dsub(double a, double b)
2185 return builtin_dadd(a, builtin_dneg(b));
2189 double builtin_dmul(double a, double b)
2191 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2192 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2194 if (finite(b)) return a * b;
2196 if (a == 0) return longBitsToDouble(DBL_NAN);
2197 else return copysign(b, copysign(1.0, b) * a);
2202 if (b == 0) return longBitsToDouble(DBL_NAN);
2203 else return copysign(a, copysign(1.0, a) * b);
2206 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2212 /* builtin_ddiv ****************************************************************
2214 Implementation as described in VM Spec.
2216 *******************************************************************************/
2218 double builtin_ddiv(double a, double b)
2222 /* If neither value1' nor value2' is NaN, the sign of the result */
2223 /* is positive if both values have the same sign, negative if the */
2224 /* values have different signs. */
2230 /* If either value1' or value2' is NaN, the result is NaN. */
2232 return longBitsToDouble(DBL_NAN);
2235 /* Division of a finite value by an infinity results in a */
2236 /* signed zero, with the sign-producing rule just given. */
2238 /* is sign equal? */
2240 if (copysign(1.0, a) == copysign(1.0, b))
2249 /* If either value1' or value2' is NaN, the result is NaN. */
2251 return longBitsToDouble(DBL_NAN);
2253 } else if (finite(b)) {
2254 /* Division of an infinity by a finite value results in a signed */
2255 /* infinity, with the sign-producing rule just given. */
2257 /* is sign equal? */
2259 if (copysign(1.0, a) == copysign(1.0, b))
2260 return longBitsToDouble(DBL_POSINF);
2262 return longBitsToDouble(DBL_NEGINF);
2265 /* Division of an infinity by an infinity results in NaN. */
2267 return longBitsToDouble(DBL_NAN);
2273 /* builtin_dneg ****************************************************************
2275 Implemented as described in VM Spec.
2277 *******************************************************************************/
2279 double builtin_dneg(double a)
2282 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2289 /* If the operand is a zero, the result is the zero of opposite */
2295 /* If the operand is an infinity, the result is the infinity of */
2296 /* opposite sign. */
2298 return copysign(a, -copysign(1.0, a));
2302 #endif /* !SUPPORT_DOUBLE */
2305 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2306 s4 builtin_dcmpl(double a, double b)
2314 if (!finite(a) || !finite(b)) {
2315 a = finite(a) ? 0 : copysign(1.0, a);
2316 b = finite(b) ? 0 : copysign(1.0, b);
2329 s4 builtin_dcmpg(double a, double b)
2337 if (!finite(a) || !finite(b)) {
2338 a = finite(a) ? 0 : copysign(1.0, a);
2339 b = finite(b) ? 0 : copysign(1.0, b);
2350 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2353 double builtin_drem(double a, double b)
2359 /* conversion operations ******************************************************/
2362 s8 builtin_i2l(s4 i)
2374 s4 builtin_l2i(s8 l)
2385 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2386 float builtin_i2f(s4 a)
2388 float f = (float) a;
2391 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2394 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2395 double builtin_i2d(s4 a)
2397 double d = (double) a;
2400 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2403 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2404 float builtin_l2f(s8 a)
2407 float f = (float) a;
2413 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2416 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2417 double builtin_l2d(s8 a)
2420 double d = (double) a;
2426 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2429 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2430 s4 builtin_f2i(float a)
2434 i = builtin_d2i((double) a);
2445 if (a < (-2147483648))
2446 return (-2147483648);
2449 f = copysignf((float) 1.0, a);
2452 return (-2147483648); */
2454 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2457 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2458 s8 builtin_f2l(float a)
2462 l = builtin_d2l((double) a);
2469 if (a > 9223372036854775807L)
2470 return 9223372036854775807L;
2471 if (a < (-9223372036854775808L))
2472 return (-9223372036854775808L);
2477 f = copysignf((float) 1.0, a);
2479 return 9223372036854775807L;
2480 return (-9223372036854775808L); */
2482 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2485 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2486 s4 builtin_d2i(double a)
2491 if (a >= 2147483647)
2493 if (a <= (-2147483647-1))
2494 return (-2147483647-1);
2499 d = copysign(1.0, a);
2502 return (-2147483647-1);
2504 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2507 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2508 s8 builtin_d2l(double a)
2513 if (a >= 9223372036854775807LL)
2514 return 9223372036854775807LL;
2515 if (a <= (-9223372036854775807LL-1))
2516 return (-9223372036854775807LL-1);
2521 d = copysign(1.0, a);
2523 return 9223372036854775807LL;
2524 return (-9223372036854775807LL-1);
2526 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2529 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2530 double builtin_f2d(float a)
2532 if (finitef(a)) return (double) a;
2535 return longBitsToDouble(DBL_NAN);
2537 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2541 float builtin_d2f(double a)
2547 return intBitsToFloat(FLT_NAN);
2549 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2552 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2555 /* builtin_arraycopy ***********************************************************
2557 Builtin for java.lang.System.arraycopy.
2559 ATTENTION: This builtin function returns a boolean value to signal
2560 the ICMD_BUILTIN if there was an exception.
2562 *******************************************************************************/
2564 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2565 java_arrayheader *dest, s4 destStart, s4 len)
2567 arraydescriptor *sdesc;
2568 arraydescriptor *ddesc;
2571 if ((src == NULL) || (dest == NULL)) {
2572 exceptions_throw_nullpointerexception();
2576 sdesc = src->objheader.vftbl->arraydesc;
2577 ddesc = dest->objheader.vftbl->arraydesc;
2579 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2580 exceptions_throw_arraystoreexception();
2584 /* we try to throw exception with the same message as SUN does */
2586 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2587 (srcStart + len < 0) || (srcStart + len > src->size) ||
2588 (destStart + len < 0) || (destStart + len > dest->size)) {
2589 exceptions_throw_arrayindexoutofboundsexception();
2593 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2594 /* We copy primitive values or references of exactly the same type */
2596 s4 dataoffset = sdesc->dataoffset;
2597 s4 componentsize = sdesc->componentsize;
2599 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2600 ((u1 *) src) + dataoffset + componentsize * srcStart,
2601 (size_t) len * componentsize);
2604 /* We copy references of different type */
2606 java_objectarray *oas = (java_objectarray *) src;
2607 java_objectarray *oad = (java_objectarray *) dest;
2609 if (destStart <= srcStart) {
2610 for (i = 0; i < len; i++) {
2611 java_objectheader *o = oas->data[srcStart + i];
2613 if (!builtin_canstore(oad, o)) {
2614 exceptions_throw_arraystoreexception();
2618 oad->data[destStart + i] = o;
2622 /* XXX this does not completely obey the specification!
2623 If an exception is thrown only the elements above the
2624 current index have been copied. The specification
2625 requires that only the elements *below* the current
2626 index have been copied before the throw. */
2628 for (i = len - 1; i >= 0; i--) {
2629 java_objectheader *o = oas->data[srcStart + i];
2631 if (!builtin_canstore(oad, o)) {
2632 exceptions_throw_arraystoreexception();
2636 oad->data[destStart + i] = o;
2645 /* builtin_currenttimemillis ***************************************************
2647 Return the current time in milliseconds.
2649 *******************************************************************************/
2651 s8 builtin_currenttimemillis(void)
2656 if (gettimeofday(&tv, NULL) == -1)
2657 vm_abort("gettimeofday failed: %s", strerror(errno));
2659 result = (s8) tv.tv_sec;
2661 result += (tv.tv_usec / 1000);
2667 /* builtin_clone ***************************************************************
2669 Function for cloning objects or arrays.
2671 *******************************************************************************/
2673 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2675 arraydescriptor *ad;
2676 java_arrayheader *ah;
2679 java_objectheader *co; /* cloned object header */
2681 /* get the array descriptor */
2683 ad = o->vftbl->arraydesc;
2685 /* we are cloning an array */
2688 ah = (java_arrayheader *) o;
2690 size = ad->dataoffset + ad->componentsize * ah->size;
2692 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2697 MCOPY(co, o, u1, size);
2699 #if defined(ENABLE_GC_CACAO)
2700 heap_init_objectheader(co, size);
2703 #if defined(ENABLE_THREADS)
2704 lock_init_object_lock(co);
2710 /* we are cloning a non-array */
2712 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2713 exceptions_throw_clonenotsupportedexception();
2717 /* get the class of the object */
2719 c = o->vftbl->class;
2721 /* create new object */
2723 co = builtin_new(c);
2728 MCOPY(co, o, u1, c->instancesize);
2730 #if defined(ENABLE_GC_CACAO)
2731 heap_init_objectheader(co, c->instancesize);
2734 #if defined(ENABLE_THREADS)
2735 lock_init_object_lock(co);
2743 * These are local overrides for various environment variables in Emacs.
2744 * Please do not remove this and leave it at the end of the file, where
2745 * Emacs will automagically detect them.
2746 * ---------------------------------------------------------------------
2749 * indent-tabs-mode: t
2753 * vim:noexpandtab:sw=4:ts=4: