1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
34 Contains C functions for JavaVM Instructions that cannot be
35 translated to machine language directly. Consequently, the
36 generated machine code for these instructions contains function
37 calls instead of machine instructions, using the C calling
40 $Id: builtin.c 5900 2006-11-04 17:30:44Z michi $
59 #include "fdlibm/fdlibm.h"
60 #if defined(__CYGWIN__) && defined(Bias)
64 #include "mm/gc-common.h"
65 #include "mm/memory.h"
66 #include "native/native.h"
67 #include "native/include/java_lang_Cloneable.h"
68 #include "native/include/java_lang_Object.h" /* required by VMObject */
69 #include "native/include/java_lang_VMObject.h"
71 #if defined(ENABLE_THREADS)
72 # include "threads/native/threads.h"
75 #include "toolbox/logging.h"
76 #include "toolbox/util.h"
77 #include "vm/builtin.h"
79 #include "vm/exceptions.h"
80 #include "vm/global.h"
81 #include "vm/initialize.h"
82 #include "vm/loader.h"
83 #include "vm/options.h"
84 #include "vm/stringlocal.h"
85 #include "vm/jit/asmpart.h"
86 #include "vm/jit/patcher.h"
87 #include "vm/rt-timing.h"
88 #include "vm/cycles-stats.h"
91 /* include builtin tables *****************************************************/
93 #include "vm/builtintable.inc"
96 CYCLES_STATS_DECLARE(builtin_new ,100,5)
97 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
110 builtintable_entry *bte;
112 /* mark start of dump memory area */
114 dumpsize = dump_size();
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* first add all descriptors to the pool */
130 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
131 /* create a utf8 string from descriptor */
133 bte->descriptor = utf_new_char(bte->cdescriptor);
135 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
136 /* release dump area */
138 dump_release(dumpsize);
144 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
145 bte->descriptor = utf_new_char(bte->cdescriptor);
147 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
148 dump_release(dumpsize);
153 for (bte = builtintable_function; bte->fp != NULL; bte++) {
154 bte->classname = utf_new_char(bte->cclassname);
155 bte->name = utf_new_char(bte->cname);
156 bte->descriptor = utf_new_char(bte->cdescriptor);
158 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
159 dump_release(dumpsize);
164 /* create the class reference table */
166 (void) descriptor_pool_create_classrefs(descpool, NULL);
168 /* allocate space for the parsed descriptors */
170 descriptor_pool_alloc_parsed_descriptors(descpool);
172 /* now parse all descriptors */
174 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175 /* parse the descriptor, builtin is always static (no `this' pointer) */
177 bte->md = descriptor_pool_parse_method_descriptor(descpool,
182 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
183 bte->md = descriptor_pool_parse_method_descriptor(descpool,
188 for (bte = builtintable_function; bte->fp != NULL; bte++) {
189 bte->md = descriptor_pool_parse_method_descriptor(descpool,
194 /* release dump area */
196 dump_release(dumpsize);
202 /* builtintable_comparator *****************************************************
204 qsort comparator for the automatic builtin table.
206 *******************************************************************************/
208 static int builtintable_comparator(const void *a, const void *b)
210 builtintable_entry *bte1;
211 builtintable_entry *bte2;
213 bte1 = (builtintable_entry *) a;
214 bte2 = (builtintable_entry *) b;
216 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
220 /* builtintable_sort_automatic *************************************************
222 Sorts the automatic builtin table.
224 *******************************************************************************/
226 static void builtintable_sort_automatic(void)
230 /* calculate table size statically (`- 1' comment see builtintable.inc) */
232 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
234 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
235 builtintable_comparator);
239 /* builtin_init ****************************************************************
241 Initialize the global table of builtin functions.
243 *******************************************************************************/
245 bool builtin_init(void)
247 /* initialize the builtin tables */
249 if (!builtintable_init())
252 /* sort builtin tables */
254 builtintable_sort_automatic();
260 /* builtintable_get_internal ***************************************************
262 Finds an entry in the builtintable for internal functions and
263 returns the a pointer to the structure.
265 *******************************************************************************/
267 builtintable_entry *builtintable_get_internal(functionptr fp)
269 builtintable_entry *bte;
271 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
280 /* builtintable_get_automatic **************************************************
282 Finds an entry in the builtintable for functions which are replaced
283 automatically and returns the a pointer to the structure.
285 *******************************************************************************/
287 builtintable_entry *builtintable_get_automatic(s4 opcode)
289 builtintable_entry *first;
290 builtintable_entry *last;
291 builtintable_entry *middle;
295 /* calculate table size statically (`- 1' comment see builtintable.inc) */
297 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
299 first = builtintable_automatic;
300 last = builtintable_automatic + entries;
302 while (entries > 0) {
304 middle = first + half;
306 if (middle->opcode < opcode) {
313 return (first != last ? first : NULL);
317 /* builtintable_replace_function ***********************************************
321 *******************************************************************************/
323 bool builtintable_replace_function(instruction *iptr)
326 builtintable_entry *bte;
328 /* get name and descriptor of the function */
331 case ICMD_INVOKESTATIC:
332 /* The instruction MUST be resolved, otherwise we run into
333 lazy loading troubles. Anyway, we should/can only replace
334 very VM-close functions. */
336 if (INSTRUCTION_IS_UNRESOLVED(iptr))
339 mr = iptr->sx.s23.s3.fmiref;
346 /* search the function table */
348 for (bte = builtintable_function; bte->fp != NULL; bte++) {
349 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
350 (mr->name == bte->name) &&
351 (mr->descriptor == bte->descriptor)) {
353 /* set the values in the instruction */
355 iptr->opc = bte->opcode;
356 iptr->sx.s23.s3.bte = bte;
357 if (bte->checkexception)
358 iptr->flags.bits |= INS_FLAG_CHECK;
360 iptr->flags.bits &= ~INS_FLAG_CHECK;
370 /*****************************************************************************
372 *****************************************************************************/
376 /*************** internal function: builtin_isanysubclass *********************
378 Checks a subclass relation between two classes. Implemented interfaces
379 are interpreted as super classes.
380 Return value: 1 ... sub is subclass of super
383 ******************************************************************************/
385 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
388 castinfo classvalues;
393 if (super->flags & ACC_INTERFACE) {
394 res = (sub->vftbl->interfacetablelength > super->index) &&
395 (sub->vftbl->interfacetable[-super->index] != NULL);
398 /* java.lang.Object is the only super_class_ of any interface */
399 if (sub->flags & ACC_INTERFACE)
400 return (super == class_java_lang_Object);
402 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
404 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
405 (u4) classvalues.super_diffval;
412 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
416 castinfo classvalues;
421 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
423 if ((base = classvalues.super_baseval) <= 0) {
424 /* super is an interface */
425 res = (sub->interfacetablelength > -base) &&
426 (sub->interfacetable[base] != NULL);
429 /* java.lang.Object is the only super_class_ of any interface */
430 if (classvalues.sub_baseval <= 0)
431 return classvalues.super_baseval == 1;
433 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
434 <= (u4) classvalues.super_diffval;
441 /****************** function: builtin_instanceof *****************************
443 Checks if an object is an instance of some given class (or subclass of
444 that class). If class is an interface, checks if the interface is
446 Return value: 1 ... obj is an instance of class or implements the interface
447 0 ... otherwise or if obj == NULL
449 *****************************************************************************/
451 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
456 return builtin_isanysubclass(obj->vftbl->class, class);
461 /**************** function: builtin_checkcast *******************************
463 The same as builtin_instanceof except that 1 is returned when
466 ****************************************************************************/
468 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
473 if (builtin_isanysubclass(obj->vftbl->class, class))
480 /* builtin_descriptorscompatible ***********************************************
482 Checks if two array type descriptors are assignment compatible
484 Return value: 1 ... target = desc is possible
487 *******************************************************************************/
489 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
490 arraydescriptor *target)
495 if (desc->arraytype != target->arraytype)
498 if (desc->arraytype != ARRAYTYPE_OBJECT)
501 /* {both arrays are arrays of references} */
503 if (desc->dimension == target->dimension) {
504 /* an array which contains elements of interface types is
505 allowed to be casted to Object (JOWENN)*/
507 if ((desc->elementvftbl->baseval < 0) &&
508 (target->elementvftbl->baseval == 1))
511 return builtin_isanysubclass_vftbl(desc->elementvftbl,
512 target->elementvftbl);
515 if (desc->dimension < target->dimension)
518 /* {desc has higher dimension than target} */
520 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
521 target->elementvftbl);
525 /* builtin_arraycheckcast ******************************************************
527 Checks if an object is really a subtype of the requested array
528 type. The object has to be an array to begin with. For simple
529 arrays (int, short, double, etc.) the types have to match exactly.
530 For arrays of objects, the type of elements in the array has to be
531 a subtype (or the same type) of the requested element type. For
532 arrays of arrays (which in turn can again be arrays of arrays), the
533 types at the lowest level have to satisfy the corresponding sub
536 *******************************************************************************/
538 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
540 arraydescriptor *desc;
545 if ((desc = o->vftbl->arraydesc) == NULL)
548 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
552 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
557 return builtin_arraycheckcast(o, targetclass);
561 /* builtin_throw_exception *****************************************************
563 Sets the exceptionptr with the thrown exception and prints some
564 debugging information. Called from asm_vm_call_method.
566 *******************************************************************************/
568 void *builtin_throw_exception(java_objectheader *xptr)
571 java_lang_Throwable *t;
577 t = (java_lang_Throwable *) xptr;
579 /* calculate message length */
581 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
585 utf_bytes(xptr->vftbl->class->name);
586 if (t->detailMessage) {
587 logtextlen += strlen(": ") +
588 u2_utflength(t->detailMessage->value->data
589 + t->detailMessage->offset,
590 t->detailMessage->count);
594 logtextlen += strlen("(nil)");
597 /* allocate memory */
599 dumpsize = dump_size();
601 logtext = DMNEW(char, logtextlen);
603 strcpy(logtext, "Builtin exception thrown: ");
606 utf_cat_classname(logtext, xptr->vftbl->class->name);
608 if (t->detailMessage) {
611 buf = javastring_tochar((java_objectheader *) t->detailMessage);
612 strcat(logtext, ": ");
613 strcat(logtext, buf);
614 MFREE(buf, char, strlen(buf) + 1);
618 strcat(logtext, "(nil)");
625 dump_release(dumpsize);
627 #endif /* !defined(NDEBUG) */
629 /* actually set the exception */
631 *exceptionptr = xptr;
633 /* Return a NULL pointer. This is required for vm_call_method to
634 check for an exception. This is for convenience. */
640 /* builtin_canstore ************************************************************
642 Checks, if an object can be stored in an array.
644 Return value: 1 ... possible
647 *******************************************************************************/
649 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
651 arraydescriptor *desc;
652 arraydescriptor *valuedesc;
653 vftbl_t *componentvftbl;
656 castinfo classvalues;
661 /* The following is guaranteed (by verifier checks):
663 * *) oa->...vftbl->arraydesc != NULL
664 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
665 * *) o->vftbl is not an interface vftbl
668 desc = oa->header.objheader.vftbl->arraydesc;
669 componentvftbl = desc->componentvftbl;
670 valuevftbl = o->vftbl;
672 if ((desc->dimension - 1) == 0) {
675 /* {oa is a one-dimensional array} */
676 /* {oa is an array of references} */
678 if (valuevftbl == componentvftbl)
681 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
683 if ((base = classvalues.super_baseval) <= 0)
684 /* an array of interface references */
685 return (valuevftbl->interfacetablelength > -base &&
686 valuevftbl->interfacetable[base] != NULL);
688 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
689 <= (unsigned) classvalues.super_diffval);
694 /* {oa has dimension > 1} */
695 /* {componentvftbl->arraydesc != NULL} */
697 /* check if o is an array */
699 if ((valuedesc = valuevftbl->arraydesc) == NULL)
702 /* {o is an array} */
704 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
708 /* This is an optimized version where a is guaranteed to be one-dimensional */
709 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
711 arraydescriptor *desc;
712 vftbl_t *elementvftbl;
716 castinfo classvalues;
720 /* The following is guaranteed (by verifier checks):
722 * *) a->...vftbl->arraydesc != NULL
723 * *) a->...vftbl->arraydesc->elementvftbl != NULL
724 * *) a->...vftbl->arraydesc->dimension == 1
725 * *) o->vftbl is not an interface vftbl
728 desc = a->header.objheader.vftbl->arraydesc;
729 elementvftbl = desc->elementvftbl;
730 valuevftbl = o->vftbl;
732 /* {a is a one-dimensional array} */
734 if (valuevftbl == elementvftbl)
737 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
739 if ((base = classvalues.super_baseval) <= 0)
740 /* an array of interface references */
741 return (valuevftbl->interfacetablelength > -base &&
742 valuevftbl->interfacetable[base] != NULL);
744 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
745 <= (unsigned) classvalues.super_diffval;
751 /* This is an optimized version where a is guaranteed to be a
752 * one-dimensional array of a class type */
753 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
755 vftbl_t *elementvftbl;
758 castinfo classvalues;
762 /* The following is guaranteed (by verifier checks):
764 * *) a->...vftbl->arraydesc != NULL
765 * *) a->...vftbl->arraydesc->elementvftbl != NULL
766 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
767 * *) a->...vftbl->arraydesc->dimension == 1
768 * *) o->vftbl is not an interface vftbl
771 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
772 valuevftbl = o->vftbl;
774 /* {a is a one-dimensional array} */
776 if (valuevftbl == elementvftbl)
779 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
781 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
782 <= (unsigned) classvalues.super_diffval;
788 /* builtin_new *****************************************************************
790 Creates a new instance of class c on the heap.
792 Return value: pointer to the object or NULL if no memory is
795 *******************************************************************************/
797 java_objectheader *builtin_new(classinfo *c)
799 java_objectheader *o;
800 #if defined(ENABLE_RT_TIMING)
801 struct timespec time_start, time_end;
803 #if defined(ENABLE_CYCLES_STATS)
804 u8 cycles_start, cycles_end;
807 RT_TIMING_GET_TIME(time_start);
808 CYCLES_STATS_GET(cycles_start);
810 /* is the class loaded */
812 assert(c->state & CLASS_LOADED);
814 /* check if we can instantiate this class */
816 if (c->flags & ACC_ABSTRACT) {
818 new_exception_utfmessage(string_java_lang_InstantiationError,
823 /* is the class linked */
825 if (!(c->state & CLASS_LINKED))
829 if (!(c->state & CLASS_INITIALIZED)) {
832 log_message_class("Initialize class (from builtin_new): ", c);
835 if (!initialize_class(c))
839 o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
847 #if defined(ENABLE_THREADS)
848 lock_init_object_lock(o);
851 CYCLES_STATS_GET(cycles_end);
852 RT_TIMING_GET_TIME(time_end);
854 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
855 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
861 /* builtin_newarray ************************************************************
863 Creates an array with the given vftbl on the heap. This function
864 takes as class argument an array class.
866 Return value: pointer to the array or NULL if no memory is available
868 *******************************************************************************/
870 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
872 arraydescriptor *desc;
877 #if defined(ENABLE_RT_TIMING)
878 struct timespec time_start, time_end;
881 RT_TIMING_GET_TIME(time_start);
883 desc = arrayclass->vftbl->arraydesc;
884 dataoffset = desc->dataoffset;
885 componentsize = desc->componentsize;
888 exceptions_throw_negativearraysizeexception();
892 actualsize = dataoffset + size * componentsize;
894 if (((u4) actualsize) < ((u4) size)) { /* overflow */
895 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
899 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
904 a->objheader.vftbl = arrayclass->vftbl;
906 #if defined(ENABLE_THREADS)
907 lock_init_object_lock(&a->objheader);
912 RT_TIMING_GET_TIME(time_end);
913 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
919 /* builtin_anewarray ***********************************************************
921 Creates an array of references to the given class type on the heap.
923 Return value: pointer to the array or NULL if no memory is
926 *******************************************************************************/
928 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
930 classinfo *arrayclass;
932 /* is class loaded */
934 assert(componentclass->state & CLASS_LOADED);
936 /* is class linked */
938 if (!(componentclass->state & CLASS_LINKED))
939 if (!link_class(componentclass))
942 arrayclass = class_array_of(componentclass, true);
947 return (java_objectarray *) builtin_newarray(size, arrayclass);
951 /* builtin_newarray_boolean ****************************************************
953 Creates an array of bytes on the heap. The array is designated as
954 an array of booleans (important for casts)
956 Return value: pointer to the array or NULL if no memory is
959 *******************************************************************************/
961 java_booleanarray *builtin_newarray_boolean(s4 size)
963 return (java_booleanarray *)
964 builtin_newarray(size,
965 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
969 /* builtin_newarray_byte *******************************************************
971 Creates an array of 8 bit Integers on the heap.
973 Return value: pointer to the array or NULL if no memory is
976 *******************************************************************************/
978 java_bytearray *builtin_newarray_byte(s4 size)
980 return (java_bytearray *)
981 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
985 /* builtin_newarray_char *******************************************************
987 Creates an array of characters on the heap.
989 Return value: pointer to the array or NULL if no memory is
992 *******************************************************************************/
994 java_chararray *builtin_newarray_char(s4 size)
996 return (java_chararray *)
997 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
1001 /* builtin_newarray_short ******************************************************
1003 Creates an array of 16 bit Integers on the heap.
1005 Return value: pointer to the array or NULL if no memory is
1008 *******************************************************************************/
1010 java_shortarray *builtin_newarray_short(s4 size)
1012 return (java_shortarray *)
1013 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
1017 /* builtin_newarray_int ********************************************************
1019 Creates an array of 32 bit Integers on the heap.
1021 Return value: pointer to the array or NULL if no memory is
1024 *******************************************************************************/
1026 java_intarray *builtin_newarray_int(s4 size)
1028 return (java_intarray *)
1029 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
1033 /* builtin_newarray_long *******************************************************
1035 Creates an array of 64 bit Integers on the heap.
1037 Return value: pointer to the array or NULL if no memory is
1040 *******************************************************************************/
1042 java_longarray *builtin_newarray_long(s4 size)
1044 return (java_longarray *)
1045 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
1049 /* builtin_newarray_float ******************************************************
1051 Creates an array of 32 bit IEEE floats on the heap.
1053 Return value: pointer to the array or NULL if no memory is
1056 *******************************************************************************/
1058 java_floatarray *builtin_newarray_float(s4 size)
1060 return (java_floatarray *)
1061 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1065 /* builtin_newarray_double *****************************************************
1067 Creates an array of 64 bit IEEE floats on the heap.
1069 Return value: pointer to the array or NULL if no memory is
1072 *******************************************************************************/
1074 java_doublearray *builtin_newarray_double(s4 size)
1076 return (java_doublearray *)
1077 builtin_newarray(size,
1078 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1082 /* builtin_multianewarray_intern ***********************************************
1084 Creates a multi-dimensional array on the heap. The dimensions are
1085 passed in an array of longs.
1088 n............number of dimensions to create
1089 arrayvftbl...vftbl of the array class
1090 dims.........array containing the size of each dimension to create
1092 Return value: pointer to the array or NULL if no memory is
1095 ******************************************************************************/
1097 static java_arrayheader *builtin_multianewarray_intern(int n,
1098 classinfo *arrayclass,
1102 java_arrayheader *a;
1103 classinfo *componentclass;
1106 /* create this dimension */
1108 size = (s4) dims[0];
1109 a = builtin_newarray(size, arrayclass);
1114 /* if this is the last dimension return */
1119 /* get the class of the components to create */
1121 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1123 /* The verifier guarantees that the dimension count is in the range. */
1125 /* create the component arrays */
1127 for (i = 0; i < size; i++) {
1128 java_arrayheader *ea =
1129 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1130 /* we save an s4 to a s8 slot, 8-byte aligned */
1132 builtin_multianewarray_intern(n, componentclass, dims + 2);
1134 builtin_multianewarray_intern(n, componentclass, dims + 1);
1140 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1147 /* builtin_multianewarray ******************************************************
1149 Wrapper for builtin_multianewarray_intern which checks all
1150 dimensions before we start allocating.
1152 ******************************************************************************/
1154 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1160 /* check all dimensions before doing anything */
1162 for (i = 0; i < n; i++) {
1163 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1164 /* we save an s4 to a s8 slot, 8-byte aligned */
1165 size = (s4) dims[i * 2];
1167 size = (s4) dims[i];
1171 exceptions_throw_negativearraysizeexception();
1176 /* now call the real function */
1178 return builtin_multianewarray_intern(n, arrayclass, dims);
1182 /*****************************************************************************
1185 Various functions for printing a message at method entry or exit (for
1188 *****************************************************************************/
1190 #if !defined(NDEBUG)
1191 static s4 methodindent = 0;
1192 static u4 callcount = 0;
1194 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1204 if (opt_verbosecall && indent)
1207 /* calculate message length */
1211 strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1214 logtextlen = strlen("Some Throwable");
1217 logtextlen += strlen(" thrown in ");
1221 utf_bytes(m->class->name) +
1223 utf_bytes(m->name) +
1224 utf_bytes(m->descriptor) +
1225 strlen("(NOSYNC,NATIVE");
1227 #if SIZEOF_VOID_P == 8
1229 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1231 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1234 if (m->class->sourcefile == NULL)
1235 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1237 logtextlen += utf_bytes(m->class->sourcefile);
1239 logtextlen += strlen(":65536)");
1243 logtextlen += strlen("call_java_method");
1246 logtextlen += strlen("0");
1248 /* allocate memory */
1250 dumpsize = dump_size();
1252 logtext = DMNEW(char, logtextlen);
1255 strcpy(logtext, "Exception ");
1256 utf_cat_classname(logtext, xptr->vftbl->class->name);
1259 strcpy(logtext, "Some Throwable");
1262 strcat(logtext, " thrown in ");
1265 utf_cat_classname(logtext, m->class->name);
1266 strcat(logtext, ".");
1267 utf_cat(logtext, m->name);
1268 utf_cat(logtext, m->descriptor);
1270 if (m->flags & ACC_SYNCHRONIZED)
1271 strcat(logtext, "(SYNC");
1273 strcat(logtext, "(NOSYNC");
1275 if (m->flags & ACC_NATIVE) {
1276 strcat(logtext, ",NATIVE");
1280 #if SIZEOF_VOID_P == 8
1281 sprintf(logtext + strlen(logtext),
1282 ")(0x%016lx) at position 0x%016lx",
1283 (ptrint) code->entrypoint, (ptrint) pos);
1285 sprintf(logtext + strlen(logtext),
1286 ")(0x%08x) at position 0x%08x",
1287 (ptrint) code->entrypoint, (ptrint) pos);
1292 /* XXX preliminary: This should get the actual codeinfo */
1293 /* in which the exception happened. */
1296 #if SIZEOF_VOID_P == 8
1297 sprintf(logtext + strlen(logtext),
1298 ")(0x%016lx) at position 0x%016lx (",
1299 (ptrint) code->entrypoint, (ptrint) pos);
1301 sprintf(logtext + strlen(logtext),
1302 ")(0x%08x) at position 0x%08x (",
1303 (ptrint) code->entrypoint, (ptrint) pos);
1306 if (m->class->sourcefile == NULL)
1307 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1309 utf_cat(logtext, m->class->sourcefile);
1311 sprintf(logtext + strlen(logtext), ":%d)", 0);
1315 strcat(logtext, "call_java_method");
1319 /* release memory */
1321 dump_release(dumpsize);
1325 #endif /* !defined(NDEBUG) */
1328 /* builtin_print_argument ******************************************************
1330 Prints arguments and return values for the call trace.
1332 *******************************************************************************/
1334 #if !defined(NDEBUG)
1335 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1336 typedesc *paramtype, s8 value)
1339 java_objectheader *o;
1340 java_lang_String *s;
1345 switch (paramtype->type) {
1348 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1353 #if SIZEOF_VOID_P == 4
1354 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1356 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1362 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1367 #if SIZEOF_VOID_P == 4
1368 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1370 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1375 #if SIZEOF_VOID_P == 4
1376 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1378 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1381 /* cast to java.lang.Object */
1383 o = (java_objectheader *) (ptrint) value;
1385 /* check return argument for java.lang.Class or java.lang.String */
1388 if (o->vftbl->class == class_java_lang_String) {
1389 /* get java.lang.String object and the length of the
1392 s = (java_lang_String *) o;
1394 u = javastring_toutf(s, false);
1396 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1398 /* realloc memory for string length */
1400 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1403 /* convert to utf8 string and strcat it to the logtext */
1405 strcat(logtext, " (String = \"");
1406 utf_cat(logtext, u);
1407 strcat(logtext, "\")");
1410 if (o->vftbl->class == class_java_lang_Class) {
1411 /* if the object returned is a java.lang.Class
1412 cast it to classinfo structure and get the name
1415 c = (classinfo *) o;
1420 /* if the object returned is not a java.lang.String or
1421 a java.lang.Class just print the name of the class */
1423 u = o->vftbl->class->name;
1426 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1428 /* realloc memory for string length */
1430 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1433 /* strcat to the logtext */
1435 strcat(logtext, " (Class = \"");
1436 utf_cat_classname(logtext, u);
1437 strcat(logtext, "\")");
1444 #endif /* !defined(NDEBUG) */
1447 /* builtin_trace_args **********************************************************
1449 Print method call with arguments for -verbose:call.
1451 *******************************************************************************/
1453 #if !defined(NDEBUG)
1455 #ifdef TRACE_ARGS_NUM
1456 void builtin_trace_args(s8 a0, s8 a1,
1457 #if TRACE_ARGS_NUM >= 4
1459 #endif /* TRACE_ARGS_NUM >= 4 */
1460 #if TRACE_ARGS_NUM >= 6
1462 #endif /* TRACE_ARGS_NUM >= 6 */
1463 #if TRACE_ARGS_NUM == 8
1465 #endif /* TRACE_ARGS_NUM == 8 */
1477 /* calculate message length */
1480 strlen("4294967295 ") +
1481 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1483 strlen("called: ") +
1484 utf_bytes(m->class->name) +
1486 utf_bytes(m->name) +
1487 utf_bytes(m->descriptor) +
1488 strlen("(") + strlen(")");
1490 /* Actually it's not possible to have all flags printed, but:
1495 strlen(" PRIVATE") +
1496 strlen(" PROTECTED") +
1499 strlen(" SYNCHRONIZED") +
1500 strlen(" VOLATILE") +
1501 strlen(" TRANSIENT") +
1503 strlen(" INTERFACE") +
1504 strlen(" ABSTRACT");
1506 /* add maximal argument length */
1509 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1512 /* allocate memory */
1514 dumpsize = dump_size();
1516 logtext = DMNEW(char, logtextlen);
1520 sprintf(logtext, "%10d ", callcount);
1521 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1523 pos = strlen(logtext);
1525 for (i = 0; i < methodindent; i++)
1526 logtext[pos++] = '\t';
1528 strcpy(logtext + pos, "called: ");
1530 utf_cat_classname(logtext, m->class->name);
1531 strcat(logtext, ".");
1532 utf_cat(logtext, m->name);
1533 utf_cat(logtext, m->descriptor);
1535 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1536 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1537 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1538 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1539 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1540 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1541 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1542 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1543 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1544 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1545 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1547 strcat(logtext, "(");
1549 if (md->paramcount >= 1) {
1550 logtext = builtin_print_argument(logtext, &logtextlen,
1551 &md->paramtypes[0], a0);
1554 if (md->paramcount >= 2) {
1555 strcat(logtext, ", ");
1557 logtext = builtin_print_argument(logtext, &logtextlen,
1558 &md->paramtypes[1], a1);
1561 #if TRACE_ARGS_NUM >= 4
1562 if (md->paramcount >= 3) {
1563 strcat(logtext, ", ");
1565 logtext = builtin_print_argument(logtext, &logtextlen,
1566 &md->paramtypes[2], a2);
1569 if (md->paramcount >= 4) {
1570 strcat(logtext, ", ");
1572 logtext = builtin_print_argument(logtext, &logtextlen,
1573 &md->paramtypes[3], a3);
1577 #if TRACE_ARGS_NUM >= 6
1578 if (md->paramcount >= 5) {
1579 strcat(logtext, ", ");
1581 logtext = builtin_print_argument(logtext, &logtextlen,
1582 &md->paramtypes[4], a4);
1585 if (md->paramcount >= 6) {
1586 strcat(logtext, ", ");
1588 logtext = builtin_print_argument(logtext, &logtextlen,
1589 &md->paramtypes[5], a5);
1593 #if TRACE_ARGS_NUM == 8
1594 if (md->paramcount >= 7) {
1595 strcat(logtext, ", ");
1597 logtext = builtin_print_argument(logtext, &logtextlen,
1598 &md->paramtypes[6], a6);
1601 if (md->paramcount >= 8) {
1602 strcat(logtext, ", ");
1604 logtext = builtin_print_argument(logtext, &logtextlen,
1605 &md->paramtypes[7], a7);
1609 if (md->paramcount > 8) {
1610 sprintf(logtext + strlen(logtext), ", ...(%d)",
1611 md->paramcount - TRACE_ARGS_NUM);
1614 strcat(logtext, ")");
1618 /* release memory */
1620 dump_release(dumpsize);
1625 #endif /* !defined(NDEBUG) */
1628 /* builtin_displaymethodstop ***************************************************
1630 Print method exit for -verbose:call.
1632 *******************************************************************************/
1634 #if !defined(NDEBUG)
1635 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1647 /* calculate message length */
1650 strlen("4294967295 ") +
1651 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1653 strlen("finished: ") +
1654 utf_bytes(m->class->name) +
1656 utf_bytes(m->name) +
1657 utf_bytes(m->descriptor) +
1658 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1660 /* add maximal argument length */
1662 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1664 /* allocate memory */
1666 dumpsize = dump_size();
1668 logtext = DMNEW(char, logtextlen);
1670 /* outdent the log message */
1675 log_text("WARNING: unmatched methodindent--");
1677 /* generate the message */
1679 sprintf(logtext, " ");
1680 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1682 pos = strlen(logtext);
1684 for (i = 0; i < methodindent; i++)
1685 logtext[pos++] = '\t';
1687 strcpy(logtext + pos, "finished: ");
1688 utf_cat_classname(logtext, m->class->name);
1689 strcat(logtext, ".");
1690 utf_cat(logtext, m->name);
1691 utf_cat(logtext, m->descriptor);
1693 if (!IS_VOID_TYPE(md->returntype.type)) {
1694 strcat(logtext, "->");
1696 switch (md->returntype.type) {
1713 builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1718 /* release memory */
1720 dump_release(dumpsize);
1722 #endif /* !defined(NDEBUG) */
1725 #if defined(ENABLE_CYCLES_STATS)
1726 void builtin_print_cycles_stats(FILE *file)
1728 fprintf(file,"builtin cylce count statistics:\n");
1730 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1731 CYCLES_STATS_PRINT(builtin_new ,file);
1735 #endif /* defined(ENABLE_CYCLES_STATS) */
1738 /*****************************************************************************
1739 MISCELLANEOUS HELPER FUNCTIONS
1740 *****************************************************************************/
1744 /*********** Functions for integer divisions *****************************
1746 On some systems (eg. DEC ALPHA), integer division is not supported by the
1747 CPU. These helper functions implement the missing functionality.
1749 ******************************************************************************/
1751 #if !SUPPORT_DIVISION
1752 s4 builtin_idiv(s4 a, s4 b)
1761 s4 builtin_irem(s4 a, s4 b)
1769 #endif /* !SUPPORT_DIVISION */
1772 /* functions for long arithmetics **********************************************
1774 On systems where 64 bit Integers are not supported by the CPU,
1775 these functions are needed.
1777 ******************************************************************************/
1779 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1780 s8 builtin_ladd(s8 a, s8 b)
1793 s8 builtin_lsub(s8 a, s8 b)
1806 s8 builtin_lneg(s8 a)
1818 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1821 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1822 s8 builtin_lmul(s8 a, s8 b)
1834 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1837 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1838 s8 builtin_ldiv(s8 a, s8 b)
1851 s8 builtin_lrem(s8 a, s8 b)
1863 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1866 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1867 s8 builtin_lshl(s8 a, s4 b)
1880 s8 builtin_lshr(s8 a, s4 b)
1893 s8 builtin_lushr(s8 a, s4 b)
1898 c = ((u8) a) >> (b & 63);
1905 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1908 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1909 s8 builtin_land(s8 a, s8 b)
1922 s8 builtin_lor(s8 a, s8 b)
1935 s8 builtin_lxor(s8 a, s8 b)
1947 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1950 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1951 s4 builtin_lcmp(s8 a, s8 b)
1965 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1968 /* functions for unsupported floating instructions ****************************/
1970 /* used to convert FLT_xxx defines into float values */
1972 static inline float intBitsToFloat(s4 i)
1981 /* used to convert DBL_xxx defines into double values */
1983 static inline float longBitsToDouble(s8 l)
1993 float builtin_fadd(float a, float b)
1995 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1996 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2007 if (copysignf(1.0, a) == copysignf(1.0, b))
2010 return intBitsToFloat(FLT_NAN);
2016 float builtin_fsub(float a, float b)
2018 return builtin_fadd(a, builtin_fneg(b));
2022 float builtin_fmul(float a, float b)
2024 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2025 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2027 if (finitef(b)) return a * b;
2029 if (a == 0) return intBitsToFloat(FLT_NAN);
2030 else return copysignf(b, copysignf(1.0, b)*a);
2035 if (b == 0) return intBitsToFloat(FLT_NAN);
2036 else return copysignf(a, copysignf(1.0, a)*b);
2039 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2045 /* builtin_ddiv ****************************************************************
2047 Implementation as described in VM Spec.
2049 *******************************************************************************/
2051 float builtin_fdiv(float a, float b)
2055 /* If neither value1' nor value2' is NaN, the sign of the result */
2056 /* is positive if both values have the same sign, negative if the */
2057 /* values have different signs. */
2063 /* If either value1' or value2' is NaN, the result is NaN. */
2065 return intBitsToFloat(FLT_NAN);
2068 /* Division of a finite value by an infinity results in a */
2069 /* signed zero, with the sign-producing rule just given. */
2071 /* is sign equal? */
2073 if (copysignf(1.0, a) == copysignf(1.0, b))
2082 /* If either value1' or value2' is NaN, the result is NaN. */
2084 return intBitsToFloat(FLT_NAN);
2086 } else if (finitef(b)) {
2087 /* Division of an infinity by a finite value results in a signed */
2088 /* infinity, with the sign-producing rule just given. */
2090 /* is sign equal? */
2092 if (copysignf(1.0, a) == copysignf(1.0, b))
2093 return intBitsToFloat(FLT_POSINF);
2095 return intBitsToFloat(FLT_NEGINF);
2098 /* Division of an infinity by an infinity results in NaN. */
2100 return intBitsToFloat(FLT_NAN);
2106 float builtin_fneg(float a)
2108 if (isnanf(a)) return a;
2110 if (finitef(a)) return -a;
2111 else return copysignf(a, -copysignf(1.0, a));
2114 #endif /* !SUPPORT_FLOAT */
2117 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2118 s4 builtin_fcmpl(float a, float b)
2120 if (isnanf(a)) return -1;
2121 if (isnanf(b)) return -1;
2122 if (!finitef(a) || !finitef(b)) {
2123 a = finitef(a) ? 0 : copysignf(1.0, a);
2124 b = finitef(b) ? 0 : copysignf(1.0, b);
2126 if (a > b) return 1;
2127 if (a == b) return 0;
2132 s4 builtin_fcmpg(float a, float b)
2134 if (isnanf(a)) return 1;
2135 if (isnanf(b)) return 1;
2136 if (!finitef(a) || !finitef(b)) {
2137 a = finitef(a) ? 0 : copysignf(1.0, a);
2138 b = finitef(b) ? 0 : copysignf(1.0, b);
2140 if (a > b) return 1;
2141 if (a == b) return 0;
2144 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2147 float builtin_frem(float a, float b)
2153 /* functions for unsupported double instructions ******************************/
2156 double builtin_dadd(double a, double b)
2158 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2159 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2161 if (finite(b)) return a + b;
2165 if (finite(b)) return a;
2167 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2168 else return longBitsToDouble(DBL_NAN);
2174 double builtin_dsub(double a, double b)
2176 return builtin_dadd(a, builtin_dneg(b));
2180 double builtin_dmul(double a, double b)
2182 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2183 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2185 if (finite(b)) return a * b;
2187 if (a == 0) return longBitsToDouble(DBL_NAN);
2188 else return copysign(b, copysign(1.0, b) * a);
2193 if (b == 0) return longBitsToDouble(DBL_NAN);
2194 else return copysign(a, copysign(1.0, a) * b);
2197 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2203 /* builtin_ddiv ****************************************************************
2205 Implementation as described in VM Spec.
2207 *******************************************************************************/
2209 double builtin_ddiv(double a, double b)
2213 /* If neither value1' nor value2' is NaN, the sign of the result */
2214 /* is positive if both values have the same sign, negative if the */
2215 /* values have different signs. */
2221 /* If either value1' or value2' is NaN, the result is NaN. */
2223 return longBitsToDouble(DBL_NAN);
2226 /* Division of a finite value by an infinity results in a */
2227 /* signed zero, with the sign-producing rule just given. */
2229 /* is sign equal? */
2231 if (copysign(1.0, a) == copysign(1.0, b))
2240 /* If either value1' or value2' is NaN, the result is NaN. */
2242 return longBitsToDouble(DBL_NAN);
2244 } else if (finite(b)) {
2245 /* Division of an infinity by a finite value results in a signed */
2246 /* infinity, with the sign-producing rule just given. */
2248 /* is sign equal? */
2250 if (copysign(1.0, a) == copysign(1.0, b))
2251 return longBitsToDouble(DBL_POSINF);
2253 return longBitsToDouble(DBL_NEGINF);
2256 /* Division of an infinity by an infinity results in NaN. */
2258 return longBitsToDouble(DBL_NAN);
2264 /* builtin_dneg ****************************************************************
2266 Implemented as described in VM Spec.
2268 *******************************************************************************/
2270 double builtin_dneg(double a)
2273 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2280 /* If the operand is a zero, the result is the zero of opposite */
2286 /* If the operand is an infinity, the result is the infinity of */
2287 /* opposite sign. */
2289 return copysign(a, -copysign(1.0, a));
2293 #endif /* !SUPPORT_DOUBLE */
2296 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2297 s4 builtin_dcmpl(double a, double b)
2299 if (isnan(a)) return -1;
2300 if (isnan(b)) return -1;
2301 if (!finite(a) || !finite(b)) {
2302 a = finite(a) ? 0 : copysign(1.0, a);
2303 b = finite(b) ? 0 : copysign(1.0, b);
2305 if (a > b) return 1;
2306 if (a == b) return 0;
2311 s4 builtin_dcmpg(double a, double b)
2313 if (isnan(a)) return 1;
2314 if (isnan(b)) return 1;
2315 if (!finite(a) || !finite(b)) {
2316 a = finite(a) ? 0 : copysign(1.0, a);
2317 b = finite(b) ? 0 : copysign(1.0, b);
2319 if (a > b) return 1;
2320 if (a == b) return 0;
2323 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2326 double builtin_drem(double a, double b)
2332 /* conversion operations ******************************************************/
2335 s8 builtin_i2l(s4 i)
2347 s4 builtin_l2i(s8 l)
2358 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2359 float builtin_i2f(s4 a)
2361 float f = (float) a;
2364 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2367 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2368 double builtin_i2d(s4 a)
2370 double d = (double) a;
2373 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2376 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2377 float builtin_l2f(s8 a)
2380 float f = (float) a;
2386 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2389 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2390 double builtin_l2d(s8 a)
2393 double d = (double) a;
2399 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2402 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2403 s4 builtin_f2i(float a)
2407 i = builtin_d2i((double) a);
2418 if (a < (-2147483648))
2419 return (-2147483648);
2422 f = copysignf((float) 1.0, a);
2425 return (-2147483648); */
2427 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2430 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2431 s8 builtin_f2l(float a)
2435 l = builtin_d2l((double) a);
2442 if (a > 9223372036854775807L)
2443 return 9223372036854775807L;
2444 if (a < (-9223372036854775808L))
2445 return (-9223372036854775808L);
2450 f = copysignf((float) 1.0, a);
2452 return 9223372036854775807L;
2453 return (-9223372036854775808L); */
2455 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2458 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2459 s4 builtin_d2i(double a)
2464 if (a >= 2147483647)
2466 if (a <= (-2147483647-1))
2467 return (-2147483647-1);
2472 d = copysign(1.0, a);
2475 return (-2147483647-1);
2477 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2480 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2481 s8 builtin_d2l(double a)
2486 if (a >= 9223372036854775807LL)
2487 return 9223372036854775807LL;
2488 if (a <= (-9223372036854775807LL-1))
2489 return (-9223372036854775807LL-1);
2494 d = copysign(1.0, a);
2496 return 9223372036854775807LL;
2497 return (-9223372036854775807LL-1);
2499 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2502 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2503 double builtin_f2d(float a)
2505 if (finitef(a)) return (double) a;
2508 return longBitsToDouble(DBL_NAN);
2510 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2514 float builtin_d2f(double a)
2520 return intBitsToFloat(FLT_NAN);
2522 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2525 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2528 /* builtin_arraycopy ***********************************************************
2530 Builtin for java.lang.System.arraycopy.
2532 ATTENTION: This builtin function returns a boolean value to signal
2533 the ICMD_BUILTIN if there was an exception.
2535 *******************************************************************************/
2537 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2538 java_arrayheader *dest, s4 destStart, s4 len)
2540 arraydescriptor *sdesc;
2541 arraydescriptor *ddesc;
2544 if ((src == NULL) || (dest == NULL)) {
2545 exceptions_throw_nullpointerexception();
2549 sdesc = src->objheader.vftbl->arraydesc;
2550 ddesc = dest->objheader.vftbl->arraydesc;
2552 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2553 exceptions_throw_arraystoreexception();
2557 /* we try to throw exception with the same message as SUN does */
2559 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2560 (srcStart + len < 0) || (srcStart + len > src->size) ||
2561 (destStart + len < 0) || (destStart + len > dest->size)) {
2562 exceptions_throw_arrayindexoutofboundsexception();
2566 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2567 /* We copy primitive values or references of exactly the same type */
2569 s4 dataoffset = sdesc->dataoffset;
2570 s4 componentsize = sdesc->componentsize;
2572 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2573 ((u1 *) src) + dataoffset + componentsize * srcStart,
2574 (size_t) len * componentsize);
2577 /* We copy references of different type */
2579 java_objectarray *oas = (java_objectarray *) src;
2580 java_objectarray *oad = (java_objectarray *) dest;
2582 if (destStart <= srcStart) {
2583 for (i = 0; i < len; i++) {
2584 java_objectheader *o = oas->data[srcStart + i];
2586 if (!builtin_canstore(oad, o)) {
2587 exceptions_throw_arraystoreexception();
2591 oad->data[destStart + i] = o;
2595 /* XXX this does not completely obey the specification!
2596 If an exception is thrown only the elements above the
2597 current index have been copied. The specification
2598 requires that only the elements *below* the current
2599 index have been copied before the throw. */
2601 for (i = len - 1; i >= 0; i--) {
2602 java_objectheader *o = oas->data[srcStart + i];
2604 if (!builtin_canstore(oad, o)) {
2605 exceptions_throw_arraystoreexception();
2609 oad->data[destStart + i] = o;
2618 /* builtin_currenttimemillis ***************************************************
2620 Return the current time in milliseconds.
2622 *******************************************************************************/
2624 s8 builtin_currenttimemillis(void)
2629 if (gettimeofday(&tv, NULL) == -1)
2630 vm_abort("gettimeofday failed: %s", strerror(errno));
2632 result = (s8) tv.tv_sec;
2634 result += (tv.tv_usec / 1000);
2640 /* builtin_clone_array *********************************************************
2642 Wrapper function for cloning arrays.
2644 *******************************************************************************/
2646 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2648 java_arrayheader *ah;
2649 java_lang_Cloneable *c;
2651 c = (java_lang_Cloneable *) o;
2653 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2660 * These are local overrides for various environment variables in Emacs.
2661 * Please do not remove this and leave it at the end of the file, where
2662 * Emacs will automagically detect them.
2663 * ---------------------------------------------------------------------
2666 * indent-tabs-mode: t
2670 * vim:noexpandtab:sw=4:ts=4: