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 8360 2007-08-20 18:02:50Z 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/llni.h"
59 #include "native/include/java_lang_String.h"
60 #include "native/include/java_lang_Throwable.h"
62 #include "threads/lock-common.h"
64 #include "toolbox/logging.h"
65 #include "toolbox/util.h"
68 #include "vm/builtin.h"
69 #include "vm/cycles-stats.h"
70 #include "vm/exceptions.h"
71 #include "vm/global.h"
72 #include "vm/initialize.h"
73 #include "vm/primitive.h"
74 #include "vm/stringlocal.h"
76 #include "vm/jit/asmpart.h"
78 #include "vmcore/class.h"
79 #include "vmcore/linker.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>
88 #if defined(ENABLE_DEBUG_FILTER)
89 # include "vm/jit/show.h"
92 /* include builtin tables *****************************************************/
94 #include "vm/builtintable.inc"
97 CYCLES_STATS_DECLARE(builtin_new ,100,5)
98 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
100 /* builtintable_init ***********************************************************
102 Parse the descriptors of builtin functions and create the parsed
105 *******************************************************************************/
107 static bool builtintable_init(void)
109 descriptor_pool *descpool;
111 builtintable_entry *bte;
113 /* mark start of dump memory area */
115 dumpsize = dump_size();
117 /* create a new descriptor pool */
119 descpool = descriptor_pool_new(class_java_lang_Object);
121 /* add some entries we need */
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
126 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
129 /* first add all descriptors to the pool */
131 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
132 /* create a utf8 string from descriptor */
134 bte->descriptor = utf_new_char(bte->cdescriptor);
136 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
137 /* release dump area */
139 dump_release(dumpsize);
145 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
146 bte->descriptor = utf_new_char(bte->cdescriptor);
148 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
149 dump_release(dumpsize);
154 for (bte = builtintable_function; bte->fp != NULL; bte++) {
155 bte->classname = utf_new_char(bte->cclassname);
156 bte->name = utf_new_char(bte->cname);
157 bte->descriptor = utf_new_char(bte->cdescriptor);
159 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
160 dump_release(dumpsize);
165 /* create the class reference table */
167 (void) descriptor_pool_create_classrefs(descpool, NULL);
169 /* allocate space for the parsed descriptors */
171 descriptor_pool_alloc_parsed_descriptors(descpool);
173 /* Now parse all descriptors. NOTE: builtin-functions are treated
174 like static methods (no `this' pointer). */
176 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
178 descriptor_pool_parse_method_descriptor(descpool,
180 ACC_STATIC | ACC_METHOD_BUILTIN,
183 /* generate a builtin stub if we need one */
185 if (bte->flags & BUILTINTABLE_FLAG_STUB)
186 codegen_generate_stub_builtin(bte);
189 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
196 /* no stubs should be needed for this table */
198 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
201 for (bte = builtintable_function; bte->fp != NULL; bte++) {
203 descriptor_pool_parse_method_descriptor(descpool,
205 ACC_STATIC | ACC_METHOD_BUILTIN,
208 /* generate a builtin stub if we need one */
210 if (bte->flags & BUILTINTABLE_FLAG_STUB)
211 codegen_generate_stub_builtin(bte);
214 /* release dump area */
216 dump_release(dumpsize);
222 /* builtintable_comparator *****************************************************
224 qsort comparator for the automatic builtin table.
226 *******************************************************************************/
228 static int builtintable_comparator(const void *a, const void *b)
230 builtintable_entry *bte1;
231 builtintable_entry *bte2;
233 bte1 = (builtintable_entry *) a;
234 bte2 = (builtintable_entry *) b;
236 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
240 /* builtintable_sort_automatic *************************************************
242 Sorts the automatic builtin table.
244 *******************************************************************************/
246 static void builtintable_sort_automatic(void)
250 /* calculate table size statically (`- 1' comment see builtintable.inc) */
252 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
254 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
255 builtintable_comparator);
259 /* builtin_init ****************************************************************
261 Initialize the global table of builtin functions.
263 *******************************************************************************/
265 bool builtin_init(void)
267 /* initialize the builtin tables */
269 if (!builtintable_init())
272 /* sort builtin tables */
274 builtintable_sort_automatic();
280 /* builtintable_get_internal ***************************************************
282 Finds an entry in the builtintable for internal functions and
283 returns the a pointer to the structure.
285 *******************************************************************************/
287 builtintable_entry *builtintable_get_internal(functionptr fp)
289 builtintable_entry *bte;
291 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
300 /* builtintable_get_automatic **************************************************
302 Finds an entry in the builtintable for functions which are replaced
303 automatically and returns the a pointer to the structure.
305 *******************************************************************************/
307 builtintable_entry *builtintable_get_automatic(s4 opcode)
309 builtintable_entry *first;
310 builtintable_entry *last;
311 builtintable_entry *middle;
315 /* calculate table size statically (`- 1' comment see builtintable.inc) */
317 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
319 first = builtintable_automatic;
320 last = builtintable_automatic + entries;
322 while (entries > 0) {
324 middle = first + half;
326 if (middle->opcode < opcode) {
334 return (first != last ? first : NULL);
338 /* builtintable_replace_function ***********************************************
342 *******************************************************************************/
344 #if defined(ENABLE_JIT)
345 bool builtintable_replace_function(void *iptr_)
348 builtintable_entry *bte;
351 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
353 /* get name and descriptor of the function */
356 case ICMD_INVOKESTATIC:
357 /* The instruction MUST be resolved, otherwise we run into
358 lazy loading troubles. Anyway, we should/can only replace
359 very VM-close functions. */
361 if (INSTRUCTION_IS_UNRESOLVED(iptr))
364 mr = iptr->sx.s23.s3.fmiref;
371 /* search the function table */
373 for (bte = builtintable_function; bte->fp != NULL; bte++) {
374 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
375 (mr->name == bte->name) &&
376 (mr->descriptor == bte->descriptor)) {
378 /* set the values in the instruction */
380 iptr->opc = bte->opcode;
381 iptr->sx.s23.s3.bte = bte;
383 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
384 iptr->flags.bits |= INS_FLAG_CHECK;
386 iptr->flags.bits &= ~INS_FLAG_CHECK;
394 #endif /* defined(ENABLE_JIT) */
397 /*****************************************************************************
399 *****************************************************************************/
401 /* builtin_instanceof **********************************************************
403 Checks if an object is an instance of some given class (or subclass
404 of that class). If class is an interface, checks if the interface
407 Return value: 1 ... o is an instance of class or implements the interface
408 0 ... otherwise or if o == NULL
410 *******************************************************************************/
412 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
417 return class_isanysubclass(o->vftbl->class, class);
422 /* builtin_checkcast ***********************************************************
424 The same as builtin_instanceof except that 1 is returned when o ==
427 *******************************************************************************/
429 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
434 if (class_isanysubclass(o->vftbl->class, class))
441 /* builtin_descriptorscompatible ***********************************************
443 Checks if two array type descriptors are assignment compatible
445 Return value: 1 ... target = desc is possible
448 *******************************************************************************/
450 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
451 arraydescriptor *target)
456 if (desc->arraytype != target->arraytype)
459 if (desc->arraytype != ARRAYTYPE_OBJECT)
462 /* {both arrays are arrays of references} */
464 if (desc->dimension == target->dimension) {
465 /* an array which contains elements of interface types is
466 allowed to be casted to Object (JOWENN)*/
468 if ((desc->elementvftbl->baseval < 0) &&
469 (target->elementvftbl->baseval == 1))
472 return class_isanysubclass(desc->elementvftbl->class,
473 target->elementvftbl->class);
476 if (desc->dimension < target->dimension)
479 /* {desc has higher dimension than target} */
481 return class_isanysubclass(pseudo_class_Arraystub,
482 target->elementvftbl->class);
486 /* builtin_arraycheckcast ******************************************************
488 Checks if an object is really a subtype of the requested array
489 type. The object has to be an array to begin with. For simple
490 arrays (int, short, double, etc.) the types have to match exactly.
491 For arrays of objects, the type of elements in the array has to be
492 a subtype (or the same type) of the requested element type. For
493 arrays of arrays (which in turn can again be arrays of arrays), the
494 types at the lowest level have to satisfy the corresponding sub
497 *******************************************************************************/
499 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
501 arraydescriptor *desc;
506 desc = o->vftbl->arraydesc;
511 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
515 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
520 return builtin_arraycheckcast(o, targetclass);
524 /* builtin_throw_exception *****************************************************
526 Sets the exceptionptr with the thrown exception and prints some
527 debugging information. Called from asm_vm_call_method.
529 *******************************************************************************/
531 void *builtin_throw_exception(java_handle_t *xptr)
534 java_lang_Throwable *t;
541 t = (java_lang_Throwable *) xptr;
543 /* get detail message */
545 LLNI_field_get_ref(t, detailMessage, s);
547 /* calculate message length */
549 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
553 utf_bytes(xptr->vftbl->class->name);
555 logtextlen += strlen(": ") +
556 u2_utflength(LLNI_field_direct(s, value)->data
557 + LLNI_field_direct(s, offset),
558 LLNI_field_direct(s,count));
562 logtextlen += strlen("(nil)");
565 /* allocate memory */
567 dumpsize = dump_size();
569 logtext = DMNEW(char, logtextlen);
571 strcpy(logtext, "Builtin exception thrown: ");
574 utf_cat_classname(logtext, xptr->vftbl->class->name);
579 buf = javastring_tochar((java_handle_t *) s);
580 strcat(logtext, ": ");
581 strcat(logtext, buf);
582 MFREE(buf, char, strlen(buf) + 1);
586 strcat(logtext, "(nil)");
593 dump_release(dumpsize);
595 #endif /* !defined(NDEBUG) */
597 /* actually set the exception */
599 exceptions_set_exception(xptr);
601 /* Return a NULL pointer. This is required for vm_call_method to
602 check for an exception. This is for convenience. */
608 /* builtin_canstore ************************************************************
610 Checks, if an object can be stored in an array.
612 Return value: 1 ... possible
613 0 ... otherwise (throws an ArrayStoreException)
615 *******************************************************************************/
617 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
619 arraydescriptor *desc;
620 arraydescriptor *valuedesc;
621 vftbl_t *componentvftbl;
630 /* The following is guaranteed (by verifier checks):
632 * *) oa->...vftbl->arraydesc != NULL
633 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
634 * *) o->vftbl is not an interface vftbl
637 desc = oa->header.objheader.vftbl->arraydesc;
638 componentvftbl = desc->componentvftbl;
639 valuevftbl = o->vftbl;
640 valuedesc = valuevftbl->arraydesc;
642 if ((desc->dimension - 1) == 0) {
643 /* {oa is a one-dimensional array} */
644 /* {oa is an array of references} */
646 if (valuevftbl == componentvftbl)
649 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
651 baseval = componentvftbl->baseval;
654 /* an array of interface references */
656 result = ((valuevftbl->interfacetablelength > -baseval) &&
657 (valuevftbl->interfacetable[baseval] != NULL));
660 diffval = valuevftbl->baseval - componentvftbl->baseval;
661 result = diffval <= (uint32_t) componentvftbl->diffval;
664 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
666 else if (valuedesc == NULL) {
667 /* {oa has dimension > 1} */
668 /* {componentvftbl->arraydesc != NULL} */
670 /* check if o is an array */
675 /* {o is an array} */
677 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
680 /* if not possible, throw an exception */
683 exceptions_throw_arraystoreexception();
691 /* This is an optimized version where a is guaranteed to be one-dimensional */
692 s4 builtin_canstore_onedim (java_handle_objectarray_t *a, java_handle_t *o)
694 arraydescriptor *desc;
695 vftbl_t *elementvftbl;
704 /* The following is guaranteed (by verifier checks):
706 * *) a->...vftbl->arraydesc != NULL
707 * *) a->...vftbl->arraydesc->elementvftbl != NULL
708 * *) a->...vftbl->arraydesc->dimension == 1
709 * *) o->vftbl is not an interface vftbl
712 desc = a->header.objheader.vftbl->arraydesc;
713 elementvftbl = desc->elementvftbl;
714 valuevftbl = o->vftbl;
716 /* {a is a one-dimensional array} */
718 if (valuevftbl == elementvftbl)
721 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
723 baseval = elementvftbl->baseval;
726 /* an array of interface references */
727 result = ((valuevftbl->interfacetablelength > -baseval) &&
728 (valuevftbl->interfacetable[baseval] != NULL));
731 diffval = valuevftbl->baseval - elementvftbl->baseval;
732 result = diffval <= (uint32_t) elementvftbl->diffval;
735 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
741 /* This is an optimized version where a is guaranteed to be a
742 * one-dimensional array of a class type */
743 s4 builtin_canstore_onedim_class(java_handle_objectarray_t *a, java_handle_t *o)
745 vftbl_t *elementvftbl;
753 /* The following is guaranteed (by verifier checks):
755 * *) a->...vftbl->arraydesc != NULL
756 * *) a->...vftbl->arraydesc->elementvftbl != NULL
757 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
758 * *) a->...vftbl->arraydesc->dimension == 1
759 * *) o->vftbl is not an interface vftbl
762 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
763 valuevftbl = o->vftbl;
765 /* {a is a one-dimensional array} */
767 if (valuevftbl == elementvftbl)
770 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
772 diffval = valuevftbl->baseval - elementvftbl->baseval;
773 result = diffval <= (uint32_t) elementvftbl->diffval;
775 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
781 /* builtin_new *****************************************************************
783 Creates a new instance of class c on the heap.
785 Return value: pointer to the object or NULL if no memory is
788 *******************************************************************************/
790 java_handle_t *builtin_new(classinfo *c)
793 #if defined(ENABLE_RT_TIMING)
794 struct timespec time_start, time_end;
796 #if defined(ENABLE_CYCLES_STATS)
797 u8 cycles_start, cycles_end;
800 RT_TIMING_GET_TIME(time_start);
801 CYCLES_STATS_GET(cycles_start);
803 /* is the class loaded */
805 assert(c->state & CLASS_LOADED);
807 /* check if we can instantiate this class */
809 if (c->flags & ACC_ABSTRACT) {
810 exceptions_throw_instantiationerror(c);
814 /* is the class linked */
816 if (!(c->state & CLASS_LINKED))
820 if (!(c->state & CLASS_INITIALIZED)) {
823 log_message_class("Initialize class (from builtin_new): ", c);
826 if (!initialize_class(c))
830 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
838 #if defined(ENABLE_THREADS)
839 lock_init_object_lock(o);
842 CYCLES_STATS_GET(cycles_end);
843 RT_TIMING_GET_TIME(time_end);
845 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
846 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
852 /* builtin_fast_new ************************************************************
854 Creates a new instance of class c on the heap.
856 Return value: pointer to the object or NULL if no fast return
857 is possible for any reason.
859 *******************************************************************************/
861 java_object_t *builtin_fast_new(classinfo *c)
864 #if defined(ENABLE_RT_TIMING)
865 struct timespec time_start, time_end;
867 #if defined(ENABLE_CYCLES_STATS)
868 u8 cycles_start, cycles_end;
871 RT_TIMING_GET_TIME(time_start);
872 CYCLES_STATS_GET(cycles_start);
874 /* is the class loaded */
876 assert(c->state & CLASS_LOADED);
878 /* check if we can instantiate this class */
880 if (c->flags & ACC_ABSTRACT)
883 /* is the class linked */
885 if (!(c->state & CLASS_LINKED))
888 if (!(c->state & CLASS_INITIALIZED))
891 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
892 c->finalizer, false);
899 #if defined(ENABLE_THREADS)
900 lock_init_object_lock(o);
903 CYCLES_STATS_GET(cycles_end);
904 RT_TIMING_GET_TIME(time_end);
906 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
907 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
913 /* builtin_newarray ************************************************************
915 Creates an array with the given vftbl on the heap. This function
916 takes as class argument an array class.
918 Return value: pointer to the array or NULL if no memory is available
920 *******************************************************************************/
922 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
924 arraydescriptor *desc;
929 #if defined(ENABLE_RT_TIMING)
930 struct timespec time_start, time_end;
933 RT_TIMING_GET_TIME(time_start);
935 desc = arrayclass->vftbl->arraydesc;
936 dataoffset = desc->dataoffset;
937 componentsize = desc->componentsize;
940 exceptions_throw_negativearraysizeexception();
944 actualsize = dataoffset + size * componentsize;
946 /* check for overflow */
948 if (((u4) actualsize) < ((u4) size)) {
949 exceptions_throw_outofmemoryerror();
953 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
958 a->objheader.vftbl = arrayclass->vftbl;
960 #if defined(ENABLE_THREADS)
961 lock_init_object_lock(&a->objheader);
964 LLNI_array_size(a) = size;
966 RT_TIMING_GET_TIME(time_end);
967 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
973 /* builtin_anewarray ***********************************************************
975 Creates an array of references to the given class type on the heap.
977 Return value: pointer to the array or NULL if no memory is
980 *******************************************************************************/
982 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
984 classinfo *arrayclass;
986 /* is class loaded */
988 assert(componentclass->state & CLASS_LOADED);
990 /* is class linked */
992 if (!(componentclass->state & CLASS_LINKED))
993 if (!link_class(componentclass))
996 arrayclass = class_array_of(componentclass, true);
1001 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1005 /* builtin_newarray_boolean ****************************************************
1007 Creates an array of bytes on the heap. The array is designated as
1008 an array of booleans (important for casts)
1010 Return value: pointer to the array or NULL if no memory is
1013 *******************************************************************************/
1015 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
1017 return (java_handle_booleanarray_t *)
1018 builtin_newarray(size,
1019 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
1023 /* builtin_newarray_byte *******************************************************
1025 Creates an array of 8 bit Integers on the heap.
1027 Return value: pointer to the array or NULL if no memory is
1030 *******************************************************************************/
1032 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
1034 return (java_handle_bytearray_t *)
1035 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1039 /* builtin_newarray_char *******************************************************
1041 Creates an array of characters on the heap.
1043 Return value: pointer to the array or NULL if no memory is
1046 *******************************************************************************/
1048 java_handle_chararray_t *builtin_newarray_char(s4 size)
1050 return (java_handle_chararray_t *)
1051 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1055 /* builtin_newarray_short ******************************************************
1057 Creates an array of 16 bit Integers on the heap.
1059 Return value: pointer to the array or NULL if no memory is
1062 *******************************************************************************/
1064 java_handle_shortarray_t *builtin_newarray_short(s4 size)
1066 return (java_handle_shortarray_t *)
1067 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1071 /* builtin_newarray_int ********************************************************
1073 Creates an array of 32 bit Integers on the heap.
1075 Return value: pointer to the array or NULL if no memory is
1078 *******************************************************************************/
1080 java_handle_intarray_t *builtin_newarray_int(s4 size)
1082 return (java_handle_intarray_t *)
1083 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1087 /* builtin_newarray_long *******************************************************
1089 Creates an array of 64 bit Integers on the heap.
1091 Return value: pointer to the array or NULL if no memory is
1094 *******************************************************************************/
1096 java_handle_longarray_t *builtin_newarray_long(s4 size)
1098 return (java_handle_longarray_t *)
1099 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1103 /* builtin_newarray_float ******************************************************
1105 Creates an array of 32 bit IEEE floats on the heap.
1107 Return value: pointer to the array or NULL if no memory is
1110 *******************************************************************************/
1112 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1114 return (java_handle_floatarray_t *)
1115 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1119 /* builtin_newarray_double *****************************************************
1121 Creates an array of 64 bit IEEE floats on the heap.
1123 Return value: pointer to the array or NULL if no memory is
1126 *******************************************************************************/
1128 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1130 return (java_handle_doublearray_t *)
1131 builtin_newarray(size,
1132 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1136 /* builtin_multianewarray_intern ***********************************************
1138 Creates a multi-dimensional array on the heap. The dimensions are
1139 passed in an array of longs.
1142 n.............number of dimensions to create
1143 arrayclass....the array class
1144 dims..........array containing the size of each dimension to create
1146 Return value: pointer to the array or NULL if no memory is
1149 ******************************************************************************/
1151 static java_handle_t *builtin_multianewarray_intern(int n,
1152 classinfo *arrayclass,
1157 classinfo *componentclass;
1160 /* create this dimension */
1162 size = (s4) dims[0];
1163 a = builtin_newarray(size, arrayclass);
1168 /* if this is the last dimension return */
1173 /* get the class of the components to create */
1175 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1177 /* The verifier guarantees that the dimension count is in the range. */
1179 /* create the component arrays */
1181 for (i = 0; i < size; i++) {
1183 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1184 /* we save an s4 to a s8 slot, 8-byte aligned */
1186 builtin_multianewarray_intern(n, componentclass, dims + 2);
1188 builtin_multianewarray_intern(n, componentclass, dims + 1);
1194 ((java_handle_objectarray_t *) a)->data[i] = (java_object_t *) ea;
1201 /* builtin_multianewarray ******************************************************
1203 Wrapper for builtin_multianewarray_intern which checks all
1204 dimensions before we start allocating.
1206 ******************************************************************************/
1208 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1214 /* check all dimensions before doing anything */
1216 for (i = 0; i < n; i++) {
1217 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1218 /* we save an s4 to a s8 slot, 8-byte aligned */
1219 size = (s4) dims[i * 2];
1221 size = (s4) dims[i];
1225 exceptions_throw_negativearraysizeexception();
1230 /* now call the real function */
1232 return builtin_multianewarray_intern(n, arrayclass, dims);
1236 /*****************************************************************************
1239 Various functions for printing a message at method entry or exit (for
1242 *****************************************************************************/
1244 #if !defined(NDEBUG)
1245 static s4 methodindent = 0;
1246 static u4 callcount = 0;
1248 java_handle_t *builtin_trace_exception(java_handle_t *xptr,
1258 #if defined(ENABLE_DEBUG_FILTER)
1259 if (! show_filters_test_verbosecall_exit(m)) return xptr;
1262 #if defined(ENABLE_VMLOG)
1266 if (opt_verbosecall && indent)
1269 /* calculate message length */
1273 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1276 logtextlen = strlen("Some Throwable");
1279 logtextlen += strlen(" thrown in ");
1283 utf_bytes(m->class->name) +
1285 utf_bytes(m->name) +
1286 utf_bytes(m->descriptor) +
1287 strlen("(NOSYNC,NATIVE");
1289 #if SIZEOF_VOID_P == 8
1291 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1293 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1296 if (m->class->sourcefile == NULL)
1297 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1299 logtextlen += utf_bytes(m->class->sourcefile);
1301 logtextlen += strlen(":65536)");
1305 logtextlen += strlen("call_java_method");
1308 logtextlen += strlen("0");
1310 /* allocate memory */
1312 dumpsize = dump_size();
1314 logtext = DMNEW(char, logtextlen);
1317 strcpy(logtext, "Exception ");
1318 utf_cat_classname(logtext, xptr->vftbl->class->name);
1321 strcpy(logtext, "Some Throwable");
1324 strcat(logtext, " thrown in ");
1327 utf_cat_classname(logtext, m->class->name);
1328 strcat(logtext, ".");
1329 utf_cat(logtext, m->name);
1330 utf_cat(logtext, m->descriptor);
1332 if (m->flags & ACC_SYNCHRONIZED)
1333 strcat(logtext, "(SYNC");
1335 strcat(logtext, "(NOSYNC");
1337 if (m->flags & ACC_NATIVE) {
1338 strcat(logtext, ",NATIVE");
1342 #if SIZEOF_VOID_P == 8
1343 sprintf(logtext + strlen(logtext),
1344 ")(0x%016lx) at position 0x%016lx",
1345 (ptrint) code->entrypoint, (ptrint) pos);
1347 sprintf(logtext + strlen(logtext),
1348 ")(0x%08x) at position 0x%08x",
1349 (ptrint) code->entrypoint, (ptrint) pos);
1354 /* XXX preliminary: This should get the actual codeinfo */
1355 /* in which the exception happened. */
1358 #if SIZEOF_VOID_P == 8
1359 sprintf(logtext + strlen(logtext),
1360 ")(0x%016lx) at position 0x%016lx (",
1361 (ptrint) code->entrypoint, (ptrint) pos);
1363 sprintf(logtext + strlen(logtext),
1364 ")(0x%08x) at position 0x%08x (",
1365 (ptrint) code->entrypoint, (ptrint) pos);
1368 if (m->class->sourcefile == NULL)
1369 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1371 utf_cat(logtext, m->class->sourcefile);
1373 sprintf(logtext + strlen(logtext), ":%d)", 0);
1377 strcat(logtext, "call_java_method");
1381 /* release memory */
1383 dump_release(dumpsize);
1387 #endif /* !defined(NDEBUG) */
1390 /* builtin_print_argument ******************************************************
1392 Prints arguments and return values for the call trace.
1394 *******************************************************************************/
1396 #if !defined(NDEBUG)
1397 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1398 typedesc *paramtype, s8 value)
1406 switch (paramtype->type) {
1409 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1414 #if SIZEOF_VOID_P == 4
1415 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1417 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1422 #if defined(__S390__)
1424 /* The below won't work on S390 */
1428 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1433 #if SIZEOF_VOID_P == 4
1434 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1436 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1441 #if SIZEOF_VOID_P == 4
1442 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1444 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1447 /* cast to java.lang.Object */
1449 o = (java_handle_t *) (ptrint) value;
1451 /* check return argument for java.lang.Class or java.lang.String */
1454 if (o->vftbl->class == class_java_lang_String) {
1455 /* get java.lang.String object and the length of the
1458 u = javastring_toutf(o, false);
1460 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1462 /* realloc memory for string length */
1464 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1467 /* convert to utf8 string and strcat it to the logtext */
1469 strcat(logtext, " (String = \"");
1470 utf_cat(logtext, u);
1471 strcat(logtext, "\")");
1474 if (o->vftbl->class == class_java_lang_Class) {
1475 /* if the object returned is a java.lang.Class
1476 cast it to classinfo structure and get the name
1479 c = (classinfo *) o;
1484 /* if the object returned is not a java.lang.String or
1485 a java.lang.Class just print the name of the class */
1487 u = o->vftbl->class->name;
1490 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1492 /* realloc memory for string length */
1494 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1497 /* strcat to the logtext */
1499 strcat(logtext, " (Class = \"");
1500 utf_cat_classname(logtext, u);
1501 strcat(logtext, "\")");
1508 #endif /* !defined(NDEBUG) */
1510 /* builtin_verbosecall_enter ***************************************************
1512 Print method call with arguments for -verbose:call.
1514 *******************************************************************************/
1516 #if !defined(NDEBUG)
1518 #ifdef TRACE_ARGS_NUM
1519 void builtin_verbosecall_enter(s8 a0, s8 a1,
1520 # if TRACE_ARGS_NUM >= 4
1523 # if TRACE_ARGS_NUM >= 6
1526 # if TRACE_ARGS_NUM == 8
1538 #if defined(ENABLE_DEBUG_FILTER)
1539 if (! show_filters_test_verbosecall_enter(m)) return;
1542 #if defined(ENABLE_VMLOG)
1543 vmlog_cacao_enter_method(m);
1549 /* calculate message length */
1552 strlen("4294967295 ") +
1553 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1555 strlen("called: ") +
1556 utf_bytes(m->class->name) +
1558 utf_bytes(m->name) +
1559 utf_bytes(m->descriptor);
1561 /* Actually it's not possible to have all flags printed, but:
1566 strlen(" PRIVATE") +
1567 strlen(" PROTECTED") +
1570 strlen(" SYNCHRONIZED") +
1571 strlen(" VOLATILE") +
1572 strlen(" TRANSIENT") +
1574 strlen(" INTERFACE") +
1575 strlen(" ABSTRACT");
1577 /* add maximal argument length */
1581 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1582 strlen("...(255)") +
1585 /* allocate memory */
1587 dumpsize = dump_size();
1589 logtext = DMNEW(char, logtextlen);
1593 sprintf(logtext, "%10d ", callcount);
1594 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1596 pos = strlen(logtext);
1598 for (i = 0; i < methodindent; i++)
1599 logtext[pos++] = '\t';
1601 strcpy(logtext + pos, "called: ");
1603 utf_cat_classname(logtext, m->class->name);
1604 strcat(logtext, ".");
1605 utf_cat(logtext, m->name);
1606 utf_cat(logtext, m->descriptor);
1608 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1609 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1610 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1611 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1612 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1613 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1614 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1615 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1616 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1617 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1618 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1620 strcat(logtext, "(");
1622 if (md->paramcount >= 1) {
1623 logtext = builtin_print_argument(logtext, &logtextlen,
1624 &md->paramtypes[0], a0);
1627 if (md->paramcount >= 2) {
1628 strcat(logtext, ", ");
1630 logtext = builtin_print_argument(logtext, &logtextlen,
1631 &md->paramtypes[1], a1);
1634 #if TRACE_ARGS_NUM >= 4
1635 if (md->paramcount >= 3) {
1636 strcat(logtext, ", ");
1638 logtext = builtin_print_argument(logtext, &logtextlen,
1639 &md->paramtypes[2], a2);
1642 if (md->paramcount >= 4) {
1643 strcat(logtext, ", ");
1645 logtext = builtin_print_argument(logtext, &logtextlen,
1646 &md->paramtypes[3], a3);
1650 #if TRACE_ARGS_NUM >= 6
1651 if (md->paramcount >= 5) {
1652 strcat(logtext, ", ");
1654 logtext = builtin_print_argument(logtext, &logtextlen,
1655 &md->paramtypes[4], a4);
1658 if (md->paramcount >= 6) {
1659 strcat(logtext, ", ");
1661 logtext = builtin_print_argument(logtext, &logtextlen,
1662 &md->paramtypes[5], a5);
1666 #if TRACE_ARGS_NUM == 8
1667 if (md->paramcount >= 7) {
1668 strcat(logtext, ", ");
1670 logtext = builtin_print_argument(logtext, &logtextlen,
1671 &md->paramtypes[6], a6);
1674 if (md->paramcount >= 8) {
1675 strcat(logtext, ", ");
1677 logtext = builtin_print_argument(logtext, &logtextlen,
1678 &md->paramtypes[7], a7);
1682 if (md->paramcount > 8) {
1683 sprintf(logtext + strlen(logtext), ", ...(%d)",
1684 md->paramcount - TRACE_ARGS_NUM);
1687 strcat(logtext, ")");
1691 /* release memory */
1693 dump_release(dumpsize);
1699 #endif /* !defined(NDEBUG) */
1702 /* builtin_verbosecall_exit ****************************************************
1704 Print method exit for -verbose:call.
1706 *******************************************************************************/
1708 #if !defined(NDEBUG)
1709 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1719 #if defined(ENABLE_DEBUG_FILTER)
1720 if (! show_filters_test_verbosecall_exit(m)) return;
1723 #if defined(ENABLE_VMLOG)
1724 vmlog_cacao_leave_method(m);
1730 /* calculate message length */
1733 strlen("4294967295 ") +
1734 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1736 strlen("finished: ") +
1737 utf_bytes(m->class->name) +
1739 utf_bytes(m->name) +
1740 utf_bytes(m->descriptor) +
1741 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1743 /* add maximal argument length */
1745 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1747 /* allocate memory */
1749 dumpsize = dump_size();
1751 logtext = DMNEW(char, logtextlen);
1753 /* outdent the log message */
1758 log_text("WARNING: unmatched methodindent--");
1760 /* generate the message */
1762 sprintf(logtext, " ");
1763 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1765 pos = strlen(logtext);
1767 for (i = 0; i < methodindent; i++)
1768 logtext[pos++] = '\t';
1770 strcpy(logtext + pos, "finished: ");
1771 utf_cat_classname(logtext, m->class->name);
1772 strcat(logtext, ".");
1773 utf_cat(logtext, m->name);
1774 utf_cat(logtext, m->descriptor);
1776 if (!IS_VOID_TYPE(md->returntype.type)) {
1777 strcat(logtext, "->");
1779 switch (md->returntype.type) {
1796 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1801 /* release memory */
1803 dump_release(dumpsize);
1806 #endif /* !defined(NDEBUG) */
1809 #if defined(ENABLE_CYCLES_STATS)
1810 void builtin_print_cycles_stats(FILE *file)
1812 fprintf(file,"builtin cylce count statistics:\n");
1814 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1815 CYCLES_STATS_PRINT(builtin_new ,file);
1819 #endif /* defined(ENABLE_CYCLES_STATS) */
1822 /*****************************************************************************
1823 MISCELLANEOUS HELPER FUNCTIONS
1824 *****************************************************************************/
1828 /*********** Functions for integer divisions *****************************
1830 On some systems (eg. DEC ALPHA), integer division is not supported by the
1831 CPU. These helper functions implement the missing functionality.
1833 ******************************************************************************/
1835 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1836 s4 builtin_idiv(s4 a, s4 b)
1845 s4 builtin_irem(s4 a, s4 b)
1853 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1856 /* functions for long arithmetics **********************************************
1858 On systems where 64 bit Integers are not supported by the CPU,
1859 these functions are needed.
1861 ******************************************************************************/
1863 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1864 s8 builtin_ladd(s8 a, s8 b)
1877 s8 builtin_lsub(s8 a, s8 b)
1890 s8 builtin_lneg(s8 a)
1902 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1905 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1906 s8 builtin_lmul(s8 a, s8 b)
1918 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1921 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1922 s8 builtin_ldiv(s8 a, s8 b)
1935 s8 builtin_lrem(s8 a, s8 b)
1947 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1950 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1951 s8 builtin_lshl(s8 a, s4 b)
1964 s8 builtin_lshr(s8 a, s4 b)
1977 s8 builtin_lushr(s8 a, s4 b)
1982 c = ((u8) a) >> (b & 63);
1989 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1992 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1993 s8 builtin_land(s8 a, s8 b)
2006 s8 builtin_lor(s8 a, s8 b)
2019 s8 builtin_lxor(s8 a, s8 b)
2031 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2034 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2035 s4 builtin_lcmp(s8 a, s8 b)
2049 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2052 /* functions for unsupported floating instructions ****************************/
2054 /* used to convert FLT_xxx defines into float values */
2056 static inline float intBitsToFloat(s4 i)
2065 /* used to convert DBL_xxx defines into double values */
2067 static inline float longBitsToDouble(s8 l)
2077 float builtin_fadd(float a, float b)
2079 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2080 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2091 if (copysignf(1.0, a) == copysignf(1.0, b))
2094 return intBitsToFloat(FLT_NAN);
2100 float builtin_fsub(float a, float b)
2102 return builtin_fadd(a, builtin_fneg(b));
2106 float builtin_fmul(float a, float b)
2108 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2109 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2111 if (finitef(b)) return a * b;
2113 if (a == 0) return intBitsToFloat(FLT_NAN);
2114 else return copysignf(b, copysignf(1.0, b)*a);
2119 if (b == 0) return intBitsToFloat(FLT_NAN);
2120 else return copysignf(a, copysignf(1.0, a)*b);
2123 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2129 /* builtin_ddiv ****************************************************************
2131 Implementation as described in VM Spec.
2133 *******************************************************************************/
2135 float builtin_fdiv(float a, float b)
2139 /* If neither value1' nor value2' is NaN, the sign of the result */
2140 /* is positive if both values have the same sign, negative if the */
2141 /* values have different signs. */
2147 /* If either value1' or value2' is NaN, the result is NaN. */
2149 return intBitsToFloat(FLT_NAN);
2152 /* Division of a finite value by an infinity results in a */
2153 /* signed zero, with the sign-producing rule just given. */
2155 /* is sign equal? */
2157 if (copysignf(1.0, a) == copysignf(1.0, b))
2166 /* If either value1' or value2' is NaN, the result is NaN. */
2168 return intBitsToFloat(FLT_NAN);
2170 } else if (finitef(b)) {
2171 /* Division of an infinity by a finite value results in a signed */
2172 /* infinity, with the sign-producing rule just given. */
2174 /* is sign equal? */
2176 if (copysignf(1.0, a) == copysignf(1.0, b))
2177 return intBitsToFloat(FLT_POSINF);
2179 return intBitsToFloat(FLT_NEGINF);
2182 /* Division of an infinity by an infinity results in NaN. */
2184 return intBitsToFloat(FLT_NAN);
2190 float builtin_fneg(float a)
2192 if (isnanf(a)) return a;
2194 if (finitef(a)) return -a;
2195 else return copysignf(a, -copysignf(1.0, a));
2198 #endif /* !SUPPORT_FLOAT */
2201 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2202 s4 builtin_fcmpl(float a, float b)
2210 if (!finitef(a) || !finitef(b)) {
2211 a = finitef(a) ? 0 : copysignf(1.0, a);
2212 b = finitef(b) ? 0 : copysignf(1.0, b);
2225 s4 builtin_fcmpg(float a, float b)
2227 if (isnanf(a)) return 1;
2228 if (isnanf(b)) return 1;
2229 if (!finitef(a) || !finitef(b)) {
2230 a = finitef(a) ? 0 : copysignf(1.0, a);
2231 b = finitef(b) ? 0 : copysignf(1.0, b);
2233 if (a > b) return 1;
2234 if (a == b) return 0;
2237 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2240 float builtin_frem(float a, float b)
2246 /* functions for unsupported double instructions ******************************/
2249 double builtin_dadd(double a, double b)
2251 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2252 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2254 if (finite(b)) return a + b;
2258 if (finite(b)) return a;
2260 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2261 else return longBitsToDouble(DBL_NAN);
2267 double builtin_dsub(double a, double b)
2269 return builtin_dadd(a, builtin_dneg(b));
2273 double builtin_dmul(double a, double b)
2275 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2276 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2278 if (finite(b)) return a * b;
2280 if (a == 0) return longBitsToDouble(DBL_NAN);
2281 else return copysign(b, copysign(1.0, b) * a);
2286 if (b == 0) return longBitsToDouble(DBL_NAN);
2287 else return copysign(a, copysign(1.0, a) * b);
2290 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2296 /* builtin_ddiv ****************************************************************
2298 Implementation as described in VM Spec.
2300 *******************************************************************************/
2302 double builtin_ddiv(double a, double b)
2306 /* If neither value1' nor value2' is NaN, the sign of the result */
2307 /* is positive if both values have the same sign, negative if the */
2308 /* values have different signs. */
2314 /* If either value1' or value2' is NaN, the result is NaN. */
2316 return longBitsToDouble(DBL_NAN);
2319 /* Division of a finite value by an infinity results in a */
2320 /* signed zero, with the sign-producing rule just given. */
2322 /* is sign equal? */
2324 if (copysign(1.0, a) == copysign(1.0, b))
2333 /* If either value1' or value2' is NaN, the result is NaN. */
2335 return longBitsToDouble(DBL_NAN);
2337 } else if (finite(b)) {
2338 /* Division of an infinity by a finite value results in a signed */
2339 /* infinity, with the sign-producing rule just given. */
2341 /* is sign equal? */
2343 if (copysign(1.0, a) == copysign(1.0, b))
2344 return longBitsToDouble(DBL_POSINF);
2346 return longBitsToDouble(DBL_NEGINF);
2349 /* Division of an infinity by an infinity results in NaN. */
2351 return longBitsToDouble(DBL_NAN);
2357 /* builtin_dneg ****************************************************************
2359 Implemented as described in VM Spec.
2361 *******************************************************************************/
2363 double builtin_dneg(double a)
2366 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2373 /* If the operand is a zero, the result is the zero of opposite */
2379 /* If the operand is an infinity, the result is the infinity of */
2380 /* opposite sign. */
2382 return copysign(a, -copysign(1.0, a));
2386 #endif /* !SUPPORT_DOUBLE */
2389 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2390 s4 builtin_dcmpl(double a, double b)
2398 if (!finite(a) || !finite(b)) {
2399 a = finite(a) ? 0 : copysign(1.0, a);
2400 b = finite(b) ? 0 : copysign(1.0, b);
2413 s4 builtin_dcmpg(double a, double b)
2421 if (!finite(a) || !finite(b)) {
2422 a = finite(a) ? 0 : copysign(1.0, a);
2423 b = finite(b) ? 0 : copysign(1.0, b);
2434 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2437 double builtin_drem(double a, double b)
2443 /* conversion operations ******************************************************/
2446 s8 builtin_i2l(s4 i)
2458 s4 builtin_l2i(s8 l)
2469 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2470 float builtin_i2f(s4 a)
2472 float f = (float) a;
2475 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2478 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2479 double builtin_i2d(s4 a)
2481 double d = (double) a;
2484 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2487 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2488 float builtin_l2f(s8 a)
2491 float f = (float) a;
2497 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2500 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2501 double builtin_l2d(s8 a)
2504 double d = (double) a;
2510 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2513 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2514 s4 builtin_f2i(float a)
2518 i = builtin_d2i((double) a);
2529 if (a < (-2147483648))
2530 return (-2147483648);
2533 f = copysignf((float) 1.0, a);
2536 return (-2147483648); */
2538 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2541 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2542 s8 builtin_f2l(float a)
2546 l = builtin_d2l((double) a);
2553 if (a > 9223372036854775807L)
2554 return 9223372036854775807L;
2555 if (a < (-9223372036854775808L))
2556 return (-9223372036854775808L);
2561 f = copysignf((float) 1.0, a);
2563 return 9223372036854775807L;
2564 return (-9223372036854775808L); */
2566 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2569 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2570 s4 builtin_d2i(double a)
2575 if (a >= 2147483647)
2577 if (a <= (-2147483647-1))
2578 return (-2147483647-1);
2583 d = copysign(1.0, a);
2586 return (-2147483647-1);
2588 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2591 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2592 s8 builtin_d2l(double a)
2597 if (a >= 9223372036854775807LL)
2598 return 9223372036854775807LL;
2599 if (a <= (-9223372036854775807LL-1))
2600 return (-9223372036854775807LL-1);
2605 d = copysign(1.0, a);
2607 return 9223372036854775807LL;
2608 return (-9223372036854775807LL-1);
2610 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2613 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2614 double builtin_f2d(float a)
2616 if (finitef(a)) return (double) a;
2619 return longBitsToDouble(DBL_NAN);
2621 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2625 float builtin_d2f(double a)
2631 return intBitsToFloat(FLT_NAN);
2633 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2636 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2639 /* builtin_arraycopy ***********************************************************
2641 Builtin for java.lang.System.arraycopy.
2643 ATTENTION: This builtin function returns a boolean value to signal
2644 the ICMD_BUILTIN if there was an exception.
2646 *******************************************************************************/
2648 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2649 java_handle_t *dest, s4 destStart, s4 len)
2651 arraydescriptor *sdesc;
2652 arraydescriptor *ddesc;
2655 if ((src == NULL) || (dest == NULL)) {
2656 exceptions_throw_nullpointerexception();
2660 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2661 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2663 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2664 exceptions_throw_arraystoreexception();
2668 /* we try to throw exception with the same message as SUN does */
2670 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2671 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2672 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2673 exceptions_throw_arrayindexoutofboundsexception();
2677 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2678 /* We copy primitive values or references of exactly the same type */
2680 s4 dataoffset = sdesc->dataoffset;
2681 s4 componentsize = sdesc->componentsize;
2683 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2684 ((u1 *) src) + dataoffset + componentsize * srcStart,
2685 (size_t) len * componentsize);
2688 /* We copy references of different type */
2690 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2691 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2693 if (destStart <= srcStart) {
2694 for (i = 0; i < len; i++) {
2695 java_handle_t *o = oas->data[srcStart + i];
2697 if (!builtin_canstore(oad, o))
2700 oad->data[destStart + i] = o;
2704 /* XXX this does not completely obey the specification!
2705 If an exception is thrown only the elements above the
2706 current index have been copied. The specification
2707 requires that only the elements *below* the current
2708 index have been copied before the throw. */
2710 for (i = len - 1; i >= 0; i--) {
2711 java_handle_t *o = oas->data[srcStart + i];
2713 if (!builtin_canstore(oad, o))
2716 oad->data[destStart + i] = o;
2725 /* builtin_nanotime ************************************************************
2727 Return the current time in nanoseconds.
2729 *******************************************************************************/
2731 s8 builtin_nanotime(void)
2736 if (gettimeofday(&tv, NULL) == -1)
2737 vm_abort("gettimeofday failed: %s", strerror(errno));
2739 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2741 return usecs * 1000;
2745 /* builtin_currenttimemillis ***************************************************
2747 Return the current time in milliseconds.
2749 *******************************************************************************/
2751 s8 builtin_currenttimemillis(void)
2755 msecs = builtin_nanotime() / 1000 / 1000;
2761 /* builtin_clone ***************************************************************
2763 Function for cloning objects or arrays.
2765 *******************************************************************************/
2767 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2769 arraydescriptor *ad;
2773 java_handle_t *co; /* cloned object header */
2775 /* get the array descriptor */
2777 ad = o->vftbl->arraydesc;
2779 /* we are cloning an array */
2782 ah = (java_handle_t *) o;
2784 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2786 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2791 MCOPY(co, o, u1, size);
2793 #if defined(ENABLE_GC_CACAO)
2794 heap_init_objectheader(co, size);
2797 #if defined(ENABLE_THREADS)
2798 lock_init_object_lock(co);
2804 /* we are cloning a non-array */
2806 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2807 exceptions_throw_clonenotsupportedexception();
2811 /* get the class of the object */
2813 c = o->vftbl->class;
2815 /* create new object */
2817 co = builtin_new(c);
2822 MCOPY(co, o, u1, c->instancesize);
2824 #if defined(ENABLE_GC_CACAO)
2825 heap_init_objectheader(co, c->instancesize);
2828 #if defined(ENABLE_THREADS)
2829 lock_init_object_lock(co);
2835 #if defined(ENABLE_VMLOG)
2837 #include <vmlog_cacao.c>
2842 * These are local overrides for various environment variables in Emacs.
2843 * Please do not remove this and leave it at the end of the file, where
2844 * Emacs will automagically detect them.
2845 * ---------------------------------------------------------------------
2848 * indent-tabs-mode: t
2852 * vim:noexpandtab:sw=4:ts=4: