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 7797 2007-04-23 20:12:39Z 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"
84 #if defined(ENABLE_VMLOG)
85 #include <vmlog_cacao.h>
89 /* include builtin tables *****************************************************/
91 #include "vm/builtintable.inc"
94 CYCLES_STATS_DECLARE(builtin_new ,100,5)
95 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
97 /* builtintable_init ***********************************************************
99 Parse the descriptors of builtin functions and create the parsed
102 *******************************************************************************/
104 static bool builtintable_init(void)
106 descriptor_pool *descpool;
108 builtintable_entry *bte;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* first add all descriptors to the pool */
128 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
129 /* create a utf8 string from descriptor */
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
134 /* release dump area */
136 dump_release(dumpsize);
142 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
143 bte->descriptor = utf_new_char(bte->cdescriptor);
145 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
146 dump_release(dumpsize);
151 for (bte = builtintable_function; bte->fp != NULL; bte++) {
152 bte->classname = utf_new_char(bte->cclassname);
153 bte->name = utf_new_char(bte->cname);
154 bte->descriptor = utf_new_char(bte->cdescriptor);
156 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
157 dump_release(dumpsize);
162 /* create the class reference table */
164 (void) descriptor_pool_create_classrefs(descpool, NULL);
166 /* allocate space for the parsed descriptors */
168 descriptor_pool_alloc_parsed_descriptors(descpool);
170 /* now parse all descriptors */
172 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
173 /* parse the descriptor, builtin is always static (no `this' pointer) */
175 bte->md = descriptor_pool_parse_method_descriptor(descpool,
179 /* generate a builtin stub if we need one */
181 if (bte->flags & BUILTINTABLE_FLAG_STUB)
182 codegen_generate_stub_builtin(bte);
185 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
186 bte->md = descriptor_pool_parse_method_descriptor(descpool,
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
192 bte->md = descriptor_pool_parse_method_descriptor(descpool,
197 /* release dump area */
199 dump_release(dumpsize);
205 /* builtintable_comparator *****************************************************
207 qsort comparator for the automatic builtin table.
209 *******************************************************************************/
211 static int builtintable_comparator(const void *a, const void *b)
213 builtintable_entry *bte1;
214 builtintable_entry *bte2;
216 bte1 = (builtintable_entry *) a;
217 bte2 = (builtintable_entry *) b;
219 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
223 /* builtintable_sort_automatic *************************************************
225 Sorts the automatic builtin table.
227 *******************************************************************************/
229 static void builtintable_sort_automatic(void)
233 /* calculate table size statically (`- 1' comment see builtintable.inc) */
235 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
237 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
238 builtintable_comparator);
242 /* builtin_init ****************************************************************
244 Initialize the global table of builtin functions.
246 *******************************************************************************/
248 bool builtin_init(void)
250 /* initialize the builtin tables */
252 if (!builtintable_init())
255 /* sort builtin tables */
257 builtintable_sort_automatic();
263 /* builtintable_get_internal ***************************************************
265 Finds an entry in the builtintable for internal functions and
266 returns the a pointer to the structure.
268 *******************************************************************************/
270 builtintable_entry *builtintable_get_internal(functionptr fp)
272 builtintable_entry *bte;
274 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
283 /* builtintable_get_automatic **************************************************
285 Finds an entry in the builtintable for functions which are replaced
286 automatically and returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_automatic(s4 opcode)
292 builtintable_entry *first;
293 builtintable_entry *last;
294 builtintable_entry *middle;
298 /* calculate table size statically (`- 1' comment see builtintable.inc) */
300 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
302 first = builtintable_automatic;
303 last = builtintable_automatic + entries;
305 while (entries > 0) {
307 middle = first + half;
309 if (middle->opcode < opcode) {
317 return (first != last ? first : NULL);
321 /* builtintable_replace_function ***********************************************
325 *******************************************************************************/
327 #if defined(ENABLE_JIT)
328 bool builtintable_replace_function(void *iptr_)
331 builtintable_entry *bte;
334 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
336 /* get name and descriptor of the function */
339 case ICMD_INVOKESTATIC:
340 /* The instruction MUST be resolved, otherwise we run into
341 lazy loading troubles. Anyway, we should/can only replace
342 very VM-close functions. */
344 if (INSTRUCTION_IS_UNRESOLVED(iptr))
347 mr = iptr->sx.s23.s3.fmiref;
354 /* search the function table */
356 for (bte = builtintable_function; bte->fp != NULL; bte++) {
357 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
358 (mr->name == bte->name) &&
359 (mr->descriptor == bte->descriptor)) {
361 /* set the values in the instruction */
363 iptr->opc = bte->opcode;
364 iptr->sx.s23.s3.bte = bte;
366 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
367 iptr->flags.bits |= INS_FLAG_CHECK;
369 iptr->flags.bits &= ~INS_FLAG_CHECK;
377 #endif /* defined(ENABLE_JIT) */
380 /*****************************************************************************
382 *****************************************************************************/
384 /* builtin_instanceof **********************************************************
386 Checks if an object is an instance of some given class (or subclass
387 of that class). If class is an interface, checks if the interface
390 Return value: 1 ... o is an instance of class or implements the interface
391 0 ... otherwise or if o == NULL
393 *******************************************************************************/
395 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
400 return class_isanysubclass(o->vftbl->class, class);
405 /* builtin_checkcast ***********************************************************
407 The same as builtin_instanceof except that 1 is returned when o ==
410 *******************************************************************************/
412 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
417 if (class_isanysubclass(o->vftbl->class, class))
424 /* builtin_descriptorscompatible ***********************************************
426 Checks if two array type descriptors are assignment compatible
428 Return value: 1 ... target = desc is possible
431 *******************************************************************************/
433 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
434 arraydescriptor *target)
439 if (desc->arraytype != target->arraytype)
442 if (desc->arraytype != ARRAYTYPE_OBJECT)
445 /* {both arrays are arrays of references} */
447 if (desc->dimension == target->dimension) {
448 /* an array which contains elements of interface types is
449 allowed to be casted to Object (JOWENN)*/
451 if ((desc->elementvftbl->baseval < 0) &&
452 (target->elementvftbl->baseval == 1))
455 return class_isanysubclass(desc->elementvftbl->class,
456 target->elementvftbl->class);
459 if (desc->dimension < target->dimension)
462 /* {desc has higher dimension than target} */
464 return class_isanysubclass(pseudo_class_Arraystub,
465 target->elementvftbl->class);
469 /* builtin_arraycheckcast ******************************************************
471 Checks if an object is really a subtype of the requested array
472 type. The object has to be an array to begin with. For simple
473 arrays (int, short, double, etc.) the types have to match exactly.
474 For arrays of objects, the type of elements in the array has to be
475 a subtype (or the same type) of the requested element type. For
476 arrays of arrays (which in turn can again be arrays of arrays), the
477 types at the lowest level have to satisfy the corresponding sub
480 *******************************************************************************/
482 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
484 arraydescriptor *desc;
489 desc = o->vftbl->arraydesc;
494 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
498 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
503 return builtin_arraycheckcast(o, targetclass);
507 /* builtin_throw_exception *****************************************************
509 Sets the exceptionptr with the thrown exception and prints some
510 debugging information. Called from asm_vm_call_method.
512 *******************************************************************************/
514 void *builtin_throw_exception(java_objectheader *xptr)
517 java_lang_Throwable *t;
523 t = (java_lang_Throwable *) xptr;
525 /* calculate message length */
527 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
531 utf_bytes(xptr->vftbl->class->name);
532 if (t->detailMessage) {
533 logtextlen += strlen(": ") +
534 u2_utflength(t->detailMessage->value->data
535 + t->detailMessage->offset,
536 t->detailMessage->count);
540 logtextlen += strlen("(nil)");
543 /* allocate memory */
545 dumpsize = dump_size();
547 logtext = DMNEW(char, logtextlen);
549 strcpy(logtext, "Builtin exception thrown: ");
552 utf_cat_classname(logtext, xptr->vftbl->class->name);
554 if (t->detailMessage) {
557 buf = javastring_tochar((java_objectheader *) t->detailMessage);
558 strcat(logtext, ": ");
559 strcat(logtext, buf);
560 MFREE(buf, char, strlen(buf) + 1);
564 strcat(logtext, "(nil)");
571 dump_release(dumpsize);
573 #endif /* !defined(NDEBUG) */
575 /* actually set the exception */
577 exceptions_set_exception(xptr);
579 /* Return a NULL pointer. This is required for vm_call_method to
580 check for an exception. This is for convenience. */
586 /* builtin_canstore ************************************************************
588 Checks, if an object can be stored in an array.
590 Return value: 1 ... possible
591 0 ... otherwise (throws an ArrayStoreException)
593 *******************************************************************************/
595 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
597 arraydescriptor *desc;
598 arraydescriptor *valuedesc;
599 vftbl_t *componentvftbl;
602 castinfo classvalues;
608 /* The following is guaranteed (by verifier checks):
610 * *) oa->...vftbl->arraydesc != NULL
611 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
612 * *) o->vftbl is not an interface vftbl
615 desc = oa->header.objheader.vftbl->arraydesc;
616 componentvftbl = desc->componentvftbl;
617 valuevftbl = o->vftbl;
618 valuedesc = valuevftbl->arraydesc;
620 if ((desc->dimension - 1) == 0) {
621 /* {oa is a one-dimensional array} */
622 /* {oa is an array of references} */
624 if (valuevftbl == componentvftbl)
627 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
629 base = classvalues.super_baseval;
632 /* an array of interface references */
634 result = ((valuevftbl->interfacetablelength > -base) &&
635 (valuevftbl->interfacetable[base] != NULL));
638 result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
639 <= (unsigned) classvalues.super_diffval);
642 else if (valuedesc == NULL) {
643 /* {oa has dimension > 1} */
644 /* {componentvftbl->arraydesc != NULL} */
646 /* check if o is an array */
651 /* {o is an array} */
653 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
656 /* if not possible, throw an exception */
659 exceptions_throw_arraystoreexception();
667 /* This is an optimized version where a is guaranteed to be one-dimensional */
668 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
670 arraydescriptor *desc;
671 vftbl_t *elementvftbl;
675 castinfo classvalues;
679 /* The following is guaranteed (by verifier checks):
681 * *) a->...vftbl->arraydesc != NULL
682 * *) a->...vftbl->arraydesc->elementvftbl != NULL
683 * *) a->...vftbl->arraydesc->dimension == 1
684 * *) o->vftbl is not an interface vftbl
687 desc = a->header.objheader.vftbl->arraydesc;
688 elementvftbl = desc->elementvftbl;
689 valuevftbl = o->vftbl;
691 /* {a is a one-dimensional array} */
693 if (valuevftbl == elementvftbl)
696 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
698 if ((base = classvalues.super_baseval) <= 0)
699 /* an array of interface references */
700 return (valuevftbl->interfacetablelength > -base &&
701 valuevftbl->interfacetable[base] != NULL);
703 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
704 <= (unsigned) classvalues.super_diffval;
710 /* This is an optimized version where a is guaranteed to be a
711 * one-dimensional array of a class type */
712 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
714 vftbl_t *elementvftbl;
717 castinfo classvalues;
721 /* The following is guaranteed (by verifier checks):
723 * *) a->...vftbl->arraydesc != NULL
724 * *) a->...vftbl->arraydesc->elementvftbl != NULL
725 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
726 * *) a->...vftbl->arraydesc->dimension == 1
727 * *) o->vftbl is not an interface vftbl
730 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
731 valuevftbl = o->vftbl;
733 /* {a is a one-dimensional array} */
735 if (valuevftbl == elementvftbl)
738 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
740 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
741 <= (unsigned) classvalues.super_diffval;
747 /* builtin_new *****************************************************************
749 Creates a new instance of class c on the heap.
751 Return value: pointer to the object or NULL if no memory is
754 *******************************************************************************/
756 java_objectheader *builtin_new(classinfo *c)
758 java_objectheader *o;
759 #if defined(ENABLE_RT_TIMING)
760 struct timespec time_start, time_end;
762 #if defined(ENABLE_CYCLES_STATS)
763 u8 cycles_start, cycles_end;
766 RT_TIMING_GET_TIME(time_start);
767 CYCLES_STATS_GET(cycles_start);
769 /* is the class loaded */
771 assert(c->state & CLASS_LOADED);
773 /* check if we can instantiate this class */
775 if (c->flags & ACC_ABSTRACT) {
776 exceptions_throw_instantiationerror(c);
780 /* is the class linked */
782 if (!(c->state & CLASS_LINKED))
786 if (!(c->state & CLASS_INITIALIZED)) {
789 log_message_class("Initialize class (from builtin_new): ", c);
792 if (!initialize_class(c))
796 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
804 #if defined(ENABLE_THREADS)
805 lock_init_object_lock(o);
808 CYCLES_STATS_GET(cycles_end);
809 RT_TIMING_GET_TIME(time_end);
811 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
812 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
818 /* builtin_fast_new ************************************************************
820 Creates a new instance of class c on the heap.
822 Return value: pointer to the object or NULL if no fast return
823 is possible for any reason.
825 *******************************************************************************/
827 java_objectheader *builtin_fast_new(classinfo *c)
829 java_objectheader *o;
830 #if defined(ENABLE_RT_TIMING)
831 struct timespec time_start, time_end;
833 #if defined(ENABLE_CYCLES_STATS)
834 u8 cycles_start, cycles_end;
837 RT_TIMING_GET_TIME(time_start);
838 CYCLES_STATS_GET(cycles_start);
840 /* is the class loaded */
842 assert(c->state & CLASS_LOADED);
844 /* check if we can instantiate this class */
846 if (c->flags & ACC_ABSTRACT)
849 /* is the class linked */
851 if (!(c->state & CLASS_LINKED))
854 if (!(c->state & CLASS_INITIALIZED))
857 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
858 c->finalizer, false);
865 #if defined(ENABLE_THREADS)
866 lock_init_object_lock(o);
869 CYCLES_STATS_GET(cycles_end);
870 RT_TIMING_GET_TIME(time_end);
872 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
873 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
879 /* builtin_newarray ************************************************************
881 Creates an array with the given vftbl on the heap. This function
882 takes as class argument an array class.
884 Return value: pointer to the array or NULL if no memory is available
886 *******************************************************************************/
888 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
890 arraydescriptor *desc;
895 #if defined(ENABLE_RT_TIMING)
896 struct timespec time_start, time_end;
899 RT_TIMING_GET_TIME(time_start);
901 desc = arrayclass->vftbl->arraydesc;
902 dataoffset = desc->dataoffset;
903 componentsize = desc->componentsize;
906 exceptions_throw_negativearraysizeexception();
910 actualsize = dataoffset + size * componentsize;
912 /* check for overflow */
914 if (((u4) actualsize) < ((u4) size)) {
915 exceptions_throw_outofmemoryerror();
919 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
924 a->objheader.vftbl = arrayclass->vftbl;
926 #if defined(ENABLE_THREADS)
927 lock_init_object_lock(&a->objheader);
932 RT_TIMING_GET_TIME(time_end);
933 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
939 /* builtin_anewarray ***********************************************************
941 Creates an array of references to the given class type on the heap.
943 Return value: pointer to the array or NULL if no memory is
946 *******************************************************************************/
948 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
950 classinfo *arrayclass;
952 /* is class loaded */
954 assert(componentclass->state & CLASS_LOADED);
956 /* is class linked */
958 if (!(componentclass->state & CLASS_LINKED))
959 if (!link_class(componentclass))
962 arrayclass = class_array_of(componentclass, true);
967 return (java_objectarray *) builtin_newarray(size, arrayclass);
971 /* builtin_newarray_boolean ****************************************************
973 Creates an array of bytes on the heap. The array is designated as
974 an array of booleans (important for casts)
976 Return value: pointer to the array or NULL if no memory is
979 *******************************************************************************/
981 java_booleanarray *builtin_newarray_boolean(s4 size)
983 return (java_booleanarray *)
984 builtin_newarray(size,
985 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
989 /* builtin_newarray_byte *******************************************************
991 Creates an array of 8 bit Integers on the heap.
993 Return value: pointer to the array or NULL if no memory is
996 *******************************************************************************/
998 java_bytearray *builtin_newarray_byte(s4 size)
1000 return (java_bytearray *)
1001 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1005 /* builtin_newarray_char *******************************************************
1007 Creates an array of characters on the heap.
1009 Return value: pointer to the array or NULL if no memory is
1012 *******************************************************************************/
1014 java_chararray *builtin_newarray_char(s4 size)
1016 return (java_chararray *)
1017 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1021 /* builtin_newarray_short ******************************************************
1023 Creates an array of 16 bit Integers on the heap.
1025 Return value: pointer to the array or NULL if no memory is
1028 *******************************************************************************/
1030 java_shortarray *builtin_newarray_short(s4 size)
1032 return (java_shortarray *)
1033 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1037 /* builtin_newarray_int ********************************************************
1039 Creates an array of 32 bit Integers on the heap.
1041 Return value: pointer to the array or NULL if no memory is
1044 *******************************************************************************/
1046 java_intarray *builtin_newarray_int(s4 size)
1048 return (java_intarray *)
1049 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1053 /* builtin_newarray_long *******************************************************
1055 Creates an array of 64 bit Integers on the heap.
1057 Return value: pointer to the array or NULL if no memory is
1060 *******************************************************************************/
1062 java_longarray *builtin_newarray_long(s4 size)
1064 return (java_longarray *)
1065 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1069 /* builtin_newarray_float ******************************************************
1071 Creates an array of 32 bit IEEE floats on the heap.
1073 Return value: pointer to the array or NULL if no memory is
1076 *******************************************************************************/
1078 java_floatarray *builtin_newarray_float(s4 size)
1080 return (java_floatarray *)
1081 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1085 /* builtin_newarray_double *****************************************************
1087 Creates an array of 64 bit IEEE floats on the heap.
1089 Return value: pointer to the array or NULL if no memory is
1092 *******************************************************************************/
1094 java_doublearray *builtin_newarray_double(s4 size)
1096 return (java_doublearray *)
1097 builtin_newarray(size,
1098 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1102 /* builtin_multianewarray_intern ***********************************************
1104 Creates a multi-dimensional array on the heap. The dimensions are
1105 passed in an array of longs.
1108 n............number of dimensions to create
1109 arrayvftbl...vftbl of the array class
1110 dims.........array containing the size of each dimension to create
1112 Return value: pointer to the array or NULL if no memory is
1115 ******************************************************************************/
1117 static java_arrayheader *builtin_multianewarray_intern(int n,
1118 classinfo *arrayclass,
1122 java_arrayheader *a;
1123 classinfo *componentclass;
1126 /* create this dimension */
1128 size = (s4) dims[0];
1129 a = builtin_newarray(size, arrayclass);
1134 /* if this is the last dimension return */
1139 /* get the class of the components to create */
1141 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1143 /* The verifier guarantees that the dimension count is in the range. */
1145 /* create the component arrays */
1147 for (i = 0; i < size; i++) {
1148 java_arrayheader *ea =
1149 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1150 /* we save an s4 to a s8 slot, 8-byte aligned */
1152 builtin_multianewarray_intern(n, componentclass, dims + 2);
1154 builtin_multianewarray_intern(n, componentclass, dims + 1);
1160 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1167 /* builtin_multianewarray ******************************************************
1169 Wrapper for builtin_multianewarray_intern which checks all
1170 dimensions before we start allocating.
1172 ******************************************************************************/
1174 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1180 /* check all dimensions before doing anything */
1182 for (i = 0; i < n; i++) {
1183 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1184 /* we save an s4 to a s8 slot, 8-byte aligned */
1185 size = (s4) dims[i * 2];
1187 size = (s4) dims[i];
1191 exceptions_throw_negativearraysizeexception();
1196 /* now call the real function */
1198 return builtin_multianewarray_intern(n, arrayclass, dims);
1202 /*****************************************************************************
1205 Various functions for printing a message at method entry or exit (for
1208 *****************************************************************************/
1210 #if !defined(NDEBUG)
1211 static s4 methodindent = 0;
1212 static u4 callcount = 0;
1214 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1224 #if defined(ENABLE_VMLOG)
1228 if (opt_verbosecall && indent)
1231 /* calculate message length */
1235 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1238 logtextlen = strlen("Some Throwable");
1241 logtextlen += strlen(" thrown in ");
1245 utf_bytes(m->class->name) +
1247 utf_bytes(m->name) +
1248 utf_bytes(m->descriptor) +
1249 strlen("(NOSYNC,NATIVE");
1251 #if SIZEOF_VOID_P == 8
1253 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1255 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1258 if (m->class->sourcefile == NULL)
1259 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1261 logtextlen += utf_bytes(m->class->sourcefile);
1263 logtextlen += strlen(":65536)");
1267 logtextlen += strlen("call_java_method");
1270 logtextlen += strlen("0");
1272 /* allocate memory */
1274 dumpsize = dump_size();
1276 logtext = DMNEW(char, logtextlen);
1279 strcpy(logtext, "Exception ");
1280 utf_cat_classname(logtext, xptr->vftbl->class->name);
1283 strcpy(logtext, "Some Throwable");
1286 strcat(logtext, " thrown in ");
1289 utf_cat_classname(logtext, m->class->name);
1290 strcat(logtext, ".");
1291 utf_cat(logtext, m->name);
1292 utf_cat(logtext, m->descriptor);
1294 if (m->flags & ACC_SYNCHRONIZED)
1295 strcat(logtext, "(SYNC");
1297 strcat(logtext, "(NOSYNC");
1299 if (m->flags & ACC_NATIVE) {
1300 strcat(logtext, ",NATIVE");
1304 #if SIZEOF_VOID_P == 8
1305 sprintf(logtext + strlen(logtext),
1306 ")(0x%016lx) at position 0x%016lx",
1307 (ptrint) code->entrypoint, (ptrint) pos);
1309 sprintf(logtext + strlen(logtext),
1310 ")(0x%08x) at position 0x%08x",
1311 (ptrint) code->entrypoint, (ptrint) pos);
1316 /* XXX preliminary: This should get the actual codeinfo */
1317 /* in which the exception happened. */
1320 #if SIZEOF_VOID_P == 8
1321 sprintf(logtext + strlen(logtext),
1322 ")(0x%016lx) at position 0x%016lx (",
1323 (ptrint) code->entrypoint, (ptrint) pos);
1325 sprintf(logtext + strlen(logtext),
1326 ")(0x%08x) at position 0x%08x (",
1327 (ptrint) code->entrypoint, (ptrint) pos);
1330 if (m->class->sourcefile == NULL)
1331 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1333 utf_cat(logtext, m->class->sourcefile);
1335 sprintf(logtext + strlen(logtext), ":%d)", 0);
1339 strcat(logtext, "call_java_method");
1343 /* release memory */
1345 dump_release(dumpsize);
1349 #endif /* !defined(NDEBUG) */
1352 /* builtin_print_argument ******************************************************
1354 Prints arguments and return values for the call trace.
1356 *******************************************************************************/
1358 #if !defined(NDEBUG)
1359 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1360 typedesc *paramtype, s8 value)
1363 java_objectheader *o;
1368 switch (paramtype->type) {
1371 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1376 #if SIZEOF_VOID_P == 4
1377 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1379 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1385 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1390 #if SIZEOF_VOID_P == 4
1391 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1393 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1398 #if SIZEOF_VOID_P == 4
1399 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1401 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1404 /* cast to java.lang.Object */
1406 o = (java_objectheader *) (ptrint) value;
1408 /* check return argument for java.lang.Class or java.lang.String */
1411 if (o->vftbl->class == class_java_lang_String) {
1412 /* get java.lang.String object and the length of the
1415 u = javastring_toutf(o, false);
1417 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1419 /* realloc memory for string length */
1421 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1424 /* convert to utf8 string and strcat it to the logtext */
1426 strcat(logtext, " (String = \"");
1427 utf_cat(logtext, u);
1428 strcat(logtext, "\")");
1431 if (o->vftbl->class == class_java_lang_Class) {
1432 /* if the object returned is a java.lang.Class
1433 cast it to classinfo structure and get the name
1436 c = (classinfo *) o;
1441 /* if the object returned is not a java.lang.String or
1442 a java.lang.Class just print the name of the class */
1444 u = o->vftbl->class->name;
1447 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1449 /* realloc memory for string length */
1451 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1454 /* strcat to the logtext */
1456 strcat(logtext, " (Class = \"");
1457 utf_cat_classname(logtext, u);
1458 strcat(logtext, "\")");
1465 #endif /* !defined(NDEBUG) */
1468 /* builtin_verbosecall_enter ***************************************************
1470 Print method call with arguments for -verbose:call.
1472 *******************************************************************************/
1474 #if !defined(NDEBUG)
1476 #ifdef TRACE_ARGS_NUM
1477 void builtin_verbosecall_enter(s8 a0, s8 a1,
1478 # if TRACE_ARGS_NUM >= 4
1481 # if TRACE_ARGS_NUM >= 6
1484 # if TRACE_ARGS_NUM == 8
1496 #if defined(ENABLE_VMLOG)
1497 vmlog_cacao_enter_method(m);
1503 /* calculate message length */
1506 strlen("4294967295 ") +
1507 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1509 strlen("called: ") +
1510 utf_bytes(m->class->name) +
1512 utf_bytes(m->name) +
1513 utf_bytes(m->descriptor);
1515 /* Actually it's not possible to have all flags printed, but:
1520 strlen(" PRIVATE") +
1521 strlen(" PROTECTED") +
1524 strlen(" SYNCHRONIZED") +
1525 strlen(" VOLATILE") +
1526 strlen(" TRANSIENT") +
1528 strlen(" INTERFACE") +
1529 strlen(" ABSTRACT");
1531 /* add maximal argument length */
1535 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1536 strlen("...(255)") +
1539 /* allocate memory */
1541 dumpsize = dump_size();
1543 logtext = DMNEW(char, logtextlen);
1547 sprintf(logtext, "%10d ", callcount);
1548 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1550 pos = strlen(logtext);
1552 for (i = 0; i < methodindent; i++)
1553 logtext[pos++] = '\t';
1555 strcpy(logtext + pos, "called: ");
1557 utf_cat_classname(logtext, m->class->name);
1558 strcat(logtext, ".");
1559 utf_cat(logtext, m->name);
1560 utf_cat(logtext, m->descriptor);
1562 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1563 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1564 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1565 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1566 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1567 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1568 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1569 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1570 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1571 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1572 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1574 strcat(logtext, "(");
1576 if (md->paramcount >= 1) {
1577 logtext = builtin_print_argument(logtext, &logtextlen,
1578 &md->paramtypes[0], a0);
1581 if (md->paramcount >= 2) {
1582 strcat(logtext, ", ");
1584 logtext = builtin_print_argument(logtext, &logtextlen,
1585 &md->paramtypes[1], a1);
1588 #if TRACE_ARGS_NUM >= 4
1589 if (md->paramcount >= 3) {
1590 strcat(logtext, ", ");
1592 logtext = builtin_print_argument(logtext, &logtextlen,
1593 &md->paramtypes[2], a2);
1596 if (md->paramcount >= 4) {
1597 strcat(logtext, ", ");
1599 logtext = builtin_print_argument(logtext, &logtextlen,
1600 &md->paramtypes[3], a3);
1604 #if TRACE_ARGS_NUM >= 6
1605 if (md->paramcount >= 5) {
1606 strcat(logtext, ", ");
1608 logtext = builtin_print_argument(logtext, &logtextlen,
1609 &md->paramtypes[4], a4);
1612 if (md->paramcount >= 6) {
1613 strcat(logtext, ", ");
1615 logtext = builtin_print_argument(logtext, &logtextlen,
1616 &md->paramtypes[5], a5);
1620 #if TRACE_ARGS_NUM == 8
1621 if (md->paramcount >= 7) {
1622 strcat(logtext, ", ");
1624 logtext = builtin_print_argument(logtext, &logtextlen,
1625 &md->paramtypes[6], a6);
1628 if (md->paramcount >= 8) {
1629 strcat(logtext, ", ");
1631 logtext = builtin_print_argument(logtext, &logtextlen,
1632 &md->paramtypes[7], a7);
1636 if (md->paramcount > 8) {
1637 sprintf(logtext + strlen(logtext), ", ...(%d)",
1638 md->paramcount - TRACE_ARGS_NUM);
1641 strcat(logtext, ")");
1645 /* release memory */
1647 dump_release(dumpsize);
1652 #endif /* !defined(NDEBUG) */
1655 /* builtin_verbosecall_exit ****************************************************
1657 Print method exit for -verbose:call.
1659 *******************************************************************************/
1661 #if !defined(NDEBUG)
1662 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1672 #if defined(ENABLE_VMLOG)
1673 vmlog_cacao_leave_method(m);
1679 /* calculate message length */
1682 strlen("4294967295 ") +
1683 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1685 strlen("finished: ") +
1686 utf_bytes(m->class->name) +
1688 utf_bytes(m->name) +
1689 utf_bytes(m->descriptor) +
1690 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1692 /* add maximal argument length */
1694 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1696 /* allocate memory */
1698 dumpsize = dump_size();
1700 logtext = DMNEW(char, logtextlen);
1702 /* outdent the log message */
1707 log_text("WARNING: unmatched methodindent--");
1709 /* generate the message */
1711 sprintf(logtext, " ");
1712 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1714 pos = strlen(logtext);
1716 for (i = 0; i < methodindent; i++)
1717 logtext[pos++] = '\t';
1719 strcpy(logtext + pos, "finished: ");
1720 utf_cat_classname(logtext, m->class->name);
1721 strcat(logtext, ".");
1722 utf_cat(logtext, m->name);
1723 utf_cat(logtext, m->descriptor);
1725 if (!IS_VOID_TYPE(md->returntype.type)) {
1726 strcat(logtext, "->");
1728 switch (md->returntype.type) {
1745 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1750 /* release memory */
1752 dump_release(dumpsize);
1754 #endif /* !defined(NDEBUG) */
1757 #if defined(ENABLE_CYCLES_STATS)
1758 void builtin_print_cycles_stats(FILE *file)
1760 fprintf(file,"builtin cylce count statistics:\n");
1762 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1763 CYCLES_STATS_PRINT(builtin_new ,file);
1767 #endif /* defined(ENABLE_CYCLES_STATS) */
1770 /*****************************************************************************
1771 MISCELLANEOUS HELPER FUNCTIONS
1772 *****************************************************************************/
1776 /*********** Functions for integer divisions *****************************
1778 On some systems (eg. DEC ALPHA), integer division is not supported by the
1779 CPU. These helper functions implement the missing functionality.
1781 ******************************************************************************/
1783 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1784 s4 builtin_idiv(s4 a, s4 b)
1793 s4 builtin_irem(s4 a, s4 b)
1801 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1804 /* functions for long arithmetics **********************************************
1806 On systems where 64 bit Integers are not supported by the CPU,
1807 these functions are needed.
1809 ******************************************************************************/
1811 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1812 s8 builtin_ladd(s8 a, s8 b)
1825 s8 builtin_lsub(s8 a, s8 b)
1838 s8 builtin_lneg(s8 a)
1850 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1853 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1854 s8 builtin_lmul(s8 a, s8 b)
1866 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1869 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1870 s8 builtin_ldiv(s8 a, s8 b)
1883 s8 builtin_lrem(s8 a, s8 b)
1895 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1898 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1899 s8 builtin_lshl(s8 a, s4 b)
1912 s8 builtin_lshr(s8 a, s4 b)
1925 s8 builtin_lushr(s8 a, s4 b)
1930 c = ((u8) a) >> (b & 63);
1937 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1940 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1941 s8 builtin_land(s8 a, s8 b)
1954 s8 builtin_lor(s8 a, s8 b)
1967 s8 builtin_lxor(s8 a, s8 b)
1979 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1982 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1983 s4 builtin_lcmp(s8 a, s8 b)
1997 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2000 /* functions for unsupported floating instructions ****************************/
2002 /* used to convert FLT_xxx defines into float values */
2004 static inline float intBitsToFloat(s4 i)
2013 /* used to convert DBL_xxx defines into double values */
2015 static inline float longBitsToDouble(s8 l)
2025 float builtin_fadd(float a, float b)
2027 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2028 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2039 if (copysignf(1.0, a) == copysignf(1.0, b))
2042 return intBitsToFloat(FLT_NAN);
2048 float builtin_fsub(float a, float b)
2050 return builtin_fadd(a, builtin_fneg(b));
2054 float builtin_fmul(float a, float b)
2056 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2057 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2059 if (finitef(b)) return a * b;
2061 if (a == 0) return intBitsToFloat(FLT_NAN);
2062 else return copysignf(b, copysignf(1.0, b)*a);
2067 if (b == 0) return intBitsToFloat(FLT_NAN);
2068 else return copysignf(a, copysignf(1.0, a)*b);
2071 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2077 /* builtin_ddiv ****************************************************************
2079 Implementation as described in VM Spec.
2081 *******************************************************************************/
2083 float builtin_fdiv(float a, float b)
2087 /* If neither value1' nor value2' is NaN, the sign of the result */
2088 /* is positive if both values have the same sign, negative if the */
2089 /* values have different signs. */
2095 /* If either value1' or value2' is NaN, the result is NaN. */
2097 return intBitsToFloat(FLT_NAN);
2100 /* Division of a finite value by an infinity results in a */
2101 /* signed zero, with the sign-producing rule just given. */
2103 /* is sign equal? */
2105 if (copysignf(1.0, a) == copysignf(1.0, b))
2114 /* If either value1' or value2' is NaN, the result is NaN. */
2116 return intBitsToFloat(FLT_NAN);
2118 } else if (finitef(b)) {
2119 /* Division of an infinity by a finite value results in a signed */
2120 /* infinity, with the sign-producing rule just given. */
2122 /* is sign equal? */
2124 if (copysignf(1.0, a) == copysignf(1.0, b))
2125 return intBitsToFloat(FLT_POSINF);
2127 return intBitsToFloat(FLT_NEGINF);
2130 /* Division of an infinity by an infinity results in NaN. */
2132 return intBitsToFloat(FLT_NAN);
2138 float builtin_fneg(float a)
2140 if (isnanf(a)) return a;
2142 if (finitef(a)) return -a;
2143 else return copysignf(a, -copysignf(1.0, a));
2146 #endif /* !SUPPORT_FLOAT */
2149 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2150 s4 builtin_fcmpl(float a, float b)
2158 if (!finitef(a) || !finitef(b)) {
2159 a = finitef(a) ? 0 : copysignf(1.0, a);
2160 b = finitef(b) ? 0 : copysignf(1.0, b);
2173 s4 builtin_fcmpg(float a, float b)
2175 if (isnanf(a)) return 1;
2176 if (isnanf(b)) return 1;
2177 if (!finitef(a) || !finitef(b)) {
2178 a = finitef(a) ? 0 : copysignf(1.0, a);
2179 b = finitef(b) ? 0 : copysignf(1.0, b);
2181 if (a > b) return 1;
2182 if (a == b) return 0;
2185 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2188 float builtin_frem(float a, float b)
2194 /* functions for unsupported double instructions ******************************/
2197 double builtin_dadd(double a, double b)
2199 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2200 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2202 if (finite(b)) return a + b;
2206 if (finite(b)) return a;
2208 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2209 else return longBitsToDouble(DBL_NAN);
2215 double builtin_dsub(double a, double b)
2217 return builtin_dadd(a, builtin_dneg(b));
2221 double builtin_dmul(double a, double b)
2223 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2224 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2226 if (finite(b)) return a * b;
2228 if (a == 0) return longBitsToDouble(DBL_NAN);
2229 else return copysign(b, copysign(1.0, b) * a);
2234 if (b == 0) return longBitsToDouble(DBL_NAN);
2235 else return copysign(a, copysign(1.0, a) * b);
2238 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2244 /* builtin_ddiv ****************************************************************
2246 Implementation as described in VM Spec.
2248 *******************************************************************************/
2250 double builtin_ddiv(double a, double b)
2254 /* If neither value1' nor value2' is NaN, the sign of the result */
2255 /* is positive if both values have the same sign, negative if the */
2256 /* values have different signs. */
2262 /* If either value1' or value2' is NaN, the result is NaN. */
2264 return longBitsToDouble(DBL_NAN);
2267 /* Division of a finite value by an infinity results in a */
2268 /* signed zero, with the sign-producing rule just given. */
2270 /* is sign equal? */
2272 if (copysign(1.0, a) == copysign(1.0, b))
2281 /* If either value1' or value2' is NaN, the result is NaN. */
2283 return longBitsToDouble(DBL_NAN);
2285 } else if (finite(b)) {
2286 /* Division of an infinity by a finite value results in a signed */
2287 /* infinity, with the sign-producing rule just given. */
2289 /* is sign equal? */
2291 if (copysign(1.0, a) == copysign(1.0, b))
2292 return longBitsToDouble(DBL_POSINF);
2294 return longBitsToDouble(DBL_NEGINF);
2297 /* Division of an infinity by an infinity results in NaN. */
2299 return longBitsToDouble(DBL_NAN);
2305 /* builtin_dneg ****************************************************************
2307 Implemented as described in VM Spec.
2309 *******************************************************************************/
2311 double builtin_dneg(double a)
2314 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2321 /* If the operand is a zero, the result is the zero of opposite */
2327 /* If the operand is an infinity, the result is the infinity of */
2328 /* opposite sign. */
2330 return copysign(a, -copysign(1.0, a));
2334 #endif /* !SUPPORT_DOUBLE */
2337 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2338 s4 builtin_dcmpl(double a, double b)
2346 if (!finite(a) || !finite(b)) {
2347 a = finite(a) ? 0 : copysign(1.0, a);
2348 b = finite(b) ? 0 : copysign(1.0, b);
2361 s4 builtin_dcmpg(double a, double b)
2369 if (!finite(a) || !finite(b)) {
2370 a = finite(a) ? 0 : copysign(1.0, a);
2371 b = finite(b) ? 0 : copysign(1.0, b);
2382 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2385 double builtin_drem(double a, double b)
2391 /* conversion operations ******************************************************/
2394 s8 builtin_i2l(s4 i)
2406 s4 builtin_l2i(s8 l)
2417 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2418 float builtin_i2f(s4 a)
2420 float f = (float) a;
2423 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2426 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2427 double builtin_i2d(s4 a)
2429 double d = (double) a;
2432 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2435 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2436 float builtin_l2f(s8 a)
2439 float f = (float) a;
2445 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2448 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2449 double builtin_l2d(s8 a)
2452 double d = (double) a;
2458 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2461 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2462 s4 builtin_f2i(float a)
2466 i = builtin_d2i((double) a);
2477 if (a < (-2147483648))
2478 return (-2147483648);
2481 f = copysignf((float) 1.0, a);
2484 return (-2147483648); */
2486 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2489 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2490 s8 builtin_f2l(float a)
2494 l = builtin_d2l((double) a);
2501 if (a > 9223372036854775807L)
2502 return 9223372036854775807L;
2503 if (a < (-9223372036854775808L))
2504 return (-9223372036854775808L);
2509 f = copysignf((float) 1.0, a);
2511 return 9223372036854775807L;
2512 return (-9223372036854775808L); */
2514 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2517 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2518 s4 builtin_d2i(double a)
2523 if (a >= 2147483647)
2525 if (a <= (-2147483647-1))
2526 return (-2147483647-1);
2531 d = copysign(1.0, a);
2534 return (-2147483647-1);
2536 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2539 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2540 s8 builtin_d2l(double a)
2545 if (a >= 9223372036854775807LL)
2546 return 9223372036854775807LL;
2547 if (a <= (-9223372036854775807LL-1))
2548 return (-9223372036854775807LL-1);
2553 d = copysign(1.0, a);
2555 return 9223372036854775807LL;
2556 return (-9223372036854775807LL-1);
2558 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2561 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2562 double builtin_f2d(float a)
2564 if (finitef(a)) return (double) a;
2567 return longBitsToDouble(DBL_NAN);
2569 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2573 float builtin_d2f(double a)
2579 return intBitsToFloat(FLT_NAN);
2581 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2584 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2587 /* builtin_arraycopy ***********************************************************
2589 Builtin for java.lang.System.arraycopy.
2591 ATTENTION: This builtin function returns a boolean value to signal
2592 the ICMD_BUILTIN if there was an exception.
2594 *******************************************************************************/
2596 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2597 java_arrayheader *dest, s4 destStart, s4 len)
2599 arraydescriptor *sdesc;
2600 arraydescriptor *ddesc;
2603 if ((src == NULL) || (dest == NULL)) {
2604 exceptions_throw_nullpointerexception();
2608 sdesc = src->objheader.vftbl->arraydesc;
2609 ddesc = dest->objheader.vftbl->arraydesc;
2611 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2612 exceptions_throw_arraystoreexception();
2616 /* we try to throw exception with the same message as SUN does */
2618 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2619 (srcStart + len < 0) || (srcStart + len > src->size) ||
2620 (destStart + len < 0) || (destStart + len > dest->size)) {
2621 exceptions_throw_arrayindexoutofboundsexception();
2625 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2626 /* We copy primitive values or references of exactly the same type */
2628 s4 dataoffset = sdesc->dataoffset;
2629 s4 componentsize = sdesc->componentsize;
2631 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2632 ((u1 *) src) + dataoffset + componentsize * srcStart,
2633 (size_t) len * componentsize);
2636 /* We copy references of different type */
2638 java_objectarray *oas = (java_objectarray *) src;
2639 java_objectarray *oad = (java_objectarray *) dest;
2641 if (destStart <= srcStart) {
2642 for (i = 0; i < len; i++) {
2643 java_objectheader *o = oas->data[srcStart + i];
2645 if (!builtin_canstore(oad, o))
2648 oad->data[destStart + i] = o;
2652 /* XXX this does not completely obey the specification!
2653 If an exception is thrown only the elements above the
2654 current index have been copied. The specification
2655 requires that only the elements *below* the current
2656 index have been copied before the throw. */
2658 for (i = len - 1; i >= 0; i--) {
2659 java_objectheader *o = oas->data[srcStart + i];
2661 if (!builtin_canstore(oad, o))
2664 oad->data[destStart + i] = o;
2673 /* builtin_currenttimemillis ***************************************************
2675 Return the current time in milliseconds.
2677 *******************************************************************************/
2679 s8 builtin_currenttimemillis(void)
2684 if (gettimeofday(&tv, NULL) == -1)
2685 vm_abort("gettimeofday failed: %s", strerror(errno));
2687 result = (s8) tv.tv_sec;
2689 result += (tv.tv_usec / 1000);
2695 /* builtin_clone ***************************************************************
2697 Function for cloning objects or arrays.
2699 *******************************************************************************/
2701 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2703 arraydescriptor *ad;
2704 java_arrayheader *ah;
2707 java_objectheader *co; /* cloned object header */
2709 /* get the array descriptor */
2711 ad = o->vftbl->arraydesc;
2713 /* we are cloning an array */
2716 ah = (java_arrayheader *) o;
2718 size = ad->dataoffset + ad->componentsize * ah->size;
2720 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2725 MCOPY(co, o, u1, size);
2727 #if defined(ENABLE_GC_CACAO)
2728 heap_init_objectheader(co, size);
2731 #if defined(ENABLE_THREADS)
2732 lock_init_object_lock(co);
2738 /* we are cloning a non-array */
2740 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2741 exceptions_throw_clonenotsupportedexception();
2745 /* get the class of the object */
2747 c = o->vftbl->class;
2749 /* create new object */
2751 co = builtin_new(c);
2756 MCOPY(co, o, u1, c->instancesize);
2758 #if defined(ENABLE_GC_CACAO)
2759 heap_init_objectheader(co, c->instancesize);
2762 #if defined(ENABLE_THREADS)
2763 lock_init_object_lock(co);
2769 #if defined(ENABLE_VMLOG)
2771 #include <vmlog_cacao.c>
2776 * These are local overrides for various environment variables in Emacs.
2777 * Please do not remove this and leave it at the end of the file, where
2778 * Emacs will automagically detect them.
2779 * ---------------------------------------------------------------------
2782 * indent-tabs-mode: t
2786 * vim:noexpandtab:sw=4:ts=4: