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
47 #include "fdlibm/fdlibm.h"
48 #if defined(__CYGWIN__) && defined(Bias)
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
55 #include "native/jni.h"
56 #include "native/llni.h"
57 #include "native/include/java_lang_String.h"
58 #include "native/include/java_lang_Throwable.h"
60 #include "threads/lock-common.h"
61 #if defined(ENABLE_THREADS)
62 #include "threads/native/threads.h"
64 #include "threads/none/threads.h"
67 #include "toolbox/logging.h"
68 #include "toolbox/util.h"
71 #include "vm/builtin.h"
72 #include "vm/cycles-stats.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/initialize.h"
76 #include "vm/primitive.h"
77 #include "vm/stringlocal.h"
79 #include "vm/jit/asmpart.h"
81 #include "vmcore/class.h"
82 #include "vmcore/linker.h"
83 #include "vmcore/loader.h"
84 #include "vmcore/options.h"
85 #include "vmcore/rt-timing.h"
87 #if defined(ENABLE_VMLOG)
88 #include <vmlog_cacao.h>
91 #if defined(ENABLE_DEBUG_FILTER)
92 # include "vm/jit/show.h"
95 /* include builtin tables *****************************************************/
97 #include "vm/builtintable.inc"
100 CYCLES_STATS_DECLARE(builtin_new ,100,5)
101 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
103 /* builtintable_init ***********************************************************
105 Parse the descriptors of builtin functions and create the parsed
108 *******************************************************************************/
110 static bool builtintable_init(void)
112 descriptor_pool *descpool;
114 builtintable_entry *bte;
116 /* mark start of dump memory area */
118 dumpsize = dump_size();
120 /* create a new descriptor pool */
122 descpool = descriptor_pool_new(class_java_lang_Object);
124 /* add some entries we need */
126 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
129 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
132 /* first add all descriptors to the pool */
134 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
135 /* create a utf8 string from descriptor */
137 bte->descriptor = utf_new_char(bte->cdescriptor);
139 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
140 /* release dump area */
142 dump_release(dumpsize);
148 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
149 bte->descriptor = utf_new_char(bte->cdescriptor);
151 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
152 dump_release(dumpsize);
157 for (bte = builtintable_function; bte->fp != NULL; bte++) {
158 bte->classname = utf_new_char(bte->cclassname);
159 bte->name = utf_new_char(bte->cname);
160 bte->descriptor = utf_new_char(bte->cdescriptor);
162 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
163 dump_release(dumpsize);
168 /* create the class reference table */
170 (void) descriptor_pool_create_classrefs(descpool, NULL);
172 /* allocate space for the parsed descriptors */
174 descriptor_pool_alloc_parsed_descriptors(descpool);
176 /* Now parse all descriptors. NOTE: builtin-functions are treated
177 like static methods (no `this' pointer). */
179 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
186 /* generate a builtin stub if we need one */
188 if (bte->flags & BUILTINTABLE_FLAG_STUB)
189 codegen_generate_stub_builtin(bte);
192 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
194 descriptor_pool_parse_method_descriptor(descpool,
196 ACC_STATIC | ACC_METHOD_BUILTIN,
199 /* no stubs should be needed for this table */
201 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
204 for (bte = builtintable_function; bte->fp != NULL; bte++) {
206 descriptor_pool_parse_method_descriptor(descpool,
208 ACC_STATIC | ACC_METHOD_BUILTIN,
211 /* generate a builtin stub if we need one */
213 if (bte->flags & BUILTINTABLE_FLAG_STUB)
214 codegen_generate_stub_builtin(bte);
217 /* release dump area */
219 dump_release(dumpsize);
225 /* builtintable_comparator *****************************************************
227 qsort comparator for the automatic builtin table.
229 *******************************************************************************/
231 static int builtintable_comparator(const void *a, const void *b)
233 builtintable_entry *bte1;
234 builtintable_entry *bte2;
236 bte1 = (builtintable_entry *) a;
237 bte2 = (builtintable_entry *) b;
239 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
243 /* builtintable_sort_automatic *************************************************
245 Sorts the automatic builtin table.
247 *******************************************************************************/
249 static void builtintable_sort_automatic(void)
253 /* calculate table size statically (`- 1' comment see builtintable.inc) */
255 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
257 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
258 builtintable_comparator);
262 /* builtin_init ****************************************************************
264 Initialize the global table of builtin functions.
266 *******************************************************************************/
268 bool builtin_init(void)
270 /* initialize the builtin tables */
272 if (!builtintable_init())
275 /* sort builtin tables */
277 builtintable_sort_automatic();
283 /* builtintable_get_internal ***************************************************
285 Finds an entry in the builtintable for internal functions and
286 returns the a pointer to the structure.
288 *******************************************************************************/
290 builtintable_entry *builtintable_get_internal(functionptr fp)
292 builtintable_entry *bte;
294 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
303 /* builtintable_get_automatic **************************************************
305 Finds an entry in the builtintable for functions which are replaced
306 automatically and returns the a pointer to the structure.
308 *******************************************************************************/
310 builtintable_entry *builtintable_get_automatic(s4 opcode)
312 builtintable_entry *first;
313 builtintable_entry *last;
314 builtintable_entry *middle;
318 /* calculate table size statically (`- 1' comment see builtintable.inc) */
320 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
322 first = builtintable_automatic;
323 last = builtintable_automatic + entries;
325 while (entries > 0) {
327 middle = first + half;
329 if (middle->opcode < opcode) {
337 return (first != last ? first : NULL);
341 /* builtintable_replace_function ***********************************************
345 *******************************************************************************/
347 #if defined(ENABLE_JIT)
348 bool builtintable_replace_function(void *iptr_)
351 builtintable_entry *bte;
354 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
356 /* get name and descriptor of the function */
359 case ICMD_INVOKESTATIC:
360 /* The instruction MUST be resolved, otherwise we run into
361 lazy loading troubles. Anyway, we should/can only replace
362 very VM-close functions. */
364 if (INSTRUCTION_IS_UNRESOLVED(iptr))
367 mr = iptr->sx.s23.s3.fmiref;
374 /* search the function table */
376 for (bte = builtintable_function; bte->fp != NULL; bte++) {
377 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
378 (mr->name == bte->name) &&
379 (mr->descriptor == bte->descriptor)) {
381 /* set the values in the instruction */
383 iptr->opc = bte->opcode;
384 iptr->sx.s23.s3.bte = bte;
386 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
387 iptr->flags.bits |= INS_FLAG_CHECK;
389 iptr->flags.bits &= ~INS_FLAG_CHECK;
397 #endif /* defined(ENABLE_JIT) */
400 /*****************************************************************************
402 *****************************************************************************/
404 /* builtin_instanceof **********************************************************
406 Checks if an object is an instance of some given class (or subclass
407 of that class). If class is an interface, checks if the interface
410 Return value: 1 ... o is an instance of class or implements the interface
411 0 ... otherwise or if o == NULL
413 *******************************************************************************/
415 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
422 LLNI_class_get(o, c);
424 return class_isanysubclass(c, class);
429 /* builtin_checkcast ***********************************************************
431 The same as builtin_instanceof except that 1 is returned when o ==
434 *******************************************************************************/
436 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
443 LLNI_class_get(o, c);
445 if (class_isanysubclass(c, class))
452 /* builtin_descriptorscompatible ***********************************************
454 Checks if two array type descriptors are assignment compatible
456 Return value: 1 ... target = desc is possible
459 *******************************************************************************/
461 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
462 arraydescriptor *target)
467 if (desc->arraytype != target->arraytype)
470 if (desc->arraytype != ARRAYTYPE_OBJECT)
473 /* {both arrays are arrays of references} */
475 if (desc->dimension == target->dimension) {
476 /* an array which contains elements of interface types is
477 allowed to be casted to Object (JOWENN)*/
479 if ((desc->elementvftbl->baseval < 0) &&
480 (target->elementvftbl->baseval == 1))
483 return class_isanysubclass(desc->elementvftbl->class,
484 target->elementvftbl->class);
487 if (desc->dimension < target->dimension)
490 /* {desc has higher dimension than target} */
492 return class_isanysubclass(pseudo_class_Arraystub,
493 target->elementvftbl->class);
497 /* builtin_arraycheckcast ******************************************************
499 Checks if an object is really a subtype of the requested array
500 type. The object has to be an array to begin with. For simple
501 arrays (int, short, double, etc.) the types have to match exactly.
502 For arrays of objects, the type of elements in the array has to be
503 a subtype (or the same type) of the requested element type. For
504 arrays of arrays (which in turn can again be arrays of arrays), the
505 types at the lowest level have to satisfy the corresponding sub
508 *******************************************************************************/
510 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
512 arraydescriptor *desc;
517 desc = LLNI_vftbl_direct(o)->arraydesc;
522 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
526 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
531 return builtin_arraycheckcast(o, targetclass);
535 /* builtin_throw_exception *****************************************************
537 Sets the exceptionptr with the thrown exception and prints some
538 debugging information. Called from asm_vm_call_method.
540 *******************************************************************************/
542 void *builtin_throw_exception(java_object_t *xptr)
545 java_lang_Throwable *t;
552 t = (java_lang_Throwable *) xptr;
554 /* get detail message */
556 LLNI_field_get_ref(t, detailMessage, s);
558 /* calculate message length */
560 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
564 utf_bytes(xptr->vftbl->class->name);
566 logtextlen += strlen(": ") +
567 u2_utflength(LLNI_field_direct(s, value)->data
568 + LLNI_field_direct(s, offset),
569 LLNI_field_direct(s,count));
573 logtextlen += strlen("(nil)");
576 /* allocate memory */
578 dumpsize = dump_size();
580 logtext = DMNEW(char, logtextlen);
582 strcpy(logtext, "Builtin exception thrown: ");
585 utf_cat_classname(logtext, xptr->vftbl->class->name);
590 buf = javastring_tochar((java_handle_t *) s);
591 strcat(logtext, ": ");
592 strcat(logtext, buf);
593 MFREE(buf, char, strlen(buf) + 1);
597 strcat(logtext, "(nil)");
604 dump_release(dumpsize);
606 #endif /* !defined(NDEBUG) */
608 /* actually set the exception */
610 exceptions_set_exception(xptr);
612 /* Return a NULL pointer. This is required for vm_call_method to
613 check for an exception. This is for convenience. */
619 /* builtin_canstore ************************************************************
621 Checks, if an object can be stored in an array.
623 Return value: 1 ... possible
624 0 ... otherwise (throws an ArrayStoreException)
626 *******************************************************************************/
628 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
634 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
638 /* if not possible, throw an exception */
641 exceptions_throw_arraystoreexception();
647 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
649 arraydescriptor *desc;
650 arraydescriptor *valuedesc;
651 vftbl_t *componentvftbl;
660 /* The following is guaranteed (by verifier checks):
662 * *) oa->...vftbl->arraydesc != NULL
663 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
664 * *) o->vftbl is not an interface vftbl
667 desc = oa->header.objheader.vftbl->arraydesc;
668 componentvftbl = desc->componentvftbl;
669 valuevftbl = o->vftbl;
670 valuedesc = valuevftbl->arraydesc;
672 if ((desc->dimension - 1) == 0) {
673 /* {oa is a one-dimensional array} */
674 /* {oa is an array of references} */
676 if (valuevftbl == componentvftbl)
679 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
681 baseval = componentvftbl->baseval;
684 /* an array of interface references */
686 result = ((valuevftbl->interfacetablelength > -baseval) &&
687 (valuevftbl->interfacetable[baseval] != NULL));
690 diffval = valuevftbl->baseval - componentvftbl->baseval;
691 result = diffval <= (uint32_t) componentvftbl->diffval;
694 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
696 else if (valuedesc == NULL) {
697 /* {oa has dimension > 1} */
698 /* {componentvftbl->arraydesc != NULL} */
700 /* check if o is an array */
705 /* {o is an array} */
707 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
716 /* This is an optimized version where a is guaranteed to be one-dimensional */
717 s4 builtin_canstore_onedim (java_objectarray_t *a, java_object_t *o)
719 arraydescriptor *desc;
720 vftbl_t *elementvftbl;
729 /* The following is guaranteed (by verifier checks):
731 * *) a->...vftbl->arraydesc != NULL
732 * *) a->...vftbl->arraydesc->elementvftbl != NULL
733 * *) a->...vftbl->arraydesc->dimension == 1
734 * *) o->vftbl is not an interface vftbl
737 desc = a->header.objheader.vftbl->arraydesc;
738 elementvftbl = desc->elementvftbl;
739 valuevftbl = o->vftbl;
741 /* {a is a one-dimensional array} */
743 if (valuevftbl == elementvftbl)
746 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
748 baseval = elementvftbl->baseval;
751 /* an array of interface references */
752 result = ((valuevftbl->interfacetablelength > -baseval) &&
753 (valuevftbl->interfacetable[baseval] != NULL));
756 diffval = valuevftbl->baseval - elementvftbl->baseval;
757 result = diffval <= (uint32_t) elementvftbl->diffval;
760 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
766 /* This is an optimized version where a is guaranteed to be a
767 * one-dimensional array of a class type */
768 s4 builtin_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
770 vftbl_t *elementvftbl;
778 /* The following is guaranteed (by verifier checks):
780 * *) a->...vftbl->arraydesc != NULL
781 * *) a->...vftbl->arraydesc->elementvftbl != NULL
782 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
783 * *) a->...vftbl->arraydesc->dimension == 1
784 * *) o->vftbl is not an interface vftbl
787 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
788 valuevftbl = o->vftbl;
790 /* {a is a one-dimensional array} */
792 if (valuevftbl == elementvftbl)
795 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
797 diffval = valuevftbl->baseval - elementvftbl->baseval;
798 result = diffval <= (uint32_t) elementvftbl->diffval;
800 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
806 /* builtin_new *****************************************************************
808 Creates a new instance of class c on the heap.
810 Return value: pointer to the object or NULL if no memory is
813 *******************************************************************************/
815 java_handle_t *builtin_new(classinfo *c)
818 #if defined(ENABLE_RT_TIMING)
819 struct timespec time_start, time_end;
821 #if defined(ENABLE_CYCLES_STATS)
822 u8 cycles_start, cycles_end;
825 RT_TIMING_GET_TIME(time_start);
826 CYCLES_STATS_GET(cycles_start);
828 /* is the class loaded */
830 assert(c->state & CLASS_LOADED);
832 /* check if we can instantiate this class */
834 if (c->flags & ACC_ABSTRACT) {
835 exceptions_throw_instantiationerror(c);
839 /* is the class linked */
841 if (!(c->state & CLASS_LINKED))
845 if (!(c->state & CLASS_INITIALIZED)) {
848 log_message_class("Initialize class (from builtin_new): ", c);
851 if (!initialize_class(c))
855 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
863 #if defined(ENABLE_THREADS)
864 lock_init_object_lock(o);
867 CYCLES_STATS_GET(cycles_end);
868 RT_TIMING_GET_TIME(time_end);
870 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
871 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
877 /* builtin_fast_new ************************************************************
879 Creates a new instance of class c on the heap.
881 Return value: pointer to the object or NULL if no fast return
882 is possible for any reason.
884 *******************************************************************************/
886 java_object_t *builtin_fast_new(classinfo *c)
889 #if defined(ENABLE_RT_TIMING)
890 struct timespec time_start, time_end;
892 #if defined(ENABLE_CYCLES_STATS)
893 u8 cycles_start, cycles_end;
896 RT_TIMING_GET_TIME(time_start);
897 CYCLES_STATS_GET(cycles_start);
899 /* is the class loaded */
901 assert(c->state & CLASS_LOADED);
903 /* check if we can instantiate this class */
905 if (c->flags & ACC_ABSTRACT)
908 /* is the class linked */
910 if (!(c->state & CLASS_LINKED))
913 if (!(c->state & CLASS_INITIALIZED))
916 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
917 c->finalizer, false);
924 #if defined(ENABLE_THREADS)
925 lock_init_object_lock(o);
928 CYCLES_STATS_GET(cycles_end);
929 RT_TIMING_GET_TIME(time_end);
931 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
932 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
938 /* builtin_newarray ************************************************************
940 Creates an array with the given vftbl on the heap. This function
941 takes as class argument an array class.
943 Return value: pointer to the array or NULL if no memory is available
945 *******************************************************************************/
947 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
949 arraydescriptor *desc;
954 #if defined(ENABLE_RT_TIMING)
955 struct timespec time_start, time_end;
958 RT_TIMING_GET_TIME(time_start);
960 desc = arrayclass->vftbl->arraydesc;
961 dataoffset = desc->dataoffset;
962 componentsize = desc->componentsize;
965 exceptions_throw_negativearraysizeexception();
969 actualsize = dataoffset + size * componentsize;
971 /* check for overflow */
973 if (((u4) actualsize) < ((u4) size)) {
974 exceptions_throw_outofmemoryerror();
978 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
983 a->objheader.vftbl = arrayclass->vftbl;
985 #if defined(ENABLE_THREADS)
986 lock_init_object_lock(&a->objheader);
989 LLNI_array_size(a) = size;
991 RT_TIMING_GET_TIME(time_end);
992 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
998 /* builtin_anewarray ***********************************************************
1000 Creates an array of references to the given class type on the heap.
1002 Return value: pointer to the array or NULL if no memory is
1005 *******************************************************************************/
1007 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
1009 classinfo *arrayclass;
1011 /* is class loaded */
1013 assert(componentclass->state & CLASS_LOADED);
1015 /* is class linked */
1017 if (!(componentclass->state & CLASS_LINKED))
1018 if (!link_class(componentclass))
1021 arrayclass = class_array_of(componentclass, true);
1026 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1030 /* builtin_newarray_boolean ****************************************************
1032 Creates an array of bytes on the heap. The array is designated as
1033 an array of booleans (important for casts)
1035 Return value: pointer to the array or NULL if no memory is
1038 *******************************************************************************/
1040 java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
1042 return (java_handle_booleanarray_t *)
1043 builtin_newarray(size,
1044 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
1048 /* builtin_newarray_byte *******************************************************
1050 Creates an array of 8 bit Integers on the heap.
1052 Return value: pointer to the array or NULL if no memory is
1055 *******************************************************************************/
1057 java_handle_bytearray_t *builtin_newarray_byte(s4 size)
1059 return (java_handle_bytearray_t *)
1060 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
1064 /* builtin_newarray_char *******************************************************
1066 Creates an array of characters on the heap.
1068 Return value: pointer to the array or NULL if no memory is
1071 *******************************************************************************/
1073 java_handle_chararray_t *builtin_newarray_char(s4 size)
1075 return (java_handle_chararray_t *)
1076 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1080 /* builtin_newarray_short ******************************************************
1082 Creates an array of 16 bit Integers on the heap.
1084 Return value: pointer to the array or NULL if no memory is
1087 *******************************************************************************/
1089 java_handle_shortarray_t *builtin_newarray_short(s4 size)
1091 return (java_handle_shortarray_t *)
1092 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1096 /* builtin_newarray_int ********************************************************
1098 Creates an array of 32 bit Integers on the heap.
1100 Return value: pointer to the array or NULL if no memory is
1103 *******************************************************************************/
1105 java_handle_intarray_t *builtin_newarray_int(s4 size)
1107 return (java_handle_intarray_t *)
1108 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1112 /* builtin_newarray_long *******************************************************
1114 Creates an array of 64 bit Integers on the heap.
1116 Return value: pointer to the array or NULL if no memory is
1119 *******************************************************************************/
1121 java_handle_longarray_t *builtin_newarray_long(s4 size)
1123 return (java_handle_longarray_t *)
1124 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1128 /* builtin_newarray_float ******************************************************
1130 Creates an array of 32 bit IEEE floats on the heap.
1132 Return value: pointer to the array or NULL if no memory is
1135 *******************************************************************************/
1137 java_handle_floatarray_t *builtin_newarray_float(s4 size)
1139 return (java_handle_floatarray_t *)
1140 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1144 /* builtin_newarray_double *****************************************************
1146 Creates an array of 64 bit IEEE floats on the heap.
1148 Return value: pointer to the array or NULL if no memory is
1151 *******************************************************************************/
1153 java_handle_doublearray_t *builtin_newarray_double(s4 size)
1155 return (java_handle_doublearray_t *)
1156 builtin_newarray(size,
1157 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1161 /* builtin_multianewarray_intern ***********************************************
1163 Creates a multi-dimensional array on the heap. The dimensions are
1164 passed in an array of longs.
1167 n.............number of dimensions to create
1168 arrayclass....the array class
1169 dims..........array containing the size of each dimension to create
1171 Return value: pointer to the array or NULL if no memory is
1174 ******************************************************************************/
1176 static java_handle_t *builtin_multianewarray_intern(int n,
1177 classinfo *arrayclass,
1182 classinfo *componentclass;
1185 /* create this dimension */
1187 size = (s4) dims[0];
1188 a = builtin_newarray(size, arrayclass);
1193 /* if this is the last dimension return */
1198 /* get the class of the components to create */
1200 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1202 /* The verifier guarantees that the dimension count is in the range. */
1204 /* create the component arrays */
1206 for (i = 0; i < size; i++) {
1208 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1209 /* we save an s4 to a s8 slot, 8-byte aligned */
1211 builtin_multianewarray_intern(n, componentclass, dims + 2);
1213 builtin_multianewarray_intern(n, componentclass, dims + 1);
1219 LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1226 /* builtin_multianewarray ******************************************************
1228 Wrapper for builtin_multianewarray_intern which checks all
1229 dimensions before we start allocating.
1231 ******************************************************************************/
1233 java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
1239 /* check all dimensions before doing anything */
1241 for (i = 0; i < n; i++) {
1242 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1243 /* we save an s4 to a s8 slot, 8-byte aligned */
1244 size = (s4) dims[i * 2];
1246 size = (s4) dims[i];
1250 exceptions_throw_negativearraysizeexception();
1255 /* now call the real function */
1257 return builtin_multianewarray_intern(n, arrayclass, dims);
1261 /*****************************************************************************
1264 Various functions for printing a message at method entry or exit (for
1267 *****************************************************************************/
1269 #if !defined(NDEBUG)
1270 static s4 methodindent = 0;
1271 static u4 callcount = 0;
1272 #endif /* !defined(NDEBUG) */
1275 /* builtin_print_argument ******************************************************
1277 Prints arguments and return values for the call trace.
1279 *******************************************************************************/
1281 #if !defined(NDEBUG)
1282 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1283 typedesc *paramtype, s8 value)
1291 switch (paramtype->type) {
1294 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1299 #if SIZEOF_VOID_P == 4
1300 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1302 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1307 #if defined(__S390__)
1309 /* The below won't work on S390 */
1313 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1318 #if SIZEOF_VOID_P == 4
1319 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1321 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1326 #if SIZEOF_VOID_P == 4
1327 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1329 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1332 /* cast to java.lang.Object */
1334 o = (java_object_t *) (ptrint) value;
1336 /* check return argument for java.lang.Class or java.lang.String */
1339 if (o->vftbl->class == class_java_lang_String) {
1340 /* get java.lang.String object and the length of the
1343 u = javastring_toutf(o, false);
1345 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1347 /* realloc memory for string length */
1349 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1352 /* convert to utf8 string and strcat it to the logtext */
1354 strcat(logtext, " (String = \"");
1355 utf_cat(logtext, u);
1356 strcat(logtext, "\")");
1359 if (o->vftbl->class == class_java_lang_Class) {
1360 /* if the object returned is a java.lang.Class
1361 cast it to classinfo structure and get the name
1364 c = (classinfo *) o;
1369 /* if the object returned is not a java.lang.String or
1370 a java.lang.Class just print the name of the class */
1372 u = o->vftbl->class->name;
1375 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1377 /* realloc memory for string length */
1379 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1382 /* strcat to the logtext */
1384 strcat(logtext, " (Class = \"");
1385 utf_cat_classname(logtext, u);
1386 strcat(logtext, "\")");
1393 #endif /* !defined(NDEBUG) */
1395 /* builtin_verbosecall_enter ***************************************************
1397 Print method call with arguments for -verbose:call.
1399 *******************************************************************************/
1401 #if !defined(NDEBUG)
1403 #ifdef TRACE_ARGS_NUM
1404 void builtin_verbosecall_enter(s8 a0, s8 a1,
1405 # if TRACE_ARGS_NUM >= 4
1408 # if TRACE_ARGS_NUM >= 6
1411 # if TRACE_ARGS_NUM == 8
1423 #if defined(ENABLE_DEBUG_FILTER)
1424 if (! show_filters_test_verbosecall_enter(m)) return;
1427 #if defined(ENABLE_VMLOG)
1428 vmlog_cacao_enter_method(m);
1434 /* calculate message length */
1437 strlen("4294967295 ") +
1438 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1440 strlen("called: ") +
1441 utf_bytes(m->class->name) +
1443 utf_bytes(m->name) +
1444 utf_bytes(m->descriptor);
1446 /* Actually it's not possible to have all flags printed, but:
1451 strlen(" PRIVATE") +
1452 strlen(" PROTECTED") +
1455 strlen(" SYNCHRONIZED") +
1456 strlen(" VOLATILE") +
1457 strlen(" TRANSIENT") +
1459 strlen(" INTERFACE") +
1460 strlen(" ABSTRACT");
1462 /* add maximal argument length */
1466 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1467 strlen("...(255)") +
1470 /* allocate memory */
1472 dumpsize = dump_size();
1474 logtext = DMNEW(char, logtextlen);
1478 sprintf(logtext, "%10d ", callcount);
1479 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1481 pos = strlen(logtext);
1483 for (i = 0; i < methodindent; i++)
1484 logtext[pos++] = '\t';
1486 strcpy(logtext + pos, "called: ");
1488 utf_cat_classname(logtext, m->class->name);
1489 strcat(logtext, ".");
1490 utf_cat(logtext, m->name);
1491 utf_cat(logtext, m->descriptor);
1493 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1494 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1495 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1496 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1497 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1498 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1499 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1500 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1501 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1502 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1503 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1505 strcat(logtext, "(");
1507 if (md->paramcount >= 1) {
1508 logtext = builtin_print_argument(logtext, &logtextlen,
1509 &md->paramtypes[0], a0);
1512 if (md->paramcount >= 2) {
1513 strcat(logtext, ", ");
1515 logtext = builtin_print_argument(logtext, &logtextlen,
1516 &md->paramtypes[1], a1);
1519 #if TRACE_ARGS_NUM >= 4
1520 if (md->paramcount >= 3) {
1521 strcat(logtext, ", ");
1523 logtext = builtin_print_argument(logtext, &logtextlen,
1524 &md->paramtypes[2], a2);
1527 if (md->paramcount >= 4) {
1528 strcat(logtext, ", ");
1530 logtext = builtin_print_argument(logtext, &logtextlen,
1531 &md->paramtypes[3], a3);
1535 #if TRACE_ARGS_NUM >= 6
1536 if (md->paramcount >= 5) {
1537 strcat(logtext, ", ");
1539 logtext = builtin_print_argument(logtext, &logtextlen,
1540 &md->paramtypes[4], a4);
1543 if (md->paramcount >= 6) {
1544 strcat(logtext, ", ");
1546 logtext = builtin_print_argument(logtext, &logtextlen,
1547 &md->paramtypes[5], a5);
1551 #if TRACE_ARGS_NUM == 8
1552 if (md->paramcount >= 7) {
1553 strcat(logtext, ", ");
1555 logtext = builtin_print_argument(logtext, &logtextlen,
1556 &md->paramtypes[6], a6);
1559 if (md->paramcount >= 8) {
1560 strcat(logtext, ", ");
1562 logtext = builtin_print_argument(logtext, &logtextlen,
1563 &md->paramtypes[7], a7);
1567 if (md->paramcount > 8) {
1568 sprintf(logtext + strlen(logtext), ", ...(%d)",
1569 md->paramcount - TRACE_ARGS_NUM);
1572 strcat(logtext, ")");
1576 /* release memory */
1578 dump_release(dumpsize);
1584 #endif /* !defined(NDEBUG) */
1587 /* builtin_verbosecall_exit ****************************************************
1589 Print method exit for -verbose:call.
1591 *******************************************************************************/
1593 #if !defined(NDEBUG)
1594 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1604 #if defined(ENABLE_DEBUG_FILTER)
1605 if (! show_filters_test_verbosecall_exit(m)) return;
1608 #if defined(ENABLE_VMLOG)
1609 vmlog_cacao_leave_method(m);
1615 /* calculate message length */
1618 strlen("4294967295 ") +
1619 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1621 strlen("finished: ") +
1622 utf_bytes(m->class->name) +
1624 utf_bytes(m->name) +
1625 utf_bytes(m->descriptor) +
1626 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1628 /* add maximal argument length */
1630 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1632 /* allocate memory */
1634 dumpsize = dump_size();
1636 logtext = DMNEW(char, logtextlen);
1638 /* outdent the log message */
1643 log_text("WARNING: unmatched methodindent--");
1645 /* generate the message */
1647 sprintf(logtext, " ");
1648 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1650 pos = strlen(logtext);
1652 for (i = 0; i < methodindent; i++)
1653 logtext[pos++] = '\t';
1655 strcpy(logtext + pos, "finished: ");
1656 utf_cat_classname(logtext, m->class->name);
1657 strcat(logtext, ".");
1658 utf_cat(logtext, m->name);
1659 utf_cat(logtext, m->descriptor);
1661 if (!IS_VOID_TYPE(md->returntype.type)) {
1662 strcat(logtext, "->");
1664 switch (md->returntype.type) {
1681 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1686 /* release memory */
1688 dump_release(dumpsize);
1691 #endif /* !defined(NDEBUG) */
1694 #if defined(ENABLE_CYCLES_STATS)
1695 void builtin_print_cycles_stats(FILE *file)
1697 fprintf(file,"builtin cylce count statistics:\n");
1699 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1700 CYCLES_STATS_PRINT(builtin_new ,file);
1704 #endif /* defined(ENABLE_CYCLES_STATS) */
1707 /*****************************************************************************
1708 MISCELLANEOUS HELPER FUNCTIONS
1709 *****************************************************************************/
1713 /*********** Functions for integer divisions *****************************
1715 On some systems (eg. DEC ALPHA), integer division is not supported by the
1716 CPU. These helper functions implement the missing functionality.
1718 ******************************************************************************/
1720 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1721 s4 builtin_idiv(s4 a, s4 b)
1730 s4 builtin_irem(s4 a, s4 b)
1738 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1741 /* functions for long arithmetics **********************************************
1743 On systems where 64 bit Integers are not supported by the CPU,
1744 these functions are needed.
1746 ******************************************************************************/
1748 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1749 s8 builtin_ladd(s8 a, s8 b)
1762 s8 builtin_lsub(s8 a, s8 b)
1775 s8 builtin_lneg(s8 a)
1787 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1790 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1791 s8 builtin_lmul(s8 a, s8 b)
1803 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1806 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1807 s8 builtin_ldiv(s8 a, s8 b)
1820 s8 builtin_lrem(s8 a, s8 b)
1832 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1835 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1836 s8 builtin_lshl(s8 a, s4 b)
1849 s8 builtin_lshr(s8 a, s4 b)
1862 s8 builtin_lushr(s8 a, s4 b)
1867 c = ((u8) a) >> (b & 63);
1874 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1877 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1878 s8 builtin_land(s8 a, s8 b)
1891 s8 builtin_lor(s8 a, s8 b)
1904 s8 builtin_lxor(s8 a, s8 b)
1916 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1919 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1920 s4 builtin_lcmp(s8 a, s8 b)
1934 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1937 /* functions for unsupported floating instructions ****************************/
1939 /* used to convert FLT_xxx defines into float values */
1941 static inline float intBitsToFloat(s4 i)
1950 /* used to convert DBL_xxx defines into double values */
1952 static inline float longBitsToDouble(s8 l)
1962 float builtin_fadd(float a, float b)
1964 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1965 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1976 if (copysignf(1.0, a) == copysignf(1.0, b))
1979 return intBitsToFloat(FLT_NAN);
1985 float builtin_fsub(float a, float b)
1987 return builtin_fadd(a, builtin_fneg(b));
1991 float builtin_fmul(float a, float b)
1993 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1994 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1996 if (finitef(b)) return a * b;
1998 if (a == 0) return intBitsToFloat(FLT_NAN);
1999 else return copysignf(b, copysignf(1.0, b)*a);
2004 if (b == 0) return intBitsToFloat(FLT_NAN);
2005 else return copysignf(a, copysignf(1.0, a)*b);
2008 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2014 /* builtin_ddiv ****************************************************************
2016 Implementation as described in VM Spec.
2018 *******************************************************************************/
2020 float builtin_fdiv(float a, float b)
2024 /* If neither value1' nor value2' is NaN, the sign of the result */
2025 /* is positive if both values have the same sign, negative if the */
2026 /* values have different signs. */
2032 /* If either value1' or value2' is NaN, the result is NaN. */
2034 return intBitsToFloat(FLT_NAN);
2037 /* Division of a finite value by an infinity results in a */
2038 /* signed zero, with the sign-producing rule just given. */
2040 /* is sign equal? */
2042 if (copysignf(1.0, a) == copysignf(1.0, b))
2051 /* If either value1' or value2' is NaN, the result is NaN. */
2053 return intBitsToFloat(FLT_NAN);
2055 } else if (finitef(b)) {
2056 /* Division of an infinity by a finite value results in a signed */
2057 /* infinity, with the sign-producing rule just given. */
2059 /* is sign equal? */
2061 if (copysignf(1.0, a) == copysignf(1.0, b))
2062 return intBitsToFloat(FLT_POSINF);
2064 return intBitsToFloat(FLT_NEGINF);
2067 /* Division of an infinity by an infinity results in NaN. */
2069 return intBitsToFloat(FLT_NAN);
2075 float builtin_fneg(float a)
2077 if (isnanf(a)) return a;
2079 if (finitef(a)) return -a;
2080 else return copysignf(a, -copysignf(1.0, a));
2083 #endif /* !SUPPORT_FLOAT */
2086 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2087 s4 builtin_fcmpl(float a, float b)
2095 if (!finitef(a) || !finitef(b)) {
2096 a = finitef(a) ? 0 : copysignf(1.0, a);
2097 b = finitef(b) ? 0 : copysignf(1.0, b);
2110 s4 builtin_fcmpg(float a, float b)
2112 if (isnanf(a)) return 1;
2113 if (isnanf(b)) return 1;
2114 if (!finitef(a) || !finitef(b)) {
2115 a = finitef(a) ? 0 : copysignf(1.0, a);
2116 b = finitef(b) ? 0 : copysignf(1.0, b);
2118 if (a > b) return 1;
2119 if (a == b) return 0;
2122 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2125 float builtin_frem(float a, float b)
2131 /* functions for unsupported double instructions ******************************/
2134 double builtin_dadd(double a, double b)
2136 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2137 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2139 if (finite(b)) return a + b;
2143 if (finite(b)) return a;
2145 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2146 else return longBitsToDouble(DBL_NAN);
2152 double builtin_dsub(double a, double b)
2154 return builtin_dadd(a, builtin_dneg(b));
2158 double builtin_dmul(double a, double b)
2160 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2161 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2163 if (finite(b)) return a * b;
2165 if (a == 0) return longBitsToDouble(DBL_NAN);
2166 else return copysign(b, copysign(1.0, b) * a);
2171 if (b == 0) return longBitsToDouble(DBL_NAN);
2172 else return copysign(a, copysign(1.0, a) * b);
2175 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2181 /* builtin_ddiv ****************************************************************
2183 Implementation as described in VM Spec.
2185 *******************************************************************************/
2187 double builtin_ddiv(double a, double b)
2191 /* If neither value1' nor value2' is NaN, the sign of the result */
2192 /* is positive if both values have the same sign, negative if the */
2193 /* values have different signs. */
2199 /* If either value1' or value2' is NaN, the result is NaN. */
2201 return longBitsToDouble(DBL_NAN);
2204 /* Division of a finite value by an infinity results in a */
2205 /* signed zero, with the sign-producing rule just given. */
2207 /* is sign equal? */
2209 if (copysign(1.0, a) == copysign(1.0, b))
2218 /* If either value1' or value2' is NaN, the result is NaN. */
2220 return longBitsToDouble(DBL_NAN);
2222 } else if (finite(b)) {
2223 /* Division of an infinity by a finite value results in a signed */
2224 /* infinity, with the sign-producing rule just given. */
2226 /* is sign equal? */
2228 if (copysign(1.0, a) == copysign(1.0, b))
2229 return longBitsToDouble(DBL_POSINF);
2231 return longBitsToDouble(DBL_NEGINF);
2234 /* Division of an infinity by an infinity results in NaN. */
2236 return longBitsToDouble(DBL_NAN);
2242 /* builtin_dneg ****************************************************************
2244 Implemented as described in VM Spec.
2246 *******************************************************************************/
2248 double builtin_dneg(double a)
2251 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2258 /* If the operand is a zero, the result is the zero of opposite */
2264 /* If the operand is an infinity, the result is the infinity of */
2265 /* opposite sign. */
2267 return copysign(a, -copysign(1.0, a));
2271 #endif /* !SUPPORT_DOUBLE */
2274 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2275 s4 builtin_dcmpl(double a, double b)
2283 if (!finite(a) || !finite(b)) {
2284 a = finite(a) ? 0 : copysign(1.0, a);
2285 b = finite(b) ? 0 : copysign(1.0, b);
2298 s4 builtin_dcmpg(double a, double b)
2306 if (!finite(a) || !finite(b)) {
2307 a = finite(a) ? 0 : copysign(1.0, a);
2308 b = finite(b) ? 0 : copysign(1.0, b);
2319 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2322 double builtin_drem(double a, double b)
2328 /* conversion operations ******************************************************/
2331 s8 builtin_i2l(s4 i)
2343 s4 builtin_l2i(s8 l)
2354 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2355 float builtin_i2f(s4 a)
2357 float f = (float) a;
2360 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2363 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2364 double builtin_i2d(s4 a)
2366 double d = (double) a;
2369 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2372 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2373 float builtin_l2f(s8 a)
2376 float f = (float) a;
2382 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2385 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2386 double builtin_l2d(s8 a)
2389 double d = (double) a;
2395 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2398 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2399 s4 builtin_f2i(float a)
2403 i = builtin_d2i((double) a);
2414 if (a < (-2147483648))
2415 return (-2147483648);
2418 f = copysignf((float) 1.0, a);
2421 return (-2147483648); */
2423 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2426 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2427 s8 builtin_f2l(float a)
2431 l = builtin_d2l((double) a);
2438 if (a > 9223372036854775807L)
2439 return 9223372036854775807L;
2440 if (a < (-9223372036854775808L))
2441 return (-9223372036854775808L);
2446 f = copysignf((float) 1.0, a);
2448 return 9223372036854775807L;
2449 return (-9223372036854775808L); */
2451 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2454 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2455 s4 builtin_d2i(double a)
2460 if (a >= 2147483647)
2462 if (a <= (-2147483647-1))
2463 return (-2147483647-1);
2468 d = copysign(1.0, a);
2471 return (-2147483647-1);
2473 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2476 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2477 s8 builtin_d2l(double a)
2482 if (a >= 9223372036854775807LL)
2483 return 9223372036854775807LL;
2484 if (a <= (-9223372036854775807LL-1))
2485 return (-9223372036854775807LL-1);
2490 d = copysign(1.0, a);
2492 return 9223372036854775807LL;
2493 return (-9223372036854775807LL-1);
2495 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2498 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2499 double builtin_f2d(float a)
2501 if (finitef(a)) return (double) a;
2504 return longBitsToDouble(DBL_NAN);
2506 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2510 float builtin_d2f(double a)
2516 return intBitsToFloat(FLT_NAN);
2518 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2521 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2524 /* builtin_arraycopy ***********************************************************
2526 Builtin for java.lang.System.arraycopy.
2528 ATTENTION: This builtin function returns a boolean value to signal
2529 the ICMD_BUILTIN if there was an exception.
2531 *******************************************************************************/
2533 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2534 java_handle_t *dest, s4 destStart, s4 len)
2536 arraydescriptor *sdesc;
2537 arraydescriptor *ddesc;
2540 if ((src == NULL) || (dest == NULL)) {
2541 exceptions_throw_nullpointerexception();
2545 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2546 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2548 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2549 exceptions_throw_arraystoreexception();
2553 /* we try to throw exception with the same message as SUN does */
2555 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2556 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2557 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2558 exceptions_throw_arrayindexoutofboundsexception();
2562 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2563 /* We copy primitive values or references of exactly the same type */
2565 s4 dataoffset = sdesc->dataoffset;
2566 s4 componentsize = sdesc->componentsize;
2568 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2569 ((u1 *) src) + dataoffset + componentsize * srcStart,
2570 (size_t) len * componentsize);
2573 /* We copy references of different type */
2575 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2576 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2578 if (destStart <= srcStart) {
2579 for (i = 0; i < len; i++) {
2582 LLNI_objectarray_element_get(oas, srcStart + i, o);
2584 if (!builtin_canstore(oad, o))
2587 LLNI_objectarray_element_set(oad, destStart + i, o);
2591 /* XXX this does not completely obey the specification!
2592 If an exception is thrown only the elements above the
2593 current index have been copied. The specification
2594 requires that only the elements *below* the current
2595 index have been copied before the throw. */
2597 for (i = len - 1; i >= 0; i--) {
2600 LLNI_objectarray_element_get(oas, srcStart + i, o);
2602 if (!builtin_canstore(oad, o))
2605 LLNI_objectarray_element_set(oad, destStart + i, o);
2614 /* builtin_nanotime ************************************************************
2616 Return the current time in nanoseconds.
2618 *******************************************************************************/
2620 s8 builtin_nanotime(void)
2625 if (gettimeofday(&tv, NULL) == -1)
2626 vm_abort("gettimeofday failed: %s", strerror(errno));
2628 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2630 return usecs * 1000;
2634 /* builtin_currenttimemillis ***************************************************
2636 Return the current time in milliseconds.
2638 *******************************************************************************/
2640 s8 builtin_currenttimemillis(void)
2644 msecs = builtin_nanotime() / 1000 / 1000;
2650 /* builtin_clone ***************************************************************
2652 Function for cloning objects or arrays.
2654 *******************************************************************************/
2656 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2658 arraydescriptor *ad;
2662 java_handle_t *co; /* cloned object header */
2664 /* get the array descriptor */
2666 ad = LLNI_vftbl_direct(o)->arraydesc;
2668 /* we are cloning an array */
2671 ah = (java_handle_t *) o;
2673 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2675 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2680 MCOPY(co, o, u1, size);
2682 #if defined(ENABLE_GC_CACAO)
2683 heap_init_objectheader(co, size);
2686 #if defined(ENABLE_THREADS)
2687 lock_init_object_lock(co);
2693 /* we are cloning a non-array */
2695 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2696 exceptions_throw_clonenotsupportedexception();
2700 /* get the class of the object */
2702 LLNI_class_get(o, c);
2704 /* create new object */
2706 co = builtin_new(c);
2711 MCOPY(co, o, u1, c->instancesize);
2713 #if defined(ENABLE_GC_CACAO)
2714 heap_init_objectheader(co, c->instancesize);
2717 #if defined(ENABLE_THREADS)
2718 lock_init_object_lock(co);
2724 #if defined(ENABLE_VMLOG)
2726 #include <vmlog_cacao.c>
2731 * These are local overrides for various environment variables in Emacs.
2732 * Please do not remove this and leave it at the end of the file, where
2733 * Emacs will automagically detect them.
2734 * ---------------------------------------------------------------------
2737 * indent-tabs-mode: t
2741 * vim:noexpandtab:sw=4:ts=4: