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 4598 2006-03-14 22:16:47Z edwin $
57 #include "fdlibm/fdlibm.h"
60 #include "mm/memory.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Cloneable.h"
63 #include "native/include/java_lang_Object.h" /* required by VMObject */
64 #include "native/include/java_lang_VMObject.h"
66 #if defined(USE_THREADS)
67 # if defined(NATIVE_THREADS)
68 # include "threads/native/threads.h"
70 # include "threads/green/threads.h"
71 # include "threads/green/locks.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"
89 /* include builtin tables *****************************************************/
91 #include "vm/builtintable.inc"
94 /* builtintable_init ***********************************************************
96 Parse the descriptors of builtin functions and create the parsed
99 *******************************************************************************/
101 static bool builtintable_init(void)
103 descriptor_pool *descpool;
107 s4 entries_automatic;
110 /* mark start of dump memory area */
112 dumpsize = dump_size();
114 /* create a new descriptor pool */
116 descpool = descriptor_pool_new(class_java_lang_Object);
118 /* add some entries we need */
120 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126 /* calculate table entries statically */
129 sizeof(builtintable_internal) / sizeof(builtintable_entry);
132 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
133 - 1; /* last filler entry (comment see builtintable.inc) */
135 /* first add all descriptors to the pool */
137 for (i = 0; i < entries_internal; i++) {
138 /* create a utf8 string from descriptor */
140 descriptor = utf_new_char(builtintable_internal[i].descriptor);
142 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
143 /* release dump area */
145 dump_release(dumpsize);
151 for (i = 0; i < entries_automatic; i++) {
152 /* create a utf8 string from descriptor */
154 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
156 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
157 /* release dump area */
159 dump_release(dumpsize);
165 /* create the class reference table */
167 (void) descriptor_pool_create_classrefs(descpool, NULL);
169 /* allocate space for the parsed descriptors */
171 descriptor_pool_alloc_parsed_descriptors(descpool);
173 /* now parse all descriptors */
175 for (i = 0; i < entries_internal; i++) {
176 /* create a utf8 string from descriptor */
178 descriptor = utf_new_char(builtintable_internal[i].descriptor);
180 /* parse the descriptor, builtin is always static (no `this' pointer) */
182 builtintable_internal[i].md =
183 descriptor_pool_parse_method_descriptor(descpool, descriptor,
187 for (i = 0; i < entries_automatic; i++) {
188 /* create a utf8 string from descriptor */
190 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
192 /* parse the descriptor, builtin is always static (no `this' pointer) */
194 builtintable_automatic[i].md =
195 descriptor_pool_parse_method_descriptor(descpool, descriptor,
199 /* release dump area */
201 dump_release(dumpsize);
207 /* builtintable_comparator *****************************************************
209 qsort comparator for the automatic builtin table.
211 *******************************************************************************/
213 static int builtintable_comparator(const void *a, const void *b)
215 builtintable_entry *bte1;
216 builtintable_entry *bte2;
218 bte1 = (builtintable_entry *) a;
219 bte2 = (builtintable_entry *) b;
221 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
225 /* builtintable_sort_automatic *************************************************
227 Sorts the automatic builtin table.
229 *******************************************************************************/
231 static void builtintable_sort_automatic(void)
235 /* calculate table size statically (`- 1' comment see builtintable.inc) */
237 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
239 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
240 builtintable_comparator);
244 /* builtin_init ****************************************************************
248 *******************************************************************************/
250 bool builtin_init(void)
252 /* initialize the builtin tables */
254 if (!builtintable_init())
257 /* sort builtin tables */
259 builtintable_sort_automatic();
265 /* builtintable_get_internal ***************************************************
267 Finds an entry in the builtintable for internal functions and
268 returns the a pointer to the structure.
270 *******************************************************************************/
272 builtintable_entry *builtintable_get_internal(functionptr fp)
276 for (i = 0; builtintable_internal[i].fp != NULL; i++) {
277 if (builtintable_internal[i].fp == fp)
278 return &builtintable_internal[i];
285 /* builtintable_get_automatic **************************************************
287 Finds an entry in the builtintable for functions which are replaced
288 automatically and returns the a pointer to the structure.
290 *******************************************************************************/
292 builtintable_entry *builtintable_get_automatic(s4 opcode)
294 builtintable_entry *first;
295 builtintable_entry *last;
296 builtintable_entry *middle;
300 /* calculate table size statically (`- 1' comment see builtintable.inc) */
302 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
304 first = builtintable_automatic;
305 last = builtintable_automatic + entries;
307 while (entries > 0) {
309 middle = first + half;
311 if (middle->opcode < opcode) {
318 return (first != last ? first : NULL);
322 /*****************************************************************************
324 *****************************************************************************/
328 /*************** internal function: builtin_isanysubclass *********************
330 Checks a subclass relation between two classes. Implemented interfaces
331 are interpreted as super classes.
332 Return value: 1 ... sub is subclass of super
335 *****************************************************************************/
336 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
339 castinfo classvalues;
344 if (super->flags & ACC_INTERFACE) {
345 res = (sub->vftbl->interfacetablelength > super->index) &&
346 (sub->vftbl->interfacetable[-super->index] != NULL);
349 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
351 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
352 (u4) classvalues.super_diffval;
359 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
363 castinfo classvalues;
368 ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
370 if ((base = classvalues.super_baseval) <= 0) {
371 /* super is an interface */
372 res = (sub->interfacetablelength > -base) &&
373 (sub->interfacetable[base] != NULL);
375 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
376 <= (u4) classvalues.super_diffval;
383 /****************** function: builtin_instanceof *****************************
385 Checks if an object is an instance of some given class (or subclass of
386 that class). If class is an interface, checks if the interface is
388 Return value: 1 ... obj is an instance of class or implements the interface
389 0 ... otherwise or if obj == NULL
391 *****************************************************************************/
393 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
398 return builtin_isanysubclass(obj->vftbl->class, class);
403 /**************** function: builtin_checkcast *******************************
405 The same as builtin_instanceof except that 1 is returned when
408 ****************************************************************************/
410 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
415 if (builtin_isanysubclass(obj->vftbl->class, class))
422 /* builtin_descriptorscompatible ***********************************************
424 Checks if two array type descriptors are assignment compatible
426 Return value: 1 ... target = desc is possible
429 *******************************************************************************/
431 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
432 arraydescriptor *target)
437 if (desc->arraytype != target->arraytype)
440 if (desc->arraytype != ARRAYTYPE_OBJECT)
443 /* {both arrays are arrays of references} */
445 if (desc->dimension == target->dimension) {
446 /* an array which contains elements of interface types is
447 allowed to be casted to Object (JOWENN)*/
449 if ((desc->elementvftbl->baseval < 0) &&
450 (target->elementvftbl->baseval == 1))
453 return builtin_isanysubclass_vftbl(desc->elementvftbl,
454 target->elementvftbl);
457 if (desc->dimension < target->dimension)
460 /* {desc has higher dimension than target} */
462 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
463 target->elementvftbl);
467 /* builtin_arraycheckcast ******************************************************
469 Checks if an object is really a subtype of the requested array
470 type. The object has to be an array to begin with. For simple
471 arrays (int, short, double, etc.) the types have to match exactly.
472 For arrays of objects, the type of elements in the array has to be
473 a subtype (or the same type) of the requested element type. For
474 arrays of arrays (which in turn can again be arrays of arrays), the
475 types at the lowest level have to satisfy the corresponding sub
478 *******************************************************************************/
480 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
482 arraydescriptor *desc;
487 if ((desc = o->vftbl->arraydesc) == NULL)
490 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
494 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
499 return builtin_arraycheckcast(o, targetclass);
503 /************************** exception functions *******************************
505 ******************************************************************************/
508 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
510 java_lang_Throwable *t;
516 t = (java_lang_Throwable *) xptr;
518 /* calculate message length */
520 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
524 utf_strlen(xptr->vftbl->class->name) +
526 javastring_strlen(t->detailMessage);
529 logtextlen += strlen("(nil)");
531 /* allocate memory */
533 dumpsize = dump_size();
535 logtext = DMNEW(char, logtextlen);
537 strcpy(logtext, "Builtin exception thrown: ");
540 utf_sprint_classname(logtext + strlen(logtext),
541 xptr->vftbl->class->name);
543 if (t->detailMessage) {
546 buf = javastring_tochar((java_objectheader *) t->detailMessage);
547 strcat(logtext, ": ");
548 strcat(logtext, buf);
549 MFREE(buf, char, strlen(buf));
553 strcat(logtext, "(nil)");
560 dump_release(dumpsize);
563 *exceptionptr = xptr;
567 #endif /* !defined(NDEBUG) */
570 /* builtin_canstore ************************************************************
572 Checks, if an object can be stored in an array.
574 Return value: 1 ... possible
577 *******************************************************************************/
579 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
581 arraydescriptor *desc;
582 arraydescriptor *valuedesc;
583 vftbl_t *componentvftbl;
586 castinfo classvalues;
591 /* The following is guaranteed (by verifier checks):
593 * *) oa->...vftbl->arraydesc != NULL
594 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
595 * *) o->vftbl is not an interface vftbl
598 desc = oa->header.objheader.vftbl->arraydesc;
599 componentvftbl = desc->componentvftbl;
600 valuevftbl = o->vftbl;
602 if ((desc->dimension - 1) == 0) {
605 /* {oa is a one-dimensional array} */
606 /* {oa is an array of references} */
608 if (valuevftbl == componentvftbl)
611 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
613 if ((base = classvalues.super_baseval) <= 0)
614 /* an array of interface references */
615 return (valuevftbl->interfacetablelength > -base &&
616 valuevftbl->interfacetable[base] != NULL);
618 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
619 <= (unsigned) classvalues.super_diffval);
624 /* {oa has dimension > 1} */
625 /* {componentvftbl->arraydesc != NULL} */
627 /* check if o is an array */
629 if ((valuedesc = valuevftbl->arraydesc) == NULL)
632 /* {o is an array} */
634 return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
638 /* This is an optimized version where a is guaranteed to be one-dimensional */
639 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
641 arraydescriptor *desc;
642 vftbl_t *elementvftbl;
646 castinfo classvalues;
650 /* The following is guaranteed (by verifier checks):
652 * *) a->...vftbl->arraydesc != NULL
653 * *) a->...vftbl->arraydesc->elementvftbl != NULL
654 * *) a->...vftbl->arraydesc->dimension == 1
655 * *) o->vftbl is not an interface vftbl
658 desc = a->header.objheader.vftbl->arraydesc;
659 elementvftbl = desc->elementvftbl;
660 valuevftbl = o->vftbl;
662 /* {a is a one-dimensional array} */
664 if (valuevftbl == elementvftbl)
667 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
669 if ((base = classvalues.super_baseval) <= 0)
670 /* an array of interface references */
671 return (valuevftbl->interfacetablelength > -base &&
672 valuevftbl->interfacetable[base] != NULL);
674 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
675 <= (unsigned) classvalues.super_diffval;
681 /* This is an optimized version where a is guaranteed to be a
682 * one-dimensional array of a class type */
683 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
685 vftbl_t *elementvftbl;
688 castinfo classvalues;
692 /* The following is guaranteed (by verifier checks):
694 * *) a->...vftbl->arraydesc != NULL
695 * *) a->...vftbl->arraydesc->elementvftbl != NULL
696 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
697 * *) a->...vftbl->arraydesc->dimension == 1
698 * *) o->vftbl is not an interface vftbl
701 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
702 valuevftbl = o->vftbl;
704 /* {a is a one-dimensional array} */
706 if (valuevftbl == elementvftbl)
709 ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
711 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
712 <= (unsigned) classvalues.super_diffval;
718 /* builtin_new *****************************************************************
720 Creates a new instance of class c on the heap.
722 Return value: pointer to the object or NULL if no memory is
725 *******************************************************************************/
727 java_objectheader *builtin_new(classinfo *c)
729 java_objectheader *o;
731 /* is the class loaded */
733 assert(c->state & CLASS_LOADED);
735 /* check if we can instantiate this class */
737 if (c->flags & ACC_ABSTRACT) {
739 new_exception_utfmessage(string_java_lang_InstantiationError,
744 /* is the class linked */
746 if (!(c->state & CLASS_LINKED))
750 if (!(c->state & CLASS_INITIALIZED)) {
752 log_message_class("Initialize class (from builtin_new): ", c);
754 if (!initialize_class(c))
758 o = heap_allocate(c->instancesize, true, c->finalizer);
765 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
773 /* builtin_newarray ************************************************************
775 Creates an array with the given vftbl on the heap. This function
776 takes as class argument an array class.
778 Return value: pointer to the array or NULL if no memory is available
780 *******************************************************************************/
782 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
784 arraydescriptor *desc;
790 desc = arrayclass->vftbl->arraydesc;
791 dataoffset = desc->dataoffset;
792 componentsize = desc->componentsize;
795 exceptions_throw_negativearraysizeexception();
799 actualsize = dataoffset + size * componentsize;
801 if (((u4) actualsize) < ((u4) size)) { /* overflow */
802 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
806 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
811 a->objheader.vftbl = arrayclass->vftbl;
813 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
814 initObjectLock(&a->objheader);
823 /* builtin_anewarray ***********************************************************
825 Creates an array of references to the given class type on the heap.
827 Return value: pointer to the array or NULL if no memory is
830 *******************************************************************************/
832 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
834 classinfo *arrayclass;
836 /* is class loaded */
838 assert(componentclass->state & CLASS_LOADED);
840 /* is class linked */
842 if (!(componentclass->state & CLASS_LINKED))
843 if (!link_class(componentclass))
846 arrayclass = class_array_of(componentclass, true);
851 return (java_objectarray *) builtin_newarray(size, arrayclass);
855 /* builtin_newarray_boolean ****************************************************
857 Creates an array of bytes on the heap. The array is designated as
858 an array of booleans (important for casts)
860 Return value: pointer to the array or NULL if no memory is
863 *******************************************************************************/
865 java_booleanarray *builtin_newarray_boolean(s4 size)
867 return (java_booleanarray *)
868 builtin_newarray(size,
869 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
873 /* builtin_newarray_byte *******************************************************
875 Creates an array of 8 bit Integers on the heap.
877 Return value: pointer to the array or NULL if no memory is
880 *******************************************************************************/
882 java_bytearray *builtin_newarray_byte(s4 size)
884 return (java_bytearray *)
885 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
889 /* builtin_newarray_char *******************************************************
891 Creates an array of characters on the heap.
893 Return value: pointer to the array or NULL if no memory is
896 *******************************************************************************/
898 java_chararray *builtin_newarray_char(s4 size)
900 return (java_chararray *)
901 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
905 /* builtin_newarray_short ******************************************************
907 Creates an array of 16 bit Integers on the heap.
909 Return value: pointer to the array or NULL if no memory is
912 *******************************************************************************/
914 java_shortarray *builtin_newarray_short(s4 size)
916 return (java_shortarray *)
917 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
921 /* builtin_newarray_int ********************************************************
923 Creates an array of 32 bit Integers on the heap.
925 Return value: pointer to the array or NULL if no memory is
928 *******************************************************************************/
930 java_intarray *builtin_newarray_int(s4 size)
932 return (java_intarray *)
933 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
937 /* builtin_newarray_long *******************************************************
939 Creates an array of 64 bit Integers on the heap.
941 Return value: pointer to the array or NULL if no memory is
944 *******************************************************************************/
946 java_longarray *builtin_newarray_long(s4 size)
948 return (java_longarray *)
949 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
953 /* builtin_newarray_float ******************************************************
955 Creates an array of 32 bit IEEE floats on the heap.
957 Return value: pointer to the array or NULL if no memory is
960 *******************************************************************************/
962 java_floatarray *builtin_newarray_float(s4 size)
964 return (java_floatarray *)
965 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
969 /* builtin_newarray_double *****************************************************
971 Creates an array of 64 bit IEEE floats on the heap.
973 Return value: pointer to the array or NULL if no memory is
976 *******************************************************************************/
978 java_doublearray *builtin_newarray_double(s4 size)
980 return (java_doublearray *)
981 builtin_newarray(size,
982 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
986 /* builtin_multianewarray_intern ***********************************************
988 Creates a multi-dimensional array on the heap. The dimensions are
989 passed in an array of longs.
992 n............number of dimensions to create
993 arrayvftbl...vftbl of the array class
994 dims.........array containing the size of each dimension to create
996 Return value: pointer to the array or NULL if no memory is
999 ******************************************************************************/
1001 static java_arrayheader *builtin_multianewarray_intern(int n,
1002 classinfo *arrayclass,
1006 java_arrayheader *a;
1007 classinfo *componentclass;
1010 /* create this dimension */
1012 size = (s4) dims[0];
1013 a = builtin_newarray(size, arrayclass);
1018 /* if this is the last dimension return */
1023 /* get the class of the components to create */
1025 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1027 /* The verifier guarantees that the dimension count is in the range. */
1029 /* create the component arrays */
1031 for (i = 0; i < size; i++) {
1032 java_arrayheader *ea =
1033 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1034 /* we save an s4 to a s8 slot, 8-byte aligned */
1036 builtin_multianewarray_intern(n, componentclass, dims + 2);
1038 builtin_multianewarray_intern(n, componentclass, dims + 1);
1044 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1051 /* builtin_multianewarray ******************************************************
1053 Wrapper for builtin_multianewarray_intern which checks all
1054 dimensions before we start allocating.
1056 ******************************************************************************/
1058 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1064 /* check all dimensions before doing anything */
1066 for (i = 0; i < n; i++) {
1067 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1068 /* we save an s4 to a s8 slot, 8-byte aligned */
1069 size = (s4) dims[i * 2];
1071 size = (s4) dims[i];
1075 exceptions_throw_negativearraysizeexception();
1080 /* now call the real function */
1082 return builtin_multianewarray_intern(n, arrayclass, dims);
1086 /*****************************************************************************
1089 Various functions for printing a message at method entry or exit (for
1092 *****************************************************************************/
1094 #if !defined(NDEBUG)
1095 static s4 methodindent = 0;
1096 static u4 callcount = 0;
1098 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1108 if (opt_verbosecall && indent)
1111 /* calculate message length */
1115 strlen("Exception ") +
1116 utf_strlen(xptr->vftbl->class->name);
1119 logtextlen = strlen("Some Throwable");
1122 logtextlen += strlen(" thrown in ");
1126 utf_strlen(m->class->name) +
1128 utf_strlen(m->name) +
1129 utf_strlen(m->descriptor) +
1130 strlen("(NOSYNC,NATIVE");
1132 #if SIZEOF_VOID_P == 8
1134 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1136 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1139 if (m->class->sourcefile == NULL)
1140 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1142 logtextlen += utf_strlen(m->class->sourcefile);
1144 logtextlen += strlen(":65536)");
1147 logtextlen += strlen("call_java_method");
1149 logtextlen += strlen("0");
1151 /* allocate memory */
1153 dumpsize = dump_size();
1155 logtext = DMNEW(char, logtextlen);
1158 strcpy(logtext, "Exception ");
1159 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1162 strcpy(logtext, "Some Throwable");
1165 strcat(logtext, " thrown in ");
1168 utf_strcat_classname(logtext, m->class->name);
1169 strcat(logtext, ".");
1170 utf_strcat(logtext, m->name);
1171 utf_strcat(logtext, m->descriptor);
1173 if (m->flags & ACC_SYNCHRONIZED)
1174 strcat(logtext, "(SYNC");
1176 strcat(logtext, "(NOSYNC");
1178 if (m->flags & ACC_NATIVE) {
1179 strcat(logtext, ",NATIVE");
1183 #if SIZEOF_VOID_P == 8
1184 sprintf(logtext + strlen(logtext),
1185 ")(0x%016lx) at position 0x%016lx",
1186 (ptrint) code->entrypoint, (ptrint) pos);
1188 sprintf(logtext + strlen(logtext),
1189 ")(0x%08x) at position 0x%08x",
1190 (ptrint) code->entrypoint, (ptrint) pos);
1195 /* XXX preliminary: This should get the actual codeinfo */
1196 /* in which the exception happened. */
1199 #if SIZEOF_VOID_P == 8
1200 sprintf(logtext + strlen(logtext),
1201 ")(0x%016lx) at position 0x%016lx (",
1202 (ptrint) code->entrypoint, (ptrint) pos);
1204 sprintf(logtext + strlen(logtext),
1205 ")(0x%08x) at position 0x%08x (",
1206 (ptrint) code->entrypoint, (ptrint) pos);
1209 if (m->class->sourcefile == NULL)
1210 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1212 utf_strcat(logtext, m->class->sourcefile);
1214 sprintf(logtext + strlen(logtext), ":%d)", 0);
1218 strcat(logtext, "call_java_method");
1222 /* release memory */
1224 dump_release(dumpsize);
1228 #endif /* !defined(NDEBUG) */
1231 /* builtin_trace_args **********************************************************
1235 *******************************************************************************/
1237 #if !defined(NDEBUG)
1239 #ifdef TRACE_ARGS_NUM
1240 void builtin_trace_args(s8 a0, s8 a1,
1241 #if TRACE_ARGS_NUM >= 4
1243 #endif /* TRACE_ARGS_NUM >= 4 */
1244 #if TRACE_ARGS_NUM >= 6
1246 #endif /* TRACE_ARGS_NUM >= 6 */
1247 #if TRACE_ARGS_NUM == 8
1249 #endif /* TRACE_ARGS_NUM == 8 */
1261 /* calculate message length */
1264 strlen("4294967295 ") +
1265 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1267 strlen("called: ") +
1268 utf_strlen(m->class->name) +
1270 utf_strlen(m->name) +
1271 utf_strlen(m->descriptor) +
1272 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1274 /* add maximal argument length */
1276 logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1278 /* allocate memory */
1280 dumpsize = dump_size();
1282 logtext = DMNEW(char, logtextlen);
1286 sprintf(logtext, "%10d ", callcount);
1287 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1289 pos = strlen(logtext);
1291 for (i = 0; i < methodindent; i++)
1292 logtext[pos++] = '\t';
1294 strcpy(logtext + pos, "called: ");
1296 utf_strcat_classname(logtext, m->class->name);
1297 strcat(logtext, ".");
1298 utf_strcat(logtext, m->name);
1299 utf_strcat(logtext, m->descriptor);
1301 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1302 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1303 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1304 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1305 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1306 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1307 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1308 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1309 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1310 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1311 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1313 strcat(logtext, "(");
1315 /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso) */
1316 /* Only Arguments in integer Registers are passed correctly here */
1317 /* long longs spilled on Stack have an wrong offset of +4 */
1318 /* So preliminary Bugfix: Only pass 3 params at once to sprintf */
1319 /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8 */
1320 switch (md->paramcount) {
1324 #if SIZEOF_VOID_P == 4
1326 sprintf(logtext + strlen(logtext),
1332 sprintf(logtext + strlen(logtext),
1337 #if TRACE_ARGS_NUM >= 4
1339 sprintf(logtext + strlen(logtext),
1340 "0x%llx, 0x%llx, 0x%llx",
1345 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1347 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1350 #endif /* TRACE_ARGS_NUM >= 4 */
1352 #if TRACE_ARGS_NUM >= 6
1354 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1356 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1361 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1363 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1366 #endif /* TRACE_ARGS_NUM >= 6 */
1368 #if TRACE_ARGS_NUM == 8
1370 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1372 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1374 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1378 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1380 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1382 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1384 #endif /* TRACE_ARGS_NUM == 8 */
1387 #if TRACE_ARGS_NUM == 2
1388 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1390 #elif TRACE_ARGS_NUM == 4
1391 sprintf(logtext + strlen(logtext),
1392 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1393 a0, a1, a2, a3, md->paramcount - 4);
1395 #elif TRACE_ARGS_NUM == 6
1396 sprintf(logtext + strlen(logtext),
1397 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1398 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1400 #elif TRACE_ARGS_NUM == 8
1401 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1403 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1405 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1406 , a6, a7, md->paramcount - 8);
1410 #else /* SIZEOF_VOID_P == 4 */
1413 sprintf(logtext + strlen(logtext),
1419 sprintf(logtext + strlen(logtext),
1425 sprintf(logtext + strlen(logtext),
1426 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1430 sprintf(logtext + strlen(logtext),
1431 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1435 #if TRACE_ARGS_NUM >= 6
1437 sprintf(logtext + strlen(logtext),
1438 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1439 a0, a1, a2, a3, a4);
1443 sprintf(logtext + strlen(logtext),
1444 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1445 a0, a1, a2, a3, a4, a5);
1447 #endif /* TRACE_ARGS_NUM >= 6 */
1449 #if TRACE_ARGS_NUM == 8
1451 sprintf(logtext + strlen(logtext),
1452 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1453 a0, a1, a2, a3, a4, a5, a6);
1457 sprintf(logtext + strlen(logtext),
1458 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1459 a0, a1, a2, a3, a4, a5, a6, a7);
1461 #endif /* TRACE_ARGS_NUM == 8 */
1464 #if TRACE_ARGS_NUM == 4
1465 sprintf(logtext + strlen(logtext),
1466 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1467 a0, a1, a2, a3, md->paramcount - 4);
1469 #elif TRACE_ARGS_NUM == 6
1470 sprintf(logtext + strlen(logtext),
1471 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1472 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1474 #elif TRACE_ARGS_NUM == 8
1475 sprintf(logtext + strlen(logtext),
1476 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1477 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1480 #endif /* SIZEOF_VOID_P == 4 */
1483 strcat(logtext, ")");
1487 /* release memory */
1489 dump_release(dumpsize);
1494 #endif /* !defined(NDEBUG) */
1497 /* builtin_displaymethodstop ***************************************************
1501 *******************************************************************************/
1503 #if !defined(NDEBUG)
1504 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1512 java_objectheader *o;
1513 java_lang_String *s;
1521 /* calculate message length */
1524 strlen("4294967295 ") +
1525 strlen("-2147483647-") + /* INT_MAX should be sufficient */
1527 strlen("finished: ") +
1528 utf_strlen(m->class->name) +
1530 utf_strlen(m->name) +
1531 utf_strlen(m->descriptor) +
1532 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1534 /* add maximal argument length */
1536 logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1538 /* allocate memory */
1540 dumpsize = dump_size();
1542 logtext = DMNEW(char, logtextlen);
1544 /* outdent the log message */
1549 log_text("WARNING: unmatched methodindent--");
1551 /* generate the message */
1553 sprintf(logtext, " ");
1554 sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1556 pos = strlen(logtext);
1558 for (i = 0; i < methodindent; i++)
1559 logtext[pos++] = '\t';
1561 strcpy(logtext + pos, "finished: ");
1562 utf_strcat_classname(logtext, m->class->name);
1563 strcat(logtext, ".");
1564 utf_strcat(logtext, m->name);
1565 utf_strcat(logtext, m->descriptor);
1567 switch (md->returntype.type) {
1569 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1573 #if SIZEOF_VOID_P == 4
1574 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1576 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1581 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1583 /* check return argument for java.lang.Class or java.lang.String */
1585 o = (java_objectheader *) (ptrint) l;
1588 if (o->vftbl->class == class_java_lang_String) {
1589 /* get java.lang.String object and the length of the
1592 s= (java_lang_String *) (ptrint) l;
1594 len = strlen(", String = \"") + javastring_strlen(s) +
1597 /* realloc memory for string length */
1599 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1601 /* convert to utf8 string and strcat it to the logtext */
1603 u = javastring_toutf(s, false);
1605 strcat(logtext, ", String = \"");
1606 utf_strcat(logtext, u);
1607 strcat(logtext, "\"");
1610 if (o->vftbl->class == class_java_lang_Class) {
1611 /* if the object returned is a java.lang.Class
1612 cast it to classinfo structure and get the name
1615 c = (classinfo *) (ptrint) l;
1620 /* if the object returned is not a java.lang.String or
1621 a java.lang.Class just print the name of the class */
1623 u = o->vftbl->class->name;
1626 len = strlen(", Class = \"") + utf_strlen(u) + strlen("\"");
1628 /* realloc memory for string length */
1630 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1632 /* strcat to the logtext */
1634 strcat(logtext, ", Class = \"");
1635 utf_strcat(logtext, u);
1636 strcat(logtext, "\"");
1643 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1648 #if SIZEOF_VOID_P == 4
1649 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1651 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1658 /* release memory */
1660 dump_release(dumpsize);
1662 #endif /* !defined(NDEBUG) */
1665 /****************************************************************************
1666 SYNCHRONIZATION FUNCTIONS
1667 *****************************************************************************/
1669 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1671 * Lock the mutex of an object.
1673 void internal_lock_mutex_for_object(java_objectheader *object)
1675 mutexHashEntry *entry;
1678 assert(object != 0);
1680 hashValue = MUTEX_HASH_VALUE(object);
1681 entry = &mutexHashTable[hashValue];
1683 if (entry->object != 0) {
1684 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1686 entry->mutex.holder = 0;
1687 entry->mutex.count = 0;
1688 entry->mutex.muxWaiters = 0;
1691 while (entry->next != 0 && entry->object != object)
1692 entry = entry->next;
1694 if (entry->object != object) {
1695 entry->next = firstFreeOverflowEntry;
1696 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1698 entry = entry->next;
1701 assert(entry->conditionCount == 0);
1706 entry->mutex.holder = 0;
1707 entry->mutex.count = 0;
1708 entry->mutex.muxWaiters = 0;
1711 if (entry->object == 0)
1712 entry->object = object;
1714 internal_lock_mutex(&entry->mutex);
1719 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1721 * Unlocks the mutex of an object.
1723 void internal_unlock_mutex_for_object (java_objectheader *object)
1726 mutexHashEntry *entry;
1728 hashValue = MUTEX_HASH_VALUE(object);
1729 entry = &mutexHashTable[hashValue];
1731 if (entry->object == object) {
1732 internal_unlock_mutex(&entry->mutex);
1735 while (entry->next != 0 && entry->next->object != object)
1736 entry = entry->next;
1738 assert(entry->next != 0);
1740 internal_unlock_mutex(&entry->next->mutex);
1742 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1743 mutexHashEntry *unlinked = entry->next;
1745 entry->next = unlinked->next;
1746 unlinked->next = firstFreeOverflowEntry;
1747 firstFreeOverflowEntry = unlinked;
1754 #if defined(USE_THREADS)
1755 void builtin_monitorenter(java_objectheader *o)
1757 #if !defined(NATIVE_THREADS)
1762 hashValue = MUTEX_HASH_VALUE(o);
1763 if (mutexHashTable[hashValue].object == o
1764 && mutexHashTable[hashValue].mutex.holder == currentThread)
1765 ++mutexHashTable[hashValue].mutex.count;
1767 internal_lock_mutex_for_object(o);
1771 monitorEnter((threadobject *) THREADOBJECT, o);
1777 #if defined(USE_THREADS)
1779 * Locks the class object - needed for static synchronized methods.
1781 void builtin_staticmonitorenter(classinfo *c)
1783 builtin_monitorenter(&c->object.header);
1788 #if defined(USE_THREADS)
1789 void builtin_monitorexit(java_objectheader *o)
1791 #if !defined(NATIVE_THREADS)
1796 hashValue = MUTEX_HASH_VALUE(o);
1797 if (mutexHashTable[hashValue].object == o) {
1798 if (mutexHashTable[hashValue].mutex.count == 1
1799 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1800 internal_unlock_mutex_for_object(o);
1802 --mutexHashTable[hashValue].mutex.count;
1805 internal_unlock_mutex_for_object(o);
1809 monitorExit((threadobject *) THREADOBJECT, o);
1815 /*****************************************************************************
1816 MISCELLANEOUS HELPER FUNCTIONS
1817 *****************************************************************************/
1821 /*********** Functions for integer divisions *****************************
1823 On some systems (eg. DEC ALPHA), integer division is not supported by the
1824 CPU. These helper functions implement the missing functionality.
1826 ******************************************************************************/
1828 #if !SUPPORT_DIVISION
1829 s4 builtin_idiv(s4 a, s4 b)
1838 s4 builtin_irem(s4 a, s4 b)
1846 #endif /* !SUPPORT_DIVISION */
1849 /* functions for long arithmetics **********************************************
1851 On systems where 64 bit Integers are not supported by the CPU,
1852 these functions are needed.
1854 ******************************************************************************/
1856 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1857 s8 builtin_ladd(s8 a, s8 b)
1870 s8 builtin_lsub(s8 a, s8 b)
1883 s8 builtin_lneg(s8 a)
1895 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1898 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1899 s8 builtin_lmul(s8 a, s8 b)
1911 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1914 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1915 s8 builtin_ldiv(s8 a, s8 b)
1928 s8 builtin_lrem(s8 a, s8 b)
1940 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1943 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1944 s8 builtin_lshl(s8 a, s4 b)
1957 s8 builtin_lshr(s8 a, s4 b)
1970 s8 builtin_lushr(s8 a, s4 b)
1975 c = ((u8) a) >> (b & 63);
1982 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1985 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1986 s8 builtin_land(s8 a, s8 b)
1999 s8 builtin_lor(s8 a, s8 b)
2012 s8 builtin_lxor(s8 a, s8 b)
2024 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2027 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2028 s4 builtin_lcmp(s8 a, s8 b)
2042 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2045 /* functions for unsupported floating instructions ****************************/
2047 /* used to convert FLT_xxx defines into float values */
2049 static inline float intBitsToFloat(s4 i)
2058 /* used to convert DBL_xxx defines into double values */
2060 static inline float longBitsToDouble(s8 l)
2070 float builtin_fadd(float a, float b)
2072 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2073 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2084 if (copysignf(1.0, a) == copysignf(1.0, b))
2087 return intBitsToFloat(FLT_NAN);
2093 float builtin_fsub(float a, float b)
2095 return builtin_fadd(a, builtin_fneg(b));
2099 float builtin_fmul(float a, float b)
2101 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2102 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2104 if (finitef(b)) return a * b;
2106 if (a == 0) return intBitsToFloat(FLT_NAN);
2107 else return copysignf(b, copysignf(1.0, b)*a);
2112 if (b == 0) return intBitsToFloat(FLT_NAN);
2113 else return copysignf(a, copysignf(1.0, a)*b);
2116 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2122 /* builtin_ddiv ****************************************************************
2124 Implementation as described in VM Spec.
2126 *******************************************************************************/
2128 float builtin_fdiv(float a, float b)
2132 /* If neither value1' nor value2' is NaN, the sign of the result */
2133 /* is positive if both values have the same sign, negative if the */
2134 /* values have different signs. */
2140 /* If either value1' or value2' is NaN, the result is NaN. */
2142 return intBitsToFloat(FLT_NAN);
2145 /* Division of a finite value by an infinity results in a */
2146 /* signed zero, with the sign-producing rule just given. */
2148 /* is sign equal? */
2150 if (copysignf(1.0, a) == copysignf(1.0, b))
2159 /* If either value1' or value2' is NaN, the result is NaN. */
2161 return intBitsToFloat(FLT_NAN);
2163 } else if (finitef(b)) {
2164 /* Division of an infinity by a finite value results in a signed */
2165 /* infinity, with the sign-producing rule just given. */
2167 /* is sign equal? */
2169 if (copysignf(1.0, a) == copysignf(1.0, b))
2170 return intBitsToFloat(FLT_POSINF);
2172 return intBitsToFloat(FLT_NEGINF);
2175 /* Division of an infinity by an infinity results in NaN. */
2177 return intBitsToFloat(FLT_NAN);
2183 float builtin_fneg(float a)
2185 if (isnanf(a)) return a;
2187 if (finitef(a)) return -a;
2188 else return copysignf(a, -copysignf(1.0, a));
2191 #endif /* !SUPPORT_FLOAT */
2194 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2195 s4 builtin_fcmpl(float a, float b)
2197 if (isnanf(a)) return -1;
2198 if (isnanf(b)) return -1;
2199 if (!finitef(a) || !finitef(b)) {
2200 a = finitef(a) ? 0 : copysignf(1.0, a);
2201 b = finitef(b) ? 0 : copysignf(1.0, b);
2203 if (a > b) return 1;
2204 if (a == b) return 0;
2209 s4 builtin_fcmpg(float a, float b)
2211 if (isnanf(a)) return 1;
2212 if (isnanf(b)) return 1;
2213 if (!finitef(a) || !finitef(b)) {
2214 a = finitef(a) ? 0 : copysignf(1.0, a);
2215 b = finitef(b) ? 0 : copysignf(1.0, b);
2217 if (a > b) return 1;
2218 if (a == b) return 0;
2221 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2224 float builtin_frem(float a, float b)
2230 /* functions for unsupported double instructions ******************************/
2233 double builtin_dadd(double a, double b)
2235 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2236 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2238 if (finite(b)) return a + b;
2242 if (finite(b)) return a;
2244 if (copysign(1.0, a)==copysign(1.0, b)) return a;
2245 else return longBitsToDouble(DBL_NAN);
2251 double builtin_dsub(double a, double b)
2253 return builtin_dadd(a, builtin_dneg(b));
2257 double builtin_dmul(double a, double b)
2259 if (isnan(a)) return longBitsToDouble(DBL_NAN);
2260 if (isnan(b)) return longBitsToDouble(DBL_NAN);
2262 if (finite(b)) return a * b;
2264 if (a == 0) return longBitsToDouble(DBL_NAN);
2265 else return copysign(b, copysign(1.0, b) * a);
2270 if (b == 0) return longBitsToDouble(DBL_NAN);
2271 else return copysign(a, copysign(1.0, a) * b);
2274 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2280 /* builtin_ddiv ****************************************************************
2282 Implementation as described in VM Spec.
2284 *******************************************************************************/
2286 double builtin_ddiv(double a, double b)
2290 /* If neither value1' nor value2' is NaN, the sign of the result */
2291 /* is positive if both values have the same sign, negative if the */
2292 /* values have different signs. */
2298 /* If either value1' or value2' is NaN, the result is NaN. */
2300 return longBitsToDouble(DBL_NAN);
2303 /* Division of a finite value by an infinity results in a */
2304 /* signed zero, with the sign-producing rule just given. */
2306 /* is sign equal? */
2308 if (copysign(1.0, a) == copysign(1.0, b))
2317 /* If either value1' or value2' is NaN, the result is NaN. */
2319 return longBitsToDouble(DBL_NAN);
2321 } else if (finite(b)) {
2322 /* Division of an infinity by a finite value results in a signed */
2323 /* infinity, with the sign-producing rule just given. */
2325 /* is sign equal? */
2327 if (copysign(1.0, a) == copysign(1.0, b))
2328 return longBitsToDouble(DBL_POSINF);
2330 return longBitsToDouble(DBL_NEGINF);
2333 /* Division of an infinity by an infinity results in NaN. */
2335 return longBitsToDouble(DBL_NAN);
2341 /* builtin_dneg ****************************************************************
2343 Implemented as described in VM Spec.
2345 *******************************************************************************/
2347 double builtin_dneg(double a)
2350 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2357 /* If the operand is a zero, the result is the zero of opposite */
2363 /* If the operand is an infinity, the result is the infinity of */
2364 /* opposite sign. */
2366 return copysign(a, -copysign(1.0, a));
2370 #endif /* !SUPPORT_DOUBLE */
2373 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2374 s4 builtin_dcmpl(double a, double b)
2376 if (isnan(a)) return -1;
2377 if (isnan(b)) return -1;
2378 if (!finite(a) || !finite(b)) {
2379 a = finite(a) ? 0 : copysign(1.0, a);
2380 b = finite(b) ? 0 : copysign(1.0, b);
2382 if (a > b) return 1;
2383 if (a == b) return 0;
2388 s4 builtin_dcmpg(double a, double b)
2390 if (isnan(a)) return 1;
2391 if (isnan(b)) return 1;
2392 if (!finite(a) || !finite(b)) {
2393 a = finite(a) ? 0 : copysign(1.0, a);
2394 b = finite(b) ? 0 : copysign(1.0, b);
2396 if (a > b) return 1;
2397 if (a == b) return 0;
2400 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2403 double builtin_drem(double a, double b)
2409 /* conversion operations ******************************************************/
2412 s8 builtin_i2l(s4 i)
2424 s4 builtin_l2i(s8 l)
2435 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2436 float builtin_i2f(s4 a)
2438 float f = (float) a;
2441 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2444 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2445 double builtin_i2d(s4 a)
2447 double d = (double) a;
2450 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2453 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2454 float builtin_l2f(s8 a)
2457 float f = (float) a;
2463 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2466 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2467 double builtin_l2d(s8 a)
2470 double d = (double) a;
2476 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2479 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2480 s4 builtin_f2i(float a)
2484 i = builtin_d2i((double) a);
2495 if (a < (-2147483648))
2496 return (-2147483648);
2499 f = copysignf((float) 1.0, a);
2502 return (-2147483648); */
2504 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2507 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2508 s8 builtin_f2l(float a)
2512 l = builtin_d2l((double) a);
2519 if (a > 9223372036854775807L)
2520 return 9223372036854775807L;
2521 if (a < (-9223372036854775808L))
2522 return (-9223372036854775808L);
2527 f = copysignf((float) 1.0, a);
2529 return 9223372036854775807L;
2530 return (-9223372036854775808L); */
2532 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2535 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2536 s4 builtin_d2i(double a)
2541 if (a >= 2147483647)
2543 if (a <= (-2147483647-1))
2544 return (-2147483647-1);
2549 d = copysign(1.0, a);
2552 return (-2147483647-1);
2554 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2557 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2558 s8 builtin_d2l(double a)
2563 if (a >= 9223372036854775807LL)
2564 return 9223372036854775807LL;
2565 if (a <= (-9223372036854775807LL-1))
2566 return (-9223372036854775807LL-1);
2571 d = copysign(1.0, a);
2573 return 9223372036854775807LL;
2574 return (-9223372036854775807LL-1);
2576 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2579 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2580 double builtin_f2d(float a)
2582 if (finitef(a)) return (double) a;
2585 return longBitsToDouble(DBL_NAN);
2587 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2591 float builtin_d2f(double a)
2597 return intBitsToFloat(FLT_NAN);
2599 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2602 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2605 /* builtin_clone_array *********************************************************
2607 Wrapper function for cloning arrays.
2609 *******************************************************************************/
2611 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2613 java_arrayheader *ah;
2614 java_lang_Cloneable *c;
2616 c = (java_lang_Cloneable *) o;
2618 ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2624 /* builtin_asm_get_exceptionptrptr *********************************************
2626 this is a wrapper for calls from asmpart
2628 *******************************************************************************/
2630 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2631 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2633 return builtin_get_exceptionptrptr();
2639 * These are local overrides for various environment variables in Emacs.
2640 * Please do not remove this and leave it at the end of the file, where
2641 * Emacs will automagically detect them.
2642 * ---------------------------------------------------------------------
2645 * indent-tabs-mode: t
2649 * vim:noexpandtab:sw=4:ts=4: