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 8179 2007-07-05 11:21:08Z michi $
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
61 #include "threads/lock-common.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
75 #include "vmcore/class.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/options.h"
78 #include "vmcore/primitive.h"
79 #include "vmcore/rt-timing.h"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
85 #if defined(ENABLE_DEBUG_FILTER)
86 # include "vm/jit/show.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 arrayclass....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_DEBUG_FILTER)
1225 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1228 #if defined(ENABLE_VMLOG)
1232 if (opt_verbosecall && indent)
1235 /* calculate message length */
1239 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1242 logtextlen = strlen("Some Throwable");
1245 logtextlen += strlen(" thrown in ");
1249 utf_bytes(m->class->name) +
1251 utf_bytes(m->name) +
1252 utf_bytes(m->descriptor) +
1253 strlen("(NOSYNC,NATIVE");
1255 #if SIZEOF_VOID_P == 8
1257 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1259 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1262 if (m->class->sourcefile == NULL)
1263 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1265 logtextlen += utf_bytes(m->class->sourcefile);
1267 logtextlen += strlen(":65536)");
1271 logtextlen += strlen("call_java_method");
1274 logtextlen += strlen("0");
1276 /* allocate memory */
1278 dumpsize = dump_size();
1280 logtext = DMNEW(char, logtextlen);
1283 strcpy(logtext, "Exception ");
1284 utf_cat_classname(logtext, xptr->vftbl->class->name);
1287 strcpy(logtext, "Some Throwable");
1290 strcat(logtext, " thrown in ");
1293 utf_cat_classname(logtext, m->class->name);
1294 strcat(logtext, ".");
1295 utf_cat(logtext, m->name);
1296 utf_cat(logtext, m->descriptor);
1298 if (m->flags & ACC_SYNCHRONIZED)
1299 strcat(logtext, "(SYNC");
1301 strcat(logtext, "(NOSYNC");
1303 if (m->flags & ACC_NATIVE) {
1304 strcat(logtext, ",NATIVE");
1308 #if SIZEOF_VOID_P == 8
1309 sprintf(logtext + strlen(logtext),
1310 ")(0x%016lx) at position 0x%016lx",
1311 (ptrint) code->entrypoint, (ptrint) pos);
1313 sprintf(logtext + strlen(logtext),
1314 ")(0x%08x) at position 0x%08x",
1315 (ptrint) code->entrypoint, (ptrint) pos);
1320 /* XXX preliminary: This should get the actual codeinfo */
1321 /* in which the exception happened. */
1324 #if SIZEOF_VOID_P == 8
1325 sprintf(logtext + strlen(logtext),
1326 ")(0x%016lx) at position 0x%016lx (",
1327 (ptrint) code->entrypoint, (ptrint) pos);
1329 sprintf(logtext + strlen(logtext),
1330 ")(0x%08x) at position 0x%08x (",
1331 (ptrint) code->entrypoint, (ptrint) pos);
1334 if (m->class->sourcefile == NULL)
1335 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1337 utf_cat(logtext, m->class->sourcefile);
1339 sprintf(logtext + strlen(logtext), ":%d)", 0);
1343 strcat(logtext, "call_java_method");
1347 /* release memory */
1349 dump_release(dumpsize);
1353 #endif /* !defined(NDEBUG) */
1356 /* builtin_print_argument ******************************************************
1358 Prints arguments and return values for the call trace.
1360 *******************************************************************************/
1362 #if !defined(NDEBUG)
1363 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1364 typedesc *paramtype, s8 value)
1367 java_objectheader *o;
1372 switch (paramtype->type) {
1375 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1380 #if SIZEOF_VOID_P == 4
1381 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1383 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1388 #if defined(__S390__)
1390 /* The below won't work on S390 */
1394 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1399 #if SIZEOF_VOID_P == 4
1400 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1402 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1407 #if SIZEOF_VOID_P == 4
1408 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1410 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1413 /* cast to java.lang.Object */
1415 o = (java_objectheader *) (ptrint) value;
1417 /* check return argument for java.lang.Class or java.lang.String */
1420 if (o->vftbl->class == class_java_lang_String) {
1421 /* get java.lang.String object and the length of the
1424 u = javastring_toutf(o, false);
1426 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1428 /* realloc memory for string length */
1430 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1433 /* convert to utf8 string and strcat it to the logtext */
1435 strcat(logtext, " (String = \"");
1436 utf_cat(logtext, u);
1437 strcat(logtext, "\")");
1440 if (o->vftbl->class == class_java_lang_Class) {
1441 /* if the object returned is a java.lang.Class
1442 cast it to classinfo structure and get the name
1445 c = (classinfo *) o;
1450 /* if the object returned is not a java.lang.String or
1451 a java.lang.Class just print the name of the class */
1453 u = o->vftbl->class->name;
1456 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1458 /* realloc memory for string length */
1460 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1463 /* strcat to the logtext */
1465 strcat(logtext, " (Class = \"");
1466 utf_cat_classname(logtext, u);
1467 strcat(logtext, "\")");
1474 #endif /* !defined(NDEBUG) */
1476 /* builtin_verbosecall_enter ***************************************************
1478 Print method call with arguments for -verbose:call.
1480 *******************************************************************************/
1482 #if !defined(NDEBUG)
1484 #ifdef TRACE_ARGS_NUM
1485 void builtin_verbosecall_enter(s8 a0, s8 a1,
1486 # if TRACE_ARGS_NUM >= 4
1489 # if TRACE_ARGS_NUM >= 6
1492 # if TRACE_ARGS_NUM == 8
1504 #if defined(ENABLE_DEBUG_FILTER)
1505 if (! show_filters_test_verbosecall_enter(m)) return;
1508 #if defined(ENABLE_VMLOG)
1509 vmlog_cacao_enter_method(m);
1515 /* calculate message length */
1518 strlen("4294967295 ") +
1519 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1521 strlen("called: ") +
1522 utf_bytes(m->class->name) +
1524 utf_bytes(m->name) +
1525 utf_bytes(m->descriptor);
1527 /* Actually it's not possible to have all flags printed, but:
1532 strlen(" PRIVATE") +
1533 strlen(" PROTECTED") +
1536 strlen(" SYNCHRONIZED") +
1537 strlen(" VOLATILE") +
1538 strlen(" TRANSIENT") +
1540 strlen(" INTERFACE") +
1541 strlen(" ABSTRACT");
1543 /* add maximal argument length */
1547 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1548 strlen("...(255)") +
1551 /* allocate memory */
1553 dumpsize = dump_size();
1555 logtext = DMNEW(char, logtextlen);
1559 sprintf(logtext, "%10d ", callcount);
1560 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1562 pos = strlen(logtext);
1564 for (i = 0; i < methodindent; i++)
1565 logtext[pos++] = '\t';
1567 strcpy(logtext + pos, "called: ");
1569 utf_cat_classname(logtext, m->class->name);
1570 strcat(logtext, ".");
1571 utf_cat(logtext, m->name);
1572 utf_cat(logtext, m->descriptor);
1574 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1575 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1576 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1577 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1578 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1579 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1580 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1581 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1582 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1583 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1584 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1586 strcat(logtext, "(");
1588 if (md->paramcount >= 1) {
1589 logtext = builtin_print_argument(logtext, &logtextlen,
1590 &md->paramtypes[0], a0);
1593 if (md->paramcount >= 2) {
1594 strcat(logtext, ", ");
1596 logtext = builtin_print_argument(logtext, &logtextlen,
1597 &md->paramtypes[1], a1);
1600 #if TRACE_ARGS_NUM >= 4
1601 if (md->paramcount >= 3) {
1602 strcat(logtext, ", ");
1604 logtext = builtin_print_argument(logtext, &logtextlen,
1605 &md->paramtypes[2], a2);
1608 if (md->paramcount >= 4) {
1609 strcat(logtext, ", ");
1611 logtext = builtin_print_argument(logtext, &logtextlen,
1612 &md->paramtypes[3], a3);
1616 #if TRACE_ARGS_NUM >= 6
1617 if (md->paramcount >= 5) {
1618 strcat(logtext, ", ");
1620 logtext = builtin_print_argument(logtext, &logtextlen,
1621 &md->paramtypes[4], a4);
1624 if (md->paramcount >= 6) {
1625 strcat(logtext, ", ");
1627 logtext = builtin_print_argument(logtext, &logtextlen,
1628 &md->paramtypes[5], a5);
1632 #if TRACE_ARGS_NUM == 8
1633 if (md->paramcount >= 7) {
1634 strcat(logtext, ", ");
1636 logtext = builtin_print_argument(logtext, &logtextlen,
1637 &md->paramtypes[6], a6);
1640 if (md->paramcount >= 8) {
1641 strcat(logtext, ", ");
1643 logtext = builtin_print_argument(logtext, &logtextlen,
1644 &md->paramtypes[7], a7);
1648 if (md->paramcount > 8) {
1649 sprintf(logtext + strlen(logtext), ", ...(%d)",
1650 md->paramcount - TRACE_ARGS_NUM);
1653 strcat(logtext, ")");
1657 /* release memory */
1659 dump_release(dumpsize);
1665 #endif /* !defined(NDEBUG) */
1668 /* builtin_verbosecall_exit ****************************************************
1670 Print method exit for -verbose:call.
1672 *******************************************************************************/
1674 #if !defined(NDEBUG)
1675 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1685 #if defined(ENABLE_DEBUG_FILTER)
1686 if (! show_filters_test_verbosecall_exit(m)) return;
1689 #if defined(ENABLE_VMLOG)
1690 vmlog_cacao_leave_method(m);
1696 /* calculate message length */
1699 strlen("4294967295 ") +
1700 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1702 strlen("finished: ") +
1703 utf_bytes(m->class->name) +
1705 utf_bytes(m->name) +
1706 utf_bytes(m->descriptor) +
1707 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1709 /* add maximal argument length */
1711 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1713 /* allocate memory */
1715 dumpsize = dump_size();
1717 logtext = DMNEW(char, logtextlen);
1719 /* outdent the log message */
1724 log_text("WARNING: unmatched methodindent--");
1726 /* generate the message */
1728 sprintf(logtext, " ");
1729 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1731 pos = strlen(logtext);
1733 for (i = 0; i < methodindent; i++)
1734 logtext[pos++] = '\t';
1736 strcpy(logtext + pos, "finished: ");
1737 utf_cat_classname(logtext, m->class->name);
1738 strcat(logtext, ".");
1739 utf_cat(logtext, m->name);
1740 utf_cat(logtext, m->descriptor);
1742 if (!IS_VOID_TYPE(md->returntype.type)) {
1743 strcat(logtext, "->");
1745 switch (md->returntype.type) {
1762 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1767 /* release memory */
1769 dump_release(dumpsize);
1772 #endif /* !defined(NDEBUG) */
1775 #if defined(ENABLE_CYCLES_STATS)
1776 void builtin_print_cycles_stats(FILE *file)
1778 fprintf(file,"builtin cylce count statistics:\n");
1780 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1781 CYCLES_STATS_PRINT(builtin_new ,file);
1785 #endif /* defined(ENABLE_CYCLES_STATS) */
1788 /*****************************************************************************
1789 MISCELLANEOUS HELPER FUNCTIONS
1790 *****************************************************************************/
1794 /*********** Functions for integer divisions *****************************
1796 On some systems (eg. DEC ALPHA), integer division is not supported by the
1797 CPU. These helper functions implement the missing functionality.
1799 ******************************************************************************/
1801 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1802 s4 builtin_idiv(s4 a, s4 b)
1811 s4 builtin_irem(s4 a, s4 b)
1819 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1822 /* functions for long arithmetics **********************************************
1824 On systems where 64 bit Integers are not supported by the CPU,
1825 these functions are needed.
1827 ******************************************************************************/
1829 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1830 s8 builtin_ladd(s8 a, s8 b)
1843 s8 builtin_lsub(s8 a, s8 b)
1856 s8 builtin_lneg(s8 a)
1868 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1871 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1872 s8 builtin_lmul(s8 a, s8 b)
1884 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1887 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1888 s8 builtin_ldiv(s8 a, s8 b)
1901 s8 builtin_lrem(s8 a, s8 b)
1913 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1916 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1917 s8 builtin_lshl(s8 a, s4 b)
1930 s8 builtin_lshr(s8 a, s4 b)
1943 s8 builtin_lushr(s8 a, s4 b)
1948 c = ((u8) a) >> (b & 63);
1955 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1958 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1959 s8 builtin_land(s8 a, s8 b)
1972 s8 builtin_lor(s8 a, s8 b)
1985 s8 builtin_lxor(s8 a, s8 b)
1997 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2000 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2001 s4 builtin_lcmp(s8 a, s8 b)
2015 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2018 /* functions for unsupported floating instructions ****************************/
2020 /* used to convert FLT_xxx defines into float values */
2022 static inline float intBitsToFloat(s4 i)
2031 /* used to convert DBL_xxx defines into double values */
2033 static inline float longBitsToDouble(s8 l)
2043 float builtin_fadd(float a, float b)
2045 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2046 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2057 if (copysignf(1.0, a) == copysignf(1.0, b))
2060 return intBitsToFloat(FLT_NAN);
2066 float builtin_fsub(float a, float b)
2068 return builtin_fadd(a, builtin_fneg(b));
2072 float builtin_fmul(float a, float b)
2074 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2075 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2077 if (finitef(b)) return a * b;
2079 if (a == 0) return intBitsToFloat(FLT_NAN);
2080 else return copysignf(b, copysignf(1.0, b)*a);
2085 if (b == 0) return intBitsToFloat(FLT_NAN);
2086 else return copysignf(a, copysignf(1.0, a)*b);
2089 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2095 /* builtin_ddiv ****************************************************************
2097 Implementation as described in VM Spec.
2099 *******************************************************************************/
2101 float builtin_fdiv(float a, float b)
2105 /* If neither value1' nor value2' is NaN, the sign of the result */
2106 /* is positive if both values have the same sign, negative if the */
2107 /* values have different signs. */
2113 /* If either value1' or value2' is NaN, the result is NaN. */
2115 return intBitsToFloat(FLT_NAN);
2118 /* Division of a finite value by an infinity results in a */
2119 /* signed zero, with the sign-producing rule just given. */
2121 /* is sign equal? */
2123 if (copysignf(1.0, a) == copysignf(1.0, b))
2132 /* If either value1' or value2' is NaN, the result is NaN. */
2134 return intBitsToFloat(FLT_NAN);
2136 } else if (finitef(b)) {
2137 /* Division of an infinity by a finite value results in a signed */
2138 /* infinity, with the sign-producing rule just given. */
2140 /* is sign equal? */
2142 if (copysignf(1.0, a) == copysignf(1.0, b))
2143 return intBitsToFloat(FLT_POSINF);
2145 return intBitsToFloat(FLT_NEGINF);
2148 /* Division of an infinity by an infinity results in NaN. */
2150 return intBitsToFloat(FLT_NAN);
2156 float builtin_fneg(float a)
2158 if (isnanf(a)) return a;
2160 if (finitef(a)) return -a;
2161 else return copysignf(a, -copysignf(1.0, a));
2164 #endif /* !SUPPORT_FLOAT */
2167 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2168 s4 builtin_fcmpl(float a, float b)
2176 if (!finitef(a) || !finitef(b)) {
2177 a = finitef(a) ? 0 : copysignf(1.0, a);
2178 b = finitef(b) ? 0 : copysignf(1.0, b);
2191 s4 builtin_fcmpg(float a, float b)
2193 if (isnanf(a)) return 1;
2194 if (isnanf(b)) return 1;
2195 if (!finitef(a) || !finitef(b)) {
2196 a = finitef(a) ? 0 : copysignf(1.0, a);
2197 b = finitef(b) ? 0 : copysignf(1.0, b);
2199 if (a > b) return 1;
2200 if (a == b) return 0;
2203 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2206 float builtin_frem(float a, float b)
2212 /* functions for unsupported double instructions ******************************/
2215 double builtin_dadd(double a, double b)
2217 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2218 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2220 if (finite(b)) return a + b;
2224 if (finite(b)) return a;
2226 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2227 else return longBitsToDouble(DBL_NAN);
2233 double builtin_dsub(double a, double b)
2235 return builtin_dadd(a, builtin_dneg(b));
2239 double builtin_dmul(double a, double b)
2241 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2242 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2244 if (finite(b)) return a * b;
2246 if (a == 0) return longBitsToDouble(DBL_NAN);
2247 else return copysign(b, copysign(1.0, b) * a);
2252 if (b == 0) return longBitsToDouble(DBL_NAN);
2253 else return copysign(a, copysign(1.0, a) * b);
2256 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2262 /* builtin_ddiv ****************************************************************
2264 Implementation as described in VM Spec.
2266 *******************************************************************************/
2268 double builtin_ddiv(double a, double b)
2272 /* If neither value1' nor value2' is NaN, the sign of the result */
2273 /* is positive if both values have the same sign, negative if the */
2274 /* values have different signs. */
2280 /* If either value1' or value2' is NaN, the result is NaN. */
2282 return longBitsToDouble(DBL_NAN);
2285 /* Division of a finite value by an infinity results in a */
2286 /* signed zero, with the sign-producing rule just given. */
2288 /* is sign equal? */
2290 if (copysign(1.0, a) == copysign(1.0, b))
2299 /* If either value1' or value2' is NaN, the result is NaN. */
2301 return longBitsToDouble(DBL_NAN);
2303 } else if (finite(b)) {
2304 /* Division of an infinity by a finite value results in a signed */
2305 /* infinity, with the sign-producing rule just given. */
2307 /* is sign equal? */
2309 if (copysign(1.0, a) == copysign(1.0, b))
2310 return longBitsToDouble(DBL_POSINF);
2312 return longBitsToDouble(DBL_NEGINF);
2315 /* Division of an infinity by an infinity results in NaN. */
2317 return longBitsToDouble(DBL_NAN);
2323 /* builtin_dneg ****************************************************************
2325 Implemented as described in VM Spec.
2327 *******************************************************************************/
2329 double builtin_dneg(double a)
2332 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2339 /* If the operand is a zero, the result is the zero of opposite */
2345 /* If the operand is an infinity, the result is the infinity of */
2346 /* opposite sign. */
2348 return copysign(a, -copysign(1.0, a));
2352 #endif /* !SUPPORT_DOUBLE */
2355 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2356 s4 builtin_dcmpl(double a, double b)
2364 if (!finite(a) || !finite(b)) {
2365 a = finite(a) ? 0 : copysign(1.0, a);
2366 b = finite(b) ? 0 : copysign(1.0, b);
2379 s4 builtin_dcmpg(double a, double b)
2387 if (!finite(a) || !finite(b)) {
2388 a = finite(a) ? 0 : copysign(1.0, a);
2389 b = finite(b) ? 0 : copysign(1.0, b);
2400 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2403 double builtin_drem(double a, double b)
2409 /* conversion operations ******************************************************/
2412 s8 builtin_i2l(s4 i)
2424 s4 builtin_l2i(s8 l)
2435 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2436 float builtin_i2f(s4 a)
2438 float f = (float) a;
2441 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2444 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2445 double builtin_i2d(s4 a)
2447 double d = (double) a;
2450 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2453 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2454 float builtin_l2f(s8 a)
2457 float f = (float) a;
2463 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2466 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2467 double builtin_l2d(s8 a)
2470 double d = (double) a;
2476 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2479 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2480 s4 builtin_f2i(float a)
2484 i = builtin_d2i((double) a);
2495 if (a < (-2147483648))
2496 return (-2147483648);
2499 f = copysignf((float) 1.0, a);
2502 return (-2147483648); */
2504 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2507 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2508 s8 builtin_f2l(float a)
2512 l = builtin_d2l((double) a);
2519 if (a > 9223372036854775807L)
2520 return 9223372036854775807L;
2521 if (a < (-9223372036854775808L))
2522 return (-9223372036854775808L);
2527 f = copysignf((float) 1.0, a);
2529 return 9223372036854775807L;
2530 return (-9223372036854775808L); */
2532 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2535 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2536 s4 builtin_d2i(double a)
2541 if (a >= 2147483647)
2543 if (a <= (-2147483647-1))
2544 return (-2147483647-1);
2549 d = copysign(1.0, a);
2552 return (-2147483647-1);
2554 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2557 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2558 s8 builtin_d2l(double a)
2563 if (a >= 9223372036854775807LL)
2564 return 9223372036854775807LL;
2565 if (a <= (-9223372036854775807LL-1))
2566 return (-9223372036854775807LL-1);
2571 d = copysign(1.0, a);
2573 return 9223372036854775807LL;
2574 return (-9223372036854775807LL-1);
2576 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2579 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2580 double builtin_f2d(float a)
2582 if (finitef(a)) return (double) a;
2585 return longBitsToDouble(DBL_NAN);
2587 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2591 float builtin_d2f(double a)
2597 return intBitsToFloat(FLT_NAN);
2599 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2602 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2605 /* builtin_arraycopy ***********************************************************
2607 Builtin for java.lang.System.arraycopy.
2609 ATTENTION: This builtin function returns a boolean value to signal
2610 the ICMD_BUILTIN if there was an exception.
2612 *******************************************************************************/
2614 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2615 java_arrayheader *dest, s4 destStart, s4 len)
2617 arraydescriptor *sdesc;
2618 arraydescriptor *ddesc;
2621 if ((src == NULL) || (dest == NULL)) {
2622 exceptions_throw_nullpointerexception();
2626 sdesc = src->objheader.vftbl->arraydesc;
2627 ddesc = dest->objheader.vftbl->arraydesc;
2629 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2630 exceptions_throw_arraystoreexception();
2634 /* we try to throw exception with the same message as SUN does */
2636 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2637 (srcStart + len < 0) || (srcStart + len > src->size) ||
2638 (destStart + len < 0) || (destStart + len > dest->size)) {
2639 exceptions_throw_arrayindexoutofboundsexception();
2643 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2644 /* We copy primitive values or references of exactly the same type */
2646 s4 dataoffset = sdesc->dataoffset;
2647 s4 componentsize = sdesc->componentsize;
2649 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2650 ((u1 *) src) + dataoffset + componentsize * srcStart,
2651 (size_t) len * componentsize);
2654 /* We copy references of different type */
2656 java_objectarray *oas = (java_objectarray *) src;
2657 java_objectarray *oad = (java_objectarray *) dest;
2659 if (destStart <= srcStart) {
2660 for (i = 0; i < len; i++) {
2661 java_objectheader *o = oas->data[srcStart + i];
2663 if (!builtin_canstore(oad, o))
2666 oad->data[destStart + i] = o;
2670 /* XXX this does not completely obey the specification!
2671 If an exception is thrown only the elements above the
2672 current index have been copied. The specification
2673 requires that only the elements *below* the current
2674 index have been copied before the throw. */
2676 for (i = len - 1; i >= 0; i--) {
2677 java_objectheader *o = oas->data[srcStart + i];
2679 if (!builtin_canstore(oad, o))
2682 oad->data[destStart + i] = o;
2691 /* builtin_nanotime ************************************************************
2693 Return the current time in nanoseconds.
2695 *******************************************************************************/
2697 s8 builtin_nanotime(void)
2702 if (gettimeofday(&tv, NULL) == -1)
2703 vm_abort("gettimeofday failed: %s", strerror(errno));
2705 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2707 return usecs * 1000;
2711 /* builtin_currenttimemillis ***************************************************
2713 Return the current time in milliseconds.
2715 *******************************************************************************/
2717 s8 builtin_currenttimemillis(void)
2721 msecs = builtin_nanotime() / 1000 / 1000;
2727 /* builtin_clone ***************************************************************
2729 Function for cloning objects or arrays.
2731 *******************************************************************************/
2733 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2735 arraydescriptor *ad;
2736 java_arrayheader *ah;
2739 java_objectheader *co; /* cloned object header */
2741 /* get the array descriptor */
2743 ad = o->vftbl->arraydesc;
2745 /* we are cloning an array */
2748 ah = (java_arrayheader *) o;
2750 size = ad->dataoffset + ad->componentsize * ah->size;
2752 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2757 MCOPY(co, o, u1, size);
2759 #if defined(ENABLE_GC_CACAO)
2760 heap_init_objectheader(co, size);
2763 #if defined(ENABLE_THREADS)
2764 lock_init_object_lock(co);
2770 /* we are cloning a non-array */
2772 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2773 exceptions_throw_clonenotsupportedexception();
2777 /* get the class of the object */
2779 c = o->vftbl->class;
2781 /* create new object */
2783 co = builtin_new(c);
2788 MCOPY(co, o, u1, c->instancesize);
2790 #if defined(ENABLE_GC_CACAO)
2791 heap_init_objectheader(co, c->instancesize);
2794 #if defined(ENABLE_THREADS)
2795 lock_init_object_lock(co);
2801 #if defined(ENABLE_VMLOG)
2803 #include <vmlog_cacao.c>
2808 * These are local overrides for various environment variables in Emacs.
2809 * Please do not remove this and leave it at the end of the file, where
2810 * Emacs will automagically detect them.
2811 * ---------------------------------------------------------------------
2814 * indent-tabs-mode: t
2818 * vim:noexpandtab:sw=4:ts=4: