1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contains C functions for JavaVM Instructions that cannot be
26 translated to machine language directly. Consequently, the
27 generated machine code for these instructions contains function
28 calls instead of machine instructions, using the C calling
47 #include "fdlibm/fdlibm.h"
48 #if defined(__CYGWIN__) && defined(Bias)
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
55 #include "native/jni.h"
56 #include "native/llni.h"
58 #include "threads/lock-common.h"
59 #include "threads/threads-common.h"
61 #include "toolbox/logging.h"
62 #include "toolbox/util.h"
65 #include "vm/builtin.h"
66 #include "vm/cycles-stats.h"
67 #include "vm/exceptions.h"
68 #include "vm/global.h"
69 #include "vm/initialize.h"
70 #include "vm/primitive.h"
71 #include "vm/stringlocal.h"
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/trace.h"
76 #include "vmcore/class.h"
77 #include "vmcore/linker.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.h"
80 #include "vmcore/rt-timing.h"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
87 /* include builtin tables *****************************************************/
89 #include "vm/builtintable.inc"
92 CYCLES_STATS_DECLARE(builtin_new ,100,5)
93 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
96 /*============================================================================*/
97 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
98 /*============================================================================*/
100 /* builtintable_init ***********************************************************
102 Parse the descriptors of builtin functions and create the parsed
105 *******************************************************************************/
107 static bool builtintable_init(void)
109 descriptor_pool *descpool;
111 builtintable_entry *bte;
114 /* mark start of dump memory area */
116 dumpsize = dump_size();
118 /* create a new descriptor pool */
120 descpool = descriptor_pool_new(class_java_lang_Object);
122 /* add some entries we need */
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
127 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
130 /* first add all descriptors to the pool */
132 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
133 bte->name = utf_new_char(bte->cname);
134 bte->descriptor = utf_new_char(bte->cdescriptor);
136 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
137 /* release dump area */
139 dump_release(dumpsize);
145 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
146 bte->descriptor = utf_new_char(bte->cdescriptor);
148 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
149 dump_release(dumpsize);
154 for (bte = builtintable_function; bte->fp != NULL; bte++) {
155 bte->classname = utf_new_char(bte->cclassname);
156 bte->name = utf_new_char(bte->cname);
157 bte->descriptor = utf_new_char(bte->cdescriptor);
159 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
160 dump_release(dumpsize);
165 /* create the class reference table */
167 (void) descriptor_pool_create_classrefs(descpool, NULL);
169 /* allocate space for the parsed descriptors */
171 descriptor_pool_alloc_parsed_descriptors(descpool);
173 /* Now parse all descriptors. NOTE: builtin-functions are treated
174 like static methods (no `this' pointer). */
176 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
178 descriptor_pool_parse_method_descriptor(descpool,
180 ACC_STATIC | ACC_METHOD_BUILTIN,
183 /* generate a builtin stub if we need one */
185 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
186 m = method_new_builtin(bte);
187 codegen_generate_stub_builtin(m, bte);
191 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* no stubs should be needed for this table */
200 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
203 for (bte = builtintable_function; bte->fp != NULL; bte++) {
205 descriptor_pool_parse_method_descriptor(descpool,
207 ACC_STATIC | ACC_METHOD_BUILTIN,
210 /* generate a builtin stub if we need one */
212 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
213 m = method_new_builtin(bte);
214 codegen_generate_stub_builtin(m, bte);
218 /* release dump area */
220 dump_release(dumpsize);
226 /* builtintable_comparator *****************************************************
228 qsort comparator for the automatic builtin table.
230 *******************************************************************************/
232 static int builtintable_comparator(const void *a, const void *b)
234 builtintable_entry *bte1;
235 builtintable_entry *bte2;
237 bte1 = (builtintable_entry *) a;
238 bte2 = (builtintable_entry *) b;
240 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
244 /* builtintable_sort_automatic *************************************************
246 Sorts the automatic builtin table.
248 *******************************************************************************/
250 static void builtintable_sort_automatic(void)
254 /* calculate table size statically (`- 1' comment see builtintable.inc) */
256 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
258 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
259 builtintable_comparator);
263 /* builtin_init ****************************************************************
265 Initialize the global table of builtin functions.
267 *******************************************************************************/
269 bool builtin_init(void)
271 /* initialize the builtin tables */
273 if (!builtintable_init())
276 /* sort builtin tables */
278 builtintable_sort_automatic();
284 /* builtintable_get_internal ***************************************************
286 Finds an entry in the builtintable for internal functions and
287 returns the a pointer to the structure.
289 *******************************************************************************/
291 builtintable_entry *builtintable_get_internal(functionptr fp)
293 builtintable_entry *bte;
295 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
304 /* builtintable_get_automatic **************************************************
306 Finds an entry in the builtintable for functions which are replaced
307 automatically and returns the a pointer to the structure.
309 *******************************************************************************/
311 builtintable_entry *builtintable_get_automatic(s4 opcode)
313 builtintable_entry *first;
314 builtintable_entry *last;
315 builtintable_entry *middle;
319 /* calculate table size statically (`- 1' comment see builtintable.inc) */
321 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
323 first = builtintable_automatic;
324 last = builtintable_automatic + entries;
326 while (entries > 0) {
328 middle = first + half;
330 if (middle->opcode < opcode) {
338 return (first != last ? first : NULL);
342 /* builtintable_replace_function ***********************************************
346 *******************************************************************************/
348 #if defined(ENABLE_JIT)
349 bool builtintable_replace_function(void *iptr_)
352 builtintable_entry *bte;
355 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
357 /* get name and descriptor of the function */
360 case ICMD_INVOKESTATIC:
361 /* The instruction MUST be resolved, otherwise we run into
362 lazy loading troubles. Anyway, we should/can only replace
363 very VM-close functions. */
365 if (INSTRUCTION_IS_UNRESOLVED(iptr))
368 mr = iptr->sx.s23.s3.fmiref;
375 /* search the function table */
377 for (bte = builtintable_function; bte->fp != NULL; bte++) {
378 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
379 (mr->name == bte->name) &&
380 (mr->descriptor == bte->descriptor)) {
382 /* set the values in the instruction */
384 iptr->opc = bte->opcode;
385 iptr->sx.s23.s3.bte = bte;
387 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
388 iptr->flags.bits |= INS_FLAG_CHECK;
390 iptr->flags.bits &= ~INS_FLAG_CHECK;
398 #endif /* defined(ENABLE_JIT) */
401 /*============================================================================*/
402 /* INTERNAL BUILTIN FUNCTIONS */
403 /*============================================================================*/
405 /* builtin_instanceof **********************************************************
407 Checks if an object is an instance of some given class (or subclass
408 of that class). If class is an interface, checks if the interface
412 1......o is an instance of class or implements the interface
413 0......otherwise or if o == NULL
415 NOTE: This builtin can be called from NATIVE code only.
417 *******************************************************************************/
419 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
426 LLNI_class_get(o, c);
428 return class_isanysubclass(c, class);
433 /* builtin_checkcast ***********************************************************
435 The same as builtin_instanceof but with the exception
436 that 1 is returned when (o == NULL).
438 NOTE: This builtin can be called from NATIVE code only.
440 *******************************************************************************/
442 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
449 LLNI_class_get(o, c);
451 if (class_isanysubclass(c, class))
458 /* builtin_descriptorscompatible ***********************************************
460 Checks if two array type descriptors are assignment compatible.
463 1......target = desc is possible
466 *******************************************************************************/
468 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
469 arraydescriptor *target)
474 if (desc->arraytype != target->arraytype)
477 if (desc->arraytype != ARRAYTYPE_OBJECT)
480 /* {both arrays are arrays of references} */
482 if (desc->dimension == target->dimension) {
483 /* an array which contains elements of interface types is
484 allowed to be casted to Object (JOWENN)*/
486 if ((desc->elementvftbl->baseval < 0) &&
487 (target->elementvftbl->baseval == 1))
490 return class_isanysubclass(desc->elementvftbl->class,
491 target->elementvftbl->class);
494 if (desc->dimension < target->dimension)
497 /* {desc has higher dimension than target} */
499 return class_isanysubclass(pseudo_class_Arraystub,
500 target->elementvftbl->class);
504 /* builtin_arraycheckcast ******************************************************
506 Checks if an object is really a subtype of the requested array
507 type. The object has to be an array to begin with. For simple
508 arrays (int, short, double, etc.) the types have to match exactly.
509 For arrays of objects, the type of elements in the array has to be
510 a subtype (or the same type) of the requested element type. For
511 arrays of arrays (which in turn can again be arrays of arrays), the
512 types at the lowest level have to satisfy the corresponding sub
515 NOTE: This is a FAST builtin and can be called from JIT code only.
517 *******************************************************************************/
519 s4 builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
521 arraydescriptor *desc;
526 desc = o->vftbl->arraydesc;
531 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
535 /* builtin_fast_arrayinstanceof ************************************************
537 NOTE: This is a FAST builtin and can be called from JIT code only.
539 *******************************************************************************/
541 s4 builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
546 return builtin_fast_arraycheckcast(o, targetclass);
550 /* builtin_arrayinstanceof *****************************************************
552 NOTE: This builtin can be called from NATIVE code only.
554 *******************************************************************************/
556 s4 builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
562 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
570 /* builtin_throw_exception *****************************************************
572 Sets the exception pointer with the thrown exception and prints some
573 debugging information.
575 NOTE: This is a FAST builtin and can be called from JIT code,
576 or from asm_vm_call_method.
578 *******************************************************************************/
580 void *builtin_throw_exception(java_object_t *xptr)
583 /* print exception trace */
585 if (opt_TraceExceptions)
586 trace_exception_builtin(xptr);
587 #endif /* !defined(NDEBUG) */
589 /* actually set the exception */
591 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
593 /* Return a NULL pointer. This is required for vm_call_method to
594 check for an exception. This is for convenience. */
600 /* builtin_retrieve_exception **************************************************
602 Gets and clears the exception pointer of the current thread.
605 the exception object, or NULL if no exception was thrown.
607 NOTE: This is a FAST builtin and can be called from JIT code,
608 or from the signal handlers.
610 *******************************************************************************/
612 java_object_t *builtin_retrieve_exception(void)
617 /* actually get and clear the exception */
619 h = exceptions_get_and_clear_exception();
626 /* builtin_canstore ************************************************************
628 Checks, if an object can be stored in an array.
632 0......otherwise (throws an ArrayStoreException)
634 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
636 *******************************************************************************/
638 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
644 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
648 /* if not possible, throw an exception */
651 exceptions_throw_arraystoreexception();
657 /* builtin_fast_canstore *******************************************************
659 Checks, if an object can be stored in an array.
663 0......otherwise (no exception thrown!)
665 NOTE: This is a FAST builtin and can be called from JIT code only.
667 *******************************************************************************/
669 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
671 arraydescriptor *desc;
672 arraydescriptor *valuedesc;
673 vftbl_t *componentvftbl;
682 /* The following is guaranteed (by verifier checks):
684 * *) oa->...vftbl->arraydesc != NULL
685 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
686 * *) o->vftbl is not an interface vftbl
689 desc = oa->header.objheader.vftbl->arraydesc;
690 componentvftbl = desc->componentvftbl;
691 valuevftbl = o->vftbl;
692 valuedesc = valuevftbl->arraydesc;
694 if ((desc->dimension - 1) == 0) {
695 /* {oa is a one-dimensional array} */
696 /* {oa is an array of references} */
698 if (valuevftbl == componentvftbl)
701 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
703 baseval = componentvftbl->baseval;
706 /* an array of interface references */
708 result = ((valuevftbl->interfacetablelength > -baseval) &&
709 (valuevftbl->interfacetable[baseval] != NULL));
712 diffval = valuevftbl->baseval - componentvftbl->baseval;
713 result = diffval <= (uint32_t) componentvftbl->diffval;
716 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
718 else if (valuedesc == NULL) {
719 /* {oa has dimension > 1} */
720 /* {componentvftbl->arraydesc != NULL} */
722 /* check if o is an array */
727 /* {o is an array} */
729 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
738 /* This is an optimized version where a is guaranteed to be one-dimensional */
739 s4 builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
741 arraydescriptor *desc;
742 vftbl_t *elementvftbl;
751 /* The following is guaranteed (by verifier checks):
753 * *) a->...vftbl->arraydesc != NULL
754 * *) a->...vftbl->arraydesc->elementvftbl != NULL
755 * *) a->...vftbl->arraydesc->dimension == 1
756 * *) o->vftbl is not an interface vftbl
759 desc = a->header.objheader.vftbl->arraydesc;
760 elementvftbl = desc->elementvftbl;
761 valuevftbl = o->vftbl;
763 /* {a is a one-dimensional array} */
765 if (valuevftbl == elementvftbl)
768 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
770 baseval = elementvftbl->baseval;
773 /* an array of interface references */
774 result = ((valuevftbl->interfacetablelength > -baseval) &&
775 (valuevftbl->interfacetable[baseval] != NULL));
778 diffval = valuevftbl->baseval - elementvftbl->baseval;
779 result = diffval <= (uint32_t) elementvftbl->diffval;
782 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
788 /* This is an optimized version where a is guaranteed to be a
789 * one-dimensional array of a class type */
790 s4 builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
792 vftbl_t *elementvftbl;
800 /* The following is guaranteed (by verifier checks):
802 * *) a->...vftbl->arraydesc != NULL
803 * *) a->...vftbl->arraydesc->elementvftbl != NULL
804 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
805 * *) a->...vftbl->arraydesc->dimension == 1
806 * *) o->vftbl is not an interface vftbl
809 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
810 valuevftbl = o->vftbl;
812 /* {a is a one-dimensional array} */
814 if (valuevftbl == elementvftbl)
817 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
819 diffval = valuevftbl->baseval - elementvftbl->baseval;
820 result = diffval <= (uint32_t) elementvftbl->diffval;
822 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
828 /* builtin_new *****************************************************************
830 Creates a new instance of class c on the heap.
833 pointer to the object, or NULL if no memory is available
835 NOTE: This builtin can be called from NATIVE code only.
837 *******************************************************************************/
839 java_handle_t *builtin_new(classinfo *c)
842 #if defined(ENABLE_RT_TIMING)
843 struct timespec time_start, time_end;
845 #if defined(ENABLE_CYCLES_STATS)
846 u8 cycles_start, cycles_end;
849 RT_TIMING_GET_TIME(time_start);
850 CYCLES_STATS_GET(cycles_start);
852 /* is the class loaded */
854 assert(c->state & CLASS_LOADED);
856 /* check if we can instantiate this class */
858 if (c->flags & ACC_ABSTRACT) {
859 exceptions_throw_instantiationerror(c);
863 /* is the class linked */
865 if (!(c->state & CLASS_LINKED))
869 if (!(c->state & CLASS_INITIALIZED)) {
872 log_message_class("Initialize class (from builtin_new): ", c);
875 if (!initialize_class(c))
879 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
885 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
886 /* XXX this is only a dirty hack to make Boehm work with handles */
888 o = LLNI_WRAP((java_object_t *) o);
891 LLNI_vftbl_direct(o) = c->vftbl;
893 #if defined(ENABLE_THREADS)
894 lock_init_object_lock(LLNI_DIRECT(o));
897 CYCLES_STATS_GET(cycles_end);
898 RT_TIMING_GET_TIME(time_end);
900 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
901 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
907 /* builtin_java_new ************************************************************
909 NOTE: This is a SLOW builtin and can be called from JIT code only.
911 *******************************************************************************/
913 java_handle_t *builtin_java_new(java_handle_t *clazz)
915 return builtin_new(LLNI_classinfo_unwrap(clazz));
919 /* builtin_fast_new ************************************************************
921 Creates a new instance of class c on the heap.
924 pointer to the object, or NULL if no fast return
925 is possible for any reason.
927 NOTE: This is a FAST builtin and can be called from JIT code only.
929 *******************************************************************************/
931 java_object_t *builtin_fast_new(classinfo *c)
934 #if defined(ENABLE_RT_TIMING)
935 struct timespec time_start, time_end;
937 #if defined(ENABLE_CYCLES_STATS)
938 u8 cycles_start, cycles_end;
941 RT_TIMING_GET_TIME(time_start);
942 CYCLES_STATS_GET(cycles_start);
944 /* is the class loaded */
946 assert(c->state & CLASS_LOADED);
948 /* check if we can instantiate this class */
950 if (c->flags & ACC_ABSTRACT)
953 /* is the class linked */
955 if (!(c->state & CLASS_LINKED))
958 if (!(c->state & CLASS_INITIALIZED))
961 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
962 c->finalizer, false);
969 #if defined(ENABLE_THREADS)
970 lock_init_object_lock(o);
973 CYCLES_STATS_GET(cycles_end);
974 RT_TIMING_GET_TIME(time_end);
976 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
977 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
983 /* builtin_newarray ************************************************************
985 Creates an array with the given vftbl on the heap. This function
986 takes as class argument an array class.
989 pointer to the array or NULL if no memory is available
991 NOTE: This builtin can be called from NATIVE code only.
993 *******************************************************************************/
995 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
997 arraydescriptor *desc;
1002 #if defined(ENABLE_RT_TIMING)
1003 struct timespec time_start, time_end;
1006 RT_TIMING_GET_TIME(time_start);
1008 desc = arrayclass->vftbl->arraydesc;
1009 dataoffset = desc->dataoffset;
1010 componentsize = desc->componentsize;
1013 exceptions_throw_negativearraysizeexception();
1017 actualsize = dataoffset + size * componentsize;
1019 /* check for overflow */
1021 if (((u4) actualsize) < ((u4) size)) {
1022 exceptions_throw_outofmemoryerror();
1026 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1031 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1032 /* XXX this is only a dirty hack to make Boehm work with handles */
1034 a = LLNI_WRAP((java_object_t *) a);
1037 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1039 #if defined(ENABLE_THREADS)
1040 lock_init_object_lock(LLNI_DIRECT(a));
1043 LLNI_array_size(a) = size;
1045 RT_TIMING_GET_TIME(time_end);
1046 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1052 /* builtin_java_newarray *******************************************************
1054 NOTE: This is a SLOW builtin and can be called from JIT code only.
1056 *******************************************************************************/
1058 java_handle_t *builtin_java_newarray(s4 size, java_handle_t *arrayclazz)
1060 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1064 /* builtin_anewarray ***********************************************************
1066 Creates an array of references to the given class type on the heap.
1069 pointer to the array or NULL if no memory is
1072 NOTE: This builtin can be called from NATIVE code only.
1074 *******************************************************************************/
1076 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
1078 classinfo *arrayclass;
1080 /* is class loaded */
1082 assert(componentclass->state & CLASS_LOADED);
1084 /* is class linked */
1086 if (!(componentclass->state & CLASS_LINKED))
1087 if (!link_class(componentclass))
1090 arrayclass = class_array_of(componentclass, true);
1095 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1099 /* builtin_newarray_type ****************************************************
1101 Creates an array of [type]s on the heap.
1104 pointer to the array or NULL if no memory is available
1106 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1108 *******************************************************************************/
1110 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1111 java_handle_##type##array_t *builtin_newarray_##type(s4 size) \
1113 return (java_handle_##type##array_t *) \
1114 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1117 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1118 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1119 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1120 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1121 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1122 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1123 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1124 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1127 /* builtin_multianewarray_intern ***********************************************
1129 Creates a multi-dimensional array on the heap. The dimensions are
1130 passed in an array of longs.
1133 n.............number of dimensions to create
1134 arrayclass....the array class
1135 dims..........array containing the size of each dimension to create
1138 pointer to the array or NULL if no memory is available
1140 ******************************************************************************/
1142 static java_handle_t *builtin_multianewarray_intern(int n,
1143 classinfo *arrayclass,
1148 classinfo *componentclass;
1151 /* create this dimension */
1153 size = (s4) dims[0];
1154 a = builtin_newarray(size, arrayclass);
1159 /* if this is the last dimension return */
1164 /* get the class of the components to create */
1166 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1168 /* The verifier guarantees that the dimension count is in the range. */
1170 /* create the component arrays */
1172 for (i = 0; i < size; i++) {
1174 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1175 /* we save an s4 to a s8 slot, 8-byte aligned */
1177 builtin_multianewarray_intern(n, componentclass, dims + 2);
1179 builtin_multianewarray_intern(n, componentclass, dims + 1);
1185 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1192 /* builtin_multianewarray ******************************************************
1194 Wrapper for builtin_multianewarray_intern which checks all
1195 dimensions before we start allocating.
1197 NOTE: This is a SLOW builtin and can be called from JIT code only.
1199 ******************************************************************************/
1201 java_handle_objectarray_t *builtin_multianewarray(int n,
1202 java_handle_t *arrayclazz,
1209 /* check all dimensions before doing anything */
1211 for (i = 0; i < n; i++) {
1212 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1213 /* we save an s4 to a s8 slot, 8-byte aligned */
1214 size = (s4) dims[i * 2];
1216 size = (s4) dims[i];
1220 exceptions_throw_negativearraysizeexception();
1225 c = LLNI_classinfo_unwrap(arrayclazz);
1227 /* now call the real function */
1229 return (java_handle_objectarray_t *)
1230 builtin_multianewarray_intern(n, c, dims);
1234 /* builtin_verbosecall_enter ***************************************************
1236 Print method call with arguments for -verbose:call.
1238 XXX: Remove mew once all archs use the new tracer!
1240 *******************************************************************************/
1242 #if !defined(NDEBUG)
1243 #ifdef TRACE_ARGS_NUM
1244 void builtin_verbosecall_enter(s8 a0, s8 a1,
1245 # if TRACE_ARGS_NUM >= 4
1248 # if TRACE_ARGS_NUM >= 6
1251 # if TRACE_ARGS_NUM == 8
1256 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1259 #endif /* !defined(NDEBUG) */
1262 /* builtin_verbosecall_exit ****************************************************
1264 Print method exit for -verbose:call.
1266 XXX: Remove mew once all archs use the new tracer!
1268 *******************************************************************************/
1270 #if !defined(NDEBUG)
1271 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1273 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1275 #endif /* !defined(NDEBUG) */
1278 /*============================================================================*/
1279 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1280 /*============================================================================*/
1282 /*********** Functions for integer divisions *****************************
1284 On some systems (eg. DEC ALPHA), integer division is not supported by the
1285 CPU. These helper functions implement the missing functionality.
1287 ******************************************************************************/
1289 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1290 s4 builtin_idiv(s4 a, s4 b)
1299 s4 builtin_irem(s4 a, s4 b)
1307 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1310 /* functions for long arithmetics **********************************************
1312 On systems where 64 bit Integers are not supported by the CPU,
1313 these functions are needed.
1315 ******************************************************************************/
1317 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1318 s8 builtin_ladd(s8 a, s8 b)
1331 s8 builtin_lsub(s8 a, s8 b)
1344 s8 builtin_lneg(s8 a)
1356 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1359 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1360 s8 builtin_lmul(s8 a, s8 b)
1372 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1375 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1376 s8 builtin_ldiv(s8 a, s8 b)
1389 s8 builtin_lrem(s8 a, s8 b)
1401 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1404 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1405 s8 builtin_lshl(s8 a, s4 b)
1418 s8 builtin_lshr(s8 a, s4 b)
1431 s8 builtin_lushr(s8 a, s4 b)
1436 c = ((u8) a) >> (b & 63);
1443 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1446 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1447 s8 builtin_land(s8 a, s8 b)
1460 s8 builtin_lor(s8 a, s8 b)
1473 s8 builtin_lxor(s8 a, s8 b)
1485 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1488 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1489 s4 builtin_lcmp(s8 a, s8 b)
1503 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1506 /* functions for unsupported floating instructions ****************************/
1508 /* used to convert FLT_xxx defines into float values */
1510 static inline float intBitsToFloat(s4 i)
1519 /* used to convert DBL_xxx defines into double values */
1521 static inline float longBitsToDouble(s8 l)
1531 float builtin_fadd(float a, float b)
1533 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1534 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1545 if (copysignf(1.0, a) == copysignf(1.0, b))
1548 return intBitsToFloat(FLT_NAN);
1554 float builtin_fsub(float a, float b)
1556 return builtin_fadd(a, builtin_fneg(b));
1560 float builtin_fmul(float a, float b)
1562 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1563 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1565 if (finitef(b)) return a * b;
1567 if (a == 0) return intBitsToFloat(FLT_NAN);
1568 else return copysignf(b, copysignf(1.0, b)*a);
1573 if (b == 0) return intBitsToFloat(FLT_NAN);
1574 else return copysignf(a, copysignf(1.0, a)*b);
1577 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1583 /* builtin_ddiv ****************************************************************
1585 Implementation as described in VM Spec.
1587 *******************************************************************************/
1589 float builtin_fdiv(float a, float b)
1593 /* If neither value1' nor value2' is NaN, the sign of the result */
1594 /* is positive if both values have the same sign, negative if the */
1595 /* values have different signs. */
1601 /* If either value1' or value2' is NaN, the result is NaN. */
1603 return intBitsToFloat(FLT_NAN);
1606 /* Division of a finite value by an infinity results in a */
1607 /* signed zero, with the sign-producing rule just given. */
1609 /* is sign equal? */
1611 if (copysignf(1.0, a) == copysignf(1.0, b))
1620 /* If either value1' or value2' is NaN, the result is NaN. */
1622 return intBitsToFloat(FLT_NAN);
1624 } else if (finitef(b)) {
1625 /* Division of an infinity by a finite value results in a signed */
1626 /* infinity, with the sign-producing rule just given. */
1628 /* is sign equal? */
1630 if (copysignf(1.0, a) == copysignf(1.0, b))
1631 return intBitsToFloat(FLT_POSINF);
1633 return intBitsToFloat(FLT_NEGINF);
1636 /* Division of an infinity by an infinity results in NaN. */
1638 return intBitsToFloat(FLT_NAN);
1644 float builtin_fneg(float a)
1646 if (isnanf(a)) return a;
1648 if (finitef(a)) return -a;
1649 else return copysignf(a, -copysignf(1.0, a));
1652 #endif /* !SUPPORT_FLOAT */
1655 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1656 s4 builtin_fcmpl(float a, float b)
1664 if (!finitef(a) || !finitef(b)) {
1665 a = finitef(a) ? 0 : copysignf(1.0, a);
1666 b = finitef(b) ? 0 : copysignf(1.0, b);
1679 s4 builtin_fcmpg(float a, float b)
1681 if (isnanf(a)) return 1;
1682 if (isnanf(b)) return 1;
1683 if (!finitef(a) || !finitef(b)) {
1684 a = finitef(a) ? 0 : copysignf(1.0, a);
1685 b = finitef(b) ? 0 : copysignf(1.0, b);
1687 if (a > b) return 1;
1688 if (a == b) return 0;
1691 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1694 float builtin_frem(float a, float b)
1700 /* functions for unsupported double instructions ******************************/
1703 double builtin_dadd(double a, double b)
1705 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1706 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1708 if (finite(b)) return a + b;
1712 if (finite(b)) return a;
1714 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1715 else return longBitsToDouble(DBL_NAN);
1721 double builtin_dsub(double a, double b)
1723 return builtin_dadd(a, builtin_dneg(b));
1727 double builtin_dmul(double a, double b)
1729 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1730 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1732 if (finite(b)) return a * b;
1734 if (a == 0) return longBitsToDouble(DBL_NAN);
1735 else return copysign(b, copysign(1.0, b) * a);
1740 if (b == 0) return longBitsToDouble(DBL_NAN);
1741 else return copysign(a, copysign(1.0, a) * b);
1744 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1750 /* builtin_ddiv ****************************************************************
1752 Implementation as described in VM Spec.
1754 *******************************************************************************/
1756 double builtin_ddiv(double a, double b)
1760 /* If neither value1' nor value2' is NaN, the sign of the result */
1761 /* is positive if both values have the same sign, negative if the */
1762 /* values have different signs. */
1768 /* If either value1' or value2' is NaN, the result is NaN. */
1770 return longBitsToDouble(DBL_NAN);
1773 /* Division of a finite value by an infinity results in a */
1774 /* signed zero, with the sign-producing rule just given. */
1776 /* is sign equal? */
1778 if (copysign(1.0, a) == copysign(1.0, b))
1787 /* If either value1' or value2' is NaN, the result is NaN. */
1789 return longBitsToDouble(DBL_NAN);
1791 } else if (finite(b)) {
1792 /* Division of an infinity by a finite value results in a signed */
1793 /* infinity, with the sign-producing rule just given. */
1795 /* is sign equal? */
1797 if (copysign(1.0, a) == copysign(1.0, b))
1798 return longBitsToDouble(DBL_POSINF);
1800 return longBitsToDouble(DBL_NEGINF);
1803 /* Division of an infinity by an infinity results in NaN. */
1805 return longBitsToDouble(DBL_NAN);
1811 /* builtin_dneg ****************************************************************
1813 Implemented as described in VM Spec.
1815 *******************************************************************************/
1817 double builtin_dneg(double a)
1820 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1827 /* If the operand is a zero, the result is the zero of opposite */
1833 /* If the operand is an infinity, the result is the infinity of */
1834 /* opposite sign. */
1836 return copysign(a, -copysign(1.0, a));
1840 #endif /* !SUPPORT_DOUBLE */
1843 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1844 s4 builtin_dcmpl(double a, double b)
1852 if (!finite(a) || !finite(b)) {
1853 a = finite(a) ? 0 : copysign(1.0, a);
1854 b = finite(b) ? 0 : copysign(1.0, b);
1867 s4 builtin_dcmpg(double a, double b)
1875 if (!finite(a) || !finite(b)) {
1876 a = finite(a) ? 0 : copysign(1.0, a);
1877 b = finite(b) ? 0 : copysign(1.0, b);
1888 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1891 double builtin_drem(double a, double b)
1897 /* conversion operations ******************************************************/
1900 s8 builtin_i2l(s4 i)
1912 s4 builtin_l2i(s8 l)
1923 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1924 float builtin_i2f(s4 a)
1926 float f = (float) a;
1929 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1932 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1933 double builtin_i2d(s4 a)
1935 double d = (double) a;
1938 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1941 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1942 float builtin_l2f(s8 a)
1945 float f = (float) a;
1951 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1954 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1955 double builtin_l2d(s8 a)
1958 double d = (double) a;
1964 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1967 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1968 s4 builtin_f2i(float a)
1972 i = builtin_d2i((double) a);
1983 if (a < (-2147483648))
1984 return (-2147483648);
1987 f = copysignf((float) 1.0, a);
1990 return (-2147483648); */
1992 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1995 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1996 s8 builtin_f2l(float a)
2000 l = builtin_d2l((double) a);
2007 if (a > 9223372036854775807L)
2008 return 9223372036854775807L;
2009 if (a < (-9223372036854775808L))
2010 return (-9223372036854775808L);
2015 f = copysignf((float) 1.0, a);
2017 return 9223372036854775807L;
2018 return (-9223372036854775808L); */
2020 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2023 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2024 s4 builtin_d2i(double a)
2029 if (a >= 2147483647)
2031 if (a <= (-2147483647-1))
2032 return (-2147483647-1);
2037 d = copysign(1.0, a);
2040 return (-2147483647-1);
2042 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2045 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2046 s8 builtin_d2l(double a)
2051 if (a >= 9223372036854775807LL)
2052 return 9223372036854775807LL;
2053 if (a <= (-9223372036854775807LL-1))
2054 return (-9223372036854775807LL-1);
2059 d = copysign(1.0, a);
2061 return 9223372036854775807LL;
2062 return (-9223372036854775807LL-1);
2064 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2067 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2068 double builtin_f2d(float a)
2070 if (finitef(a)) return (double) a;
2073 return longBitsToDouble(DBL_NAN);
2075 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2079 float builtin_d2f(double a)
2085 return intBitsToFloat(FLT_NAN);
2087 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2090 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2093 /*============================================================================*/
2094 /* AUTOMATICALLY REPLACED FUNCTIONS */
2095 /*============================================================================*/
2097 /* builtin_arraycopy ***********************************************************
2099 Builtin for java.lang.System.arraycopy.
2101 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2103 *******************************************************************************/
2105 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2106 java_handle_t *dest, s4 destStart, s4 len)
2108 arraydescriptor *sdesc;
2109 arraydescriptor *ddesc;
2112 if ((src == NULL) || (dest == NULL)) {
2113 exceptions_throw_nullpointerexception();
2117 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2118 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2120 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2121 exceptions_throw_arraystoreexception();
2125 /* we try to throw exception with the same message as SUN does */
2127 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2128 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2129 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2130 exceptions_throw_arrayindexoutofboundsexception();
2134 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2135 /* We copy primitive values or references of exactly the same type */
2137 s4 dataoffset = sdesc->dataoffset;
2138 s4 componentsize = sdesc->componentsize;
2140 LLNI_CRITICAL_START;
2142 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2143 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2144 u1, (size_t) len * componentsize);
2149 /* We copy references of different type */
2151 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2152 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2154 if (destStart <= srcStart) {
2155 for (i = 0; i < len; i++) {
2158 o = array_objectarray_element_get(oas, srcStart + i);
2160 if (!builtin_canstore(oad, o))
2163 array_objectarray_element_set(oad, destStart + i, o);
2167 /* XXX this does not completely obey the specification!
2168 If an exception is thrown only the elements above the
2169 current index have been copied. The specification
2170 requires that only the elements *below* the current
2171 index have been copied before the throw. */
2173 for (i = len - 1; i >= 0; i--) {
2176 o = array_objectarray_element_get(oas, srcStart + i);
2178 if (!builtin_canstore(oad, o))
2181 array_objectarray_element_set(oad, destStart + i, o);
2188 /* builtin_nanotime ************************************************************
2190 Return the current time in nanoseconds.
2192 *******************************************************************************/
2194 s8 builtin_nanotime(void)
2199 if (gettimeofday(&tv, NULL) == -1)
2200 vm_abort("gettimeofday failed: %s", strerror(errno));
2202 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2204 return usecs * 1000;
2208 /* builtin_currenttimemillis ***************************************************
2210 Return the current time in milliseconds.
2212 *******************************************************************************/
2214 s8 builtin_currenttimemillis(void)
2218 msecs = builtin_nanotime() / 1000 / 1000;
2224 /* builtin_clone ***************************************************************
2226 Function for cloning objects or arrays.
2228 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2230 *******************************************************************************/
2232 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2234 arraydescriptor *ad;
2237 java_handle_t *co; /* cloned object header */
2239 /* get the array descriptor */
2241 ad = LLNI_vftbl_direct(o)->arraydesc;
2243 /* we are cloning an array */
2246 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2248 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2253 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2254 /* XXX this is only a dirty hack to make Boehm work with handles */
2256 co = LLNI_WRAP((java_object_t *) co);
2259 LLNI_CRITICAL_START;
2261 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2263 #if defined(ENABLE_GC_CACAO)
2264 heap_init_objectheader(LLNI_DIRECT(co), size);
2267 #if defined(ENABLE_THREADS)
2268 lock_init_object_lock(LLNI_DIRECT(co));
2276 /* we are cloning a non-array */
2278 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2279 exceptions_throw_clonenotsupportedexception();
2283 /* get the class of the object */
2285 LLNI_class_get(o, c);
2287 /* create new object */
2289 co = builtin_new(c);
2294 LLNI_CRITICAL_START;
2296 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2298 #if defined(ENABLE_GC_CACAO)
2299 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2302 #if defined(ENABLE_THREADS)
2303 lock_init_object_lock(LLNI_DIRECT(co));
2312 #if defined(ENABLE_CYCLES_STATS)
2313 void builtin_print_cycles_stats(FILE *file)
2315 fprintf(file,"builtin cylce count statistics:\n");
2317 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2318 CYCLES_STATS_PRINT(builtin_new ,file);
2322 #endif /* defined(ENABLE_CYCLES_STATS) */
2325 #if defined(ENABLE_VMLOG)
2327 #include <vmlog_cacao.c>
2332 * These are local overrides for various environment variables in Emacs.
2333 * Please do not remove this and leave it at the end of the file, where
2334 * Emacs will automagically detect them.
2335 * ---------------------------------------------------------------------
2338 * indent-tabs-mode: t
2342 * vim:noexpandtab:sw=4:ts=4: