1 /* src/vm/jit/builtin.cpp - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Contains C functions for JavaVM Instructions that cannot be
24 translated to machine language directly. Consequently, the
25 generated machine code for these instructions contains function
26 calls instead of machine instructions, using the C calling
45 #include "fdlibm/fdlibm.h"
46 #if defined(__CYGWIN__) && defined(Bias)
51 #include "mm/memory.hpp"
53 #include "native/llni.h"
55 #include "threads/lock.hpp"
56 #include "threads/mutex.hpp"
57 #include "threads/thread.hpp"
59 #include "toolbox/logging.hpp"
60 #include "toolbox/util.h"
62 #include "vm/array.hpp"
63 #include "vm/jit/builtin.hpp"
64 #include "vm/class.hpp"
65 #include "vm/cycles-stats.h"
66 #include "vm/exceptions.hpp"
67 #include "vm/global.h"
68 #include "vm/globals.hpp"
69 #include "vm/initialize.hpp"
70 #include "vm/linker.hpp"
71 #include "vm/loader.hpp"
72 #include "vm/options.h"
73 #include "vm/primitive.hpp"
74 #include "vm/rt-timing.h"
75 #include "vm/string.hpp"
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/emit-common.hpp"
79 #include "vm/jit/stubs.hpp"
80 #include "vm/jit/trace.hpp"
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
87 /* include builtin tables *****************************************************/
89 #include "vm/jit/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;
110 builtintable_entry *bte;
113 // Create new dump memory area.
116 /* create a new descriptor pool */
118 descpool = descriptor_pool_new(class_java_lang_Object);
120 /* add some entries we need */
122 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
125 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
128 /* first add all descriptors to the pool */
130 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
131 bte->name = utf_new_char(bte->cname);
132 bte->descriptor = utf_new_char(bte->cdescriptor);
134 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
138 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
139 bte->descriptor = utf_new_char(bte->cdescriptor);
141 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
145 for (bte = builtintable_function; bte->fp != NULL; bte++) {
146 bte->classname = utf_new_char(bte->cclassname);
147 bte->name = utf_new_char(bte->cname);
148 bte->descriptor = utf_new_char(bte->cdescriptor);
150 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
154 /* create the class reference table */
156 (void) descriptor_pool_create_classrefs(descpool, NULL);
158 /* allocate space for the parsed descriptors */
160 descriptor_pool_alloc_parsed_descriptors(descpool);
162 /* Now parse all descriptors. NOTE: builtin-functions are treated
163 like static methods (no `this' pointer). */
165 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
167 descriptor_pool_parse_method_descriptor(descpool,
169 ACC_STATIC | ACC_METHOD_BUILTIN,
172 /* generate a builtin stub if we need one */
174 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
175 m = method_new_builtin(bte);
176 BuiltinStub::generate(m, bte);
180 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
182 descriptor_pool_parse_method_descriptor(descpool,
184 ACC_STATIC | ACC_METHOD_BUILTIN,
187 /* no stubs should be needed for this table */
189 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
192 for (bte = builtintable_function; bte->fp != NULL; bte++) {
194 descriptor_pool_parse_method_descriptor(descpool,
196 ACC_STATIC | ACC_METHOD_BUILTIN,
199 /* generate a builtin stub if we need one */
201 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
202 m = method_new_builtin(bte);
203 BuiltinStub::generate(m, bte);
211 /* builtintable_comparator *****************************************************
213 qsort comparator for the automatic builtin table.
215 *******************************************************************************/
217 static int builtintable_comparator(const void *a, const void *b)
219 builtintable_entry *bte1;
220 builtintable_entry *bte2;
222 bte1 = (builtintable_entry *) a;
223 bte2 = (builtintable_entry *) b;
225 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
229 /* builtintable_sort_automatic *************************************************
231 Sorts the automatic builtin table.
233 *******************************************************************************/
235 static void builtintable_sort_automatic(void)
239 /* calculate table size statically (`- 1' comment see builtintable.inc) */
241 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
243 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
244 builtintable_comparator);
248 /* builtin_init ****************************************************************
250 Initialize the global table of builtin functions.
252 *******************************************************************************/
254 bool builtin_init(void)
256 TRACESUBSYSTEMINITIALIZATION("builtin_init");
258 /* initialize the builtin tables */
260 if (!builtintable_init())
263 /* sort builtin tables */
265 builtintable_sort_automatic();
271 /* builtintable_get_internal ***************************************************
273 Finds an entry in the builtintable for internal functions and
274 returns the a pointer to the structure.
276 *******************************************************************************/
278 builtintable_entry *builtintable_get_internal(functionptr fp)
280 builtintable_entry *bte;
282 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
291 /* builtintable_get_automatic **************************************************
293 Finds an entry in the builtintable for functions which are replaced
294 automatically and returns the a pointer to the structure.
296 *******************************************************************************/
298 builtintable_entry *builtintable_get_automatic(s4 opcode)
300 builtintable_entry *first;
301 builtintable_entry *last;
302 builtintable_entry *middle;
306 /* calculate table size statically (`- 1' comment see builtintable.inc) */
308 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
310 first = builtintable_automatic;
311 last = builtintable_automatic + entries;
313 while (entries > 0) {
315 middle = first + half;
317 if (middle->opcode < opcode) {
325 return (first != last ? first : NULL);
329 /* builtintable_replace_function ***********************************************
333 *******************************************************************************/
335 #if defined(ENABLE_JIT)
336 bool builtintable_replace_function(void *iptr_)
339 builtintable_entry *bte;
342 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
344 /* get name and descriptor of the function */
347 case ICMD_INVOKESTATIC:
348 /* The instruction MUST be resolved, otherwise we run into
349 lazy loading troubles. Anyway, we should/can only replace
350 very VM-close functions. */
352 if (INSTRUCTION_IS_UNRESOLVED(iptr))
355 mr = iptr->sx.s23.s3.fmiref;
362 /* search the function table */
364 for (bte = builtintable_function; bte->fp != NULL; bte++) {
365 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
366 (mr->name == bte->name) &&
367 (mr->descriptor == bte->descriptor)) {
369 /* set the values in the instruction */
371 iptr->opc = bte->opcode;
372 iptr->sx.s23.s3.bte = bte;
374 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
375 iptr->flags.bits |= INS_FLAG_CHECK;
377 iptr->flags.bits &= ~INS_FLAG_CHECK;
385 #endif /* defined(ENABLE_JIT) */
388 /*============================================================================*/
389 /* INTERNAL BUILTIN FUNCTIONS */
390 /*============================================================================*/
392 /* builtin_instanceof **********************************************************
394 Checks if an object is an instance of some given class (or subclass
395 of that class). If class is an interface, checks if the interface
399 1......o is an instance of class or implements the interface
400 0......otherwise or if o == NULL
402 NOTE: This builtin can be called from NATIVE code only.
404 *******************************************************************************/
406 bool builtin_instanceof(java_handle_t *o, classinfo *c)
413 LLNI_class_get(o, oc);
415 return class_isanysubclass(oc, c);
420 /* builtin_checkcast ***********************************************************
422 The same as builtin_instanceof but with the exception
423 that 1 is returned when (o == NULL).
425 NOTE: This builtin can be called from NATIVE code only.
427 *******************************************************************************/
429 bool builtin_checkcast(java_handle_t *o, classinfo *c)
436 LLNI_class_get(o, oc);
438 if (class_isanysubclass(oc, c))
445 /* builtin_arraycheckcast ******************************************************
447 Checks if an object is really a subtype of the requested array
448 type. The object has to be an array to begin with. For simple
449 arrays (int, short, double, etc.) the types have to match exactly.
450 For arrays of objects, the type of elements in the array has to be
451 a subtype (or the same type) of the requested element type. For
452 arrays of arrays (which in turn can again be arrays of arrays), the
453 types at the lowest level have to satisfy the corresponding sub
456 NOTE: This is a FAST builtin and can be called from JIT code only.
458 *******************************************************************************/
460 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
462 arraydescriptor *desc;
467 desc = o->vftbl->arraydesc;
472 return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
476 /* builtin_fast_arrayinstanceof ************************************************
478 NOTE: This is a FAST builtin and can be called from JIT code only.
480 *******************************************************************************/
482 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
487 return builtin_fast_arraycheckcast(o, targetclass);
491 /* builtin_arrayinstanceof *****************************************************
493 NOTE: This builtin can be called from NATIVE code only.
495 *******************************************************************************/
497 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
503 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
511 /* builtin_throw_exception *****************************************************
513 Sets the exception pointer with the thrown exception and prints some
514 debugging information.
516 NOTE: This is a FAST builtin and can be called from JIT code,
517 or from asm_vm_call_method.
519 *******************************************************************************/
521 void *builtin_throw_exception(java_object_t *xptr)
524 /* print exception trace */
526 if (opt_TraceExceptions)
527 trace_exception_builtin(xptr);
528 #endif /* !defined(NDEBUG) */
530 /* actually set the exception */
532 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
534 /* Return a NULL pointer. This is required for vm_call_method to
535 check for an exception. This is for convenience. */
541 /* builtin_retrieve_exception **************************************************
543 Gets and clears the exception pointer of the current thread.
546 the exception object, or NULL if no exception was thrown.
548 NOTE: This is a FAST builtin and can be called from JIT code,
549 or from the signal handlers.
551 *******************************************************************************/
553 java_object_t *builtin_retrieve_exception(void)
558 /* actually get and clear the exception */
560 h = exceptions_get_and_clear_exception();
567 /* builtin_canstore ************************************************************
569 Checks, if an object can be stored in an array.
573 0......otherwise (throws an ArrayStoreException)
575 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
577 *******************************************************************************/
579 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
585 result = builtin_fast_canstore((java_objectarray_t*) LLNI_DIRECT(oa), LLNI_UNWRAP(o));
589 /* if not possible, throw an exception */
592 exceptions_throw_arraystoreexception();
598 /* fast_subtype_check **********************************************************
600 Checks if s is a subtype of t, using both the restricted subtype relation
601 and the overflow array (see Cliff Click and John Rose: Fast subtype checking
605 1......s is a subtype of t.
608 *******************************************************************************/
610 bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
612 if (s->subtype_display[t->subtype_depth] == t)
614 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
616 return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
620 /* builtin_fast_canstore *******************************************************
622 Checks, if an object can be stored in an array.
626 0......otherwise (no exception thrown!)
628 NOTE: This is a FAST builtin and can be called from JIT code only.
630 *******************************************************************************/
632 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
634 arraydescriptor *desc;
635 arraydescriptor *valuedesc;
636 vftbl_t *componentvftbl;
644 /* The following is guaranteed (by verifier checks):
646 * *) oa->...vftbl->arraydesc != NULL
647 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
648 * *) o->vftbl is not an interface vftbl
651 desc = oa->header.objheader.vftbl->arraydesc;
652 componentvftbl = desc->componentvftbl;
653 valuevftbl = o->vftbl;
654 valuedesc = valuevftbl->arraydesc;
656 if ((desc->dimension - 1) == 0) {
657 /* {oa is a one-dimensional array} */
658 /* {oa is an array of references} */
660 if (valuevftbl == componentvftbl)
663 LOCK_CLASSRENUMBER_LOCK;
665 baseval = componentvftbl->baseval;
668 /* an array of interface references */
670 result = ((valuevftbl->interfacetablelength > -baseval) &&
671 (valuevftbl->interfacetable[baseval] != NULL));
675 result = fast_subtype_check(valuevftbl, componentvftbl);
677 uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
678 result = diffval <= (uint32_t) componentvftbl->diffval;
682 UNLOCK_CLASSRENUMBER_LOCK;
684 else if (valuedesc == NULL) {
685 /* {oa has dimension > 1} */
686 /* {componentvftbl->arraydesc != NULL} */
688 /* check if o is an array */
693 /* {o is an array} */
695 result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
704 /* This is an optimized version where a is guaranteed to be one-dimensional */
705 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
707 arraydescriptor *desc;
708 vftbl_t *elementvftbl;
716 /* The following is guaranteed (by verifier checks):
718 * *) a->...vftbl->arraydesc != NULL
719 * *) a->...vftbl->arraydesc->elementvftbl != NULL
720 * *) a->...vftbl->arraydesc->dimension == 1
721 * *) o->vftbl is not an interface vftbl
724 desc = a->header.objheader.vftbl->arraydesc;
725 elementvftbl = desc->elementvftbl;
726 valuevftbl = o->vftbl;
728 /* {a is a one-dimensional array} */
730 if (valuevftbl == elementvftbl)
733 LOCK_CLASSRENUMBER_LOCK;
735 baseval = elementvftbl->baseval;
738 /* an array of interface references */
739 result = ((valuevftbl->interfacetablelength > -baseval) &&
740 (valuevftbl->interfacetable[baseval] != NULL));
744 result = fast_subtype_check(valuevftbl, elementvftbl);
746 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
747 result = diffval <= (uint32_t) elementvftbl->diffval;
751 UNLOCK_CLASSRENUMBER_LOCK;
757 /* This is an optimized version where a is guaranteed to be a
758 * one-dimensional array of a class type */
759 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
761 vftbl_t *elementvftbl;
768 /* The following is guaranteed (by verifier checks):
770 * *) a->...vftbl->arraydesc != NULL
771 * *) a->...vftbl->arraydesc->elementvftbl != NULL
772 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
773 * *) a->...vftbl->arraydesc->dimension == 1
774 * *) o->vftbl is not an interface vftbl
777 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
778 valuevftbl = o->vftbl;
780 /* {a is a one-dimensional array} */
782 if (valuevftbl == elementvftbl)
785 LOCK_CLASSRENUMBER_LOCK;
788 result = fast_subtype_check(valuevftbl, elementvftbl);
790 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
791 result = diffval <= (uint32_t) elementvftbl->diffval;
794 UNLOCK_CLASSRENUMBER_LOCK;
800 /* builtin_new *****************************************************************
802 Creates a new instance of class c on the heap.
805 pointer to the object, or NULL if no memory is available
807 NOTE: This builtin can be called from NATIVE code only.
809 *******************************************************************************/
811 java_handle_t *builtin_new(classinfo *c)
814 #if defined(ENABLE_RT_TIMING)
815 struct timespec time_start, time_end;
817 #if defined(ENABLE_CYCLES_STATS)
818 u8 cycles_start, cycles_end;
821 RT_TIMING_GET_TIME(time_start);
822 CYCLES_STATS_GET(cycles_start);
824 /* is the class loaded */
826 assert(c->state & CLASS_LOADED);
828 /* check if we can instantiate this class */
830 if (c->flags & ACC_ABSTRACT) {
831 exceptions_throw_instantiationerror(c);
835 /* is the class linked */
837 if (!(c->state & CLASS_LINKED))
841 if (!(c->state & CLASS_INITIALIZED)) {
844 log_message_class("Initialize class (from builtin_new): ", c);
847 if (!initialize_class(c))
851 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
857 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
858 /* XXX this is only a dirty hack to make Boehm work with handles */
860 o = LLNI_WRAP((java_object_t *) o);
863 LLNI_vftbl_direct(o) = c->vftbl;
865 #if defined(ENABLE_THREADS)
866 Lockword(LLNI_DIRECT(o)->lockword).init();
869 CYCLES_STATS_GET(cycles_end);
870 RT_TIMING_GET_TIME(time_end);
872 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
873 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
878 #if defined(ENABLE_ESCAPE_REASON)
879 java_handle_t *builtin_escape_reason_new(classinfo *c) {
880 print_escape_reasons();
881 return builtin_java_new(c);
885 #if defined(ENABLE_TLH)
886 java_handle_t *builtin_tlh_new(classinfo *c)
889 # if defined(ENABLE_RT_TIMING)
890 struct timespec time_start, time_end;
892 # if defined(ENABLE_CYCLES_STATS)
893 u8 cycles_start, cycles_end;
896 RT_TIMING_GET_TIME(time_start);
897 CYCLES_STATS_GET(cycles_start);
899 /* is the class loaded */
901 assert(c->state & CLASS_LOADED);
903 /* check if we can instantiate this class */
905 if (c->flags & ACC_ABSTRACT) {
906 exceptions_throw_instantiationerror(c);
910 /* is the class linked */
912 if (!(c->state & CLASS_LINKED))
916 if (!(c->state & CLASS_INITIALIZED)) {
917 # if !defined(NDEBUG)
919 log_message_class("Initialize class (from builtin_new): ", c);
922 if (!initialize_class(c))
927 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
932 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
939 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
940 /* XXX this is only a dirty hack to make Boehm work with handles */
942 o = LLNI_WRAP((java_object_t *) o);
945 LLNI_vftbl_direct(o) = c->vftbl;
947 # if defined(ENABLE_THREADS)
948 Lockword(LLNI_DIRECT(o)->lockword).init();
951 CYCLES_STATS_GET(cycles_end);
952 RT_TIMING_GET_TIME(time_end);
955 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
956 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
964 /* builtin_java_new ************************************************************
966 NOTE: This is a SLOW builtin and can be called from JIT code only.
968 *******************************************************************************/
970 java_handle_t *builtin_java_new(java_handle_t *clazz)
972 return builtin_new(LLNI_classinfo_unwrap(clazz));
976 /* builtin_fast_new ************************************************************
978 Creates a new instance of class c on the heap.
981 pointer to the object, or NULL if no fast return
982 is possible for any reason.
984 NOTE: This is a FAST builtin and can be called from JIT code only.
986 *******************************************************************************/
988 java_object_t *builtin_fast_new(classinfo *c)
991 #if defined(ENABLE_RT_TIMING)
992 struct timespec time_start, time_end;
994 #if defined(ENABLE_CYCLES_STATS)
995 u8 cycles_start, cycles_end;
998 RT_TIMING_GET_TIME(time_start);
999 CYCLES_STATS_GET(cycles_start);
1001 /* is the class loaded */
1003 assert(c->state & CLASS_LOADED);
1005 /* check if we can instantiate this class */
1007 if (c->flags & ACC_ABSTRACT)
1010 /* is the class linked */
1012 if (!(c->state & CLASS_LINKED))
1015 if (!(c->state & CLASS_INITIALIZED))
1018 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1019 c->finalizer, false);
1024 o->vftbl = c->vftbl;
1026 #if defined(ENABLE_THREADS)
1027 Lockword(LLNI_DIRECT(o)->lockword).init();
1030 CYCLES_STATS_GET(cycles_end);
1031 RT_TIMING_GET_TIME(time_end);
1033 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1034 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1040 /* builtin_java_newarray *******************************************************
1042 Creates an array with the given vftbl on the heap. This function
1043 takes as class argument an array class.
1046 pointer to the array or NULL if no memory is available
1048 NOTE: This is a SLOW builtin and can be called from JIT code only.
1050 *******************************************************************************/
1052 java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1054 #if defined(ENABLE_RT_TIMING)
1055 struct timespec time_start, time_end;
1058 RT_TIMING_GET_TIME(time_start);
1060 classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
1062 // Allocate a new array with given size and class on the heap
1063 Array a(size, arrayclass);
1065 RT_TIMING_GET_TIME(time_end);
1066 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1068 return a.get_handle();
1072 /* builtin_newarray_type ****************************************************
1074 Creates an array of [type]s on the heap.
1077 pointer to the array or NULL if no memory is available
1079 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1081 *******************************************************************************/
1083 #define BUILTIN_NEWARRAY_TYPE(type, name) \
1084 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1086 name##Array a(size); \
1087 return a.get_handle(); \
1090 BUILTIN_NEWARRAY_TYPE(boolean, Boolean)
1091 BUILTIN_NEWARRAY_TYPE(byte, Byte)
1092 BUILTIN_NEWARRAY_TYPE(char, Char)
1093 BUILTIN_NEWARRAY_TYPE(short, Short)
1094 BUILTIN_NEWARRAY_TYPE(int, Int)
1095 BUILTIN_NEWARRAY_TYPE(long, Long)
1096 BUILTIN_NEWARRAY_TYPE(float, Float)
1097 BUILTIN_NEWARRAY_TYPE(double, Double)
1100 /* builtin_multianewarray_intern ***********************************************
1102 Creates a multi-dimensional array on the heap. The dimensions are
1103 passed in an array of longs.
1106 n.............number of dimensions to create
1107 arrayclass....the array class
1108 dims..........array containing the size of each dimension to create
1111 pointer to the array or NULL if no memory is available
1113 ******************************************************************************/
1115 static java_handle_array_t *builtin_multianewarray_intern(int n,
1116 classinfo *arrayclass,
1121 /* create this dimension */
1123 int32_t size = (int32_t) dims[0];
1124 Array a(size, arrayclass);
1129 /* if this is the last dimension return */
1132 return a.get_handle();
1134 /* get the class of the components to create */
1136 classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1138 /* The verifier guarantees that the dimension count is in the range. */
1140 /* create the component arrays */
1142 ObjectArray oa(a.get_handle());
1144 for (i = 0; i < size; i++) {
1145 java_handle_array_t *ea =
1146 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1147 /* we save an s4 to a s8 slot, 8-byte aligned */
1149 builtin_multianewarray_intern(n, componentclass, dims + 2);
1151 builtin_multianewarray_intern(n, componentclass, dims + 1);
1157 oa.set_element(i, (java_handle_t*) ea);
1160 return a.get_handle();
1164 /* builtin_multianewarray ******************************************************
1166 Wrapper for builtin_multianewarray_intern which checks all
1167 dimensions before we start allocating.
1169 NOTE: This is a SLOW builtin and can be called from JIT code only.
1171 ******************************************************************************/
1173 java_handle_objectarray_t *builtin_multianewarray(int n,
1174 java_handle_t *arrayclazz,
1181 /* check all dimensions before doing anything */
1183 for (i = 0; i < n; i++) {
1184 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1185 /* we save an s4 to a s8 slot, 8-byte aligned */
1186 size = (s4) dims[i * 2];
1188 size = (s4) dims[i];
1192 exceptions_throw_negativearraysizeexception();
1197 c = LLNI_classinfo_unwrap(arrayclazz);
1199 /* now call the real function */
1201 return (java_handle_objectarray_t *)
1202 builtin_multianewarray_intern(n, c, dims);
1206 /* builtin_verbosecall_enter ***************************************************
1208 Print method call with arguments for -verbose:call.
1210 XXX: Remove mew once all archs use the new tracer!
1212 *******************************************************************************/
1214 #if !defined(NDEBUG)
1215 #ifdef TRACE_ARGS_NUM
1216 void builtin_verbosecall_enter(s8 a0, s8 a1,
1217 # if TRACE_ARGS_NUM >= 4
1220 # if TRACE_ARGS_NUM >= 6
1223 # if TRACE_ARGS_NUM == 8
1228 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1231 #endif /* !defined(NDEBUG) */
1234 /* builtin_verbosecall_exit ****************************************************
1236 Print method exit for -verbose:call.
1238 XXX: Remove mew once all archs use the new tracer!
1240 *******************************************************************************/
1242 #if !defined(NDEBUG)
1243 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1245 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1247 #endif /* !defined(NDEBUG) */
1250 /*============================================================================*/
1251 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1252 /*============================================================================*/
1254 /*********** Functions for integer divisions *****************************
1256 On some systems (eg. DEC ALPHA), integer division is not supported by the
1257 CPU. These helper functions implement the missing functionality.
1259 ******************************************************************************/
1261 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1262 s4 builtin_idiv(s4 a, s4 b)
1271 s4 builtin_irem(s4 a, s4 b)
1279 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1282 /* functions for long arithmetics **********************************************
1284 On systems where 64 bit Integers are not supported by the CPU,
1285 these functions are needed.
1287 ******************************************************************************/
1289 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1290 s8 builtin_ladd(s8 a, s8 b)
1299 s8 builtin_lsub(s8 a, s8 b)
1308 s8 builtin_lneg(s8 a)
1316 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1319 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1320 s8 builtin_lmul(s8 a, s8 b)
1328 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1331 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1332 s8 builtin_ldiv(s8 a, s8 b)
1341 s8 builtin_lrem(s8 a, s8 b)
1349 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1352 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1353 s8 builtin_lshl(s8 a, s4 b)
1362 s8 builtin_lshr(s8 a, s4 b)
1371 s8 builtin_lushr(s8 a, s4 b)
1375 c = ((u8) a) >> (b & 63);
1379 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1382 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1383 s8 builtin_land(s8 a, s8 b)
1392 s8 builtin_lor(s8 a, s8 b)
1401 s8 builtin_lxor(s8 a, s8 b)
1409 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1412 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1413 s4 builtin_lcmp(s8 a, s8 b)
1423 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1426 /* functions for unsupported floating instructions ****************************/
1428 /* used to convert FLT_xxx defines into float values */
1430 static inline float intBitsToFloat(s4 i)
1439 /* used to convert DBL_xxx defines into double values */
1441 static inline float longBitsToDouble(s8 l)
1451 float builtin_fadd(float a, float b)
1453 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1454 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1465 if (copysignf(1.0, a) == copysignf(1.0, b))
1468 return intBitsToFloat(FLT_NAN);
1474 float builtin_fsub(float a, float b)
1476 return builtin_fadd(a, builtin_fneg(b));
1480 float builtin_fmul(float a, float b)
1482 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1483 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1485 if (finitef(b)) return a * b;
1487 if (a == 0) return intBitsToFloat(FLT_NAN);
1488 else return copysignf(b, copysignf(1.0, b)*a);
1493 if (b == 0) return intBitsToFloat(FLT_NAN);
1494 else return copysignf(a, copysignf(1.0, a)*b);
1497 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1503 /* builtin_ddiv ****************************************************************
1505 Implementation as described in VM Spec.
1507 *******************************************************************************/
1509 float builtin_fdiv(float a, float b)
1513 /* If neither value1' nor value2' is NaN, the sign of the result */
1514 /* is positive if both values have the same sign, negative if the */
1515 /* values have different signs. */
1521 /* If either value1' or value2' is NaN, the result is NaN. */
1523 return intBitsToFloat(FLT_NAN);
1526 /* Division of a finite value by an infinity results in a */
1527 /* signed zero, with the sign-producing rule just given. */
1529 /* is sign equal? */
1531 if (copysignf(1.0, a) == copysignf(1.0, b))
1540 /* If either value1' or value2' is NaN, the result is NaN. */
1542 return intBitsToFloat(FLT_NAN);
1544 } else if (finitef(b)) {
1545 /* Division of an infinity by a finite value results in a signed */
1546 /* infinity, with the sign-producing rule just given. */
1548 /* is sign equal? */
1550 if (copysignf(1.0, a) == copysignf(1.0, b))
1551 return intBitsToFloat(FLT_POSINF);
1553 return intBitsToFloat(FLT_NEGINF);
1556 /* Division of an infinity by an infinity results in NaN. */
1558 return intBitsToFloat(FLT_NAN);
1564 float builtin_fneg(float a)
1566 if (isnanf(a)) return a;
1568 if (finitef(a)) return -a;
1569 else return copysignf(a, -copysignf(1.0, a));
1572 #endif /* !SUPPORT_FLOAT */
1575 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1576 s4 builtin_fcmpl(float a, float b)
1584 if (!finitef(a) || !finitef(b)) {
1585 a = finitef(a) ? 0 : copysignf(1.0, a);
1586 b = finitef(b) ? 0 : copysignf(1.0, b);
1599 s4 builtin_fcmpg(float a, float b)
1601 if (isnanf(a)) return 1;
1602 if (isnanf(b)) return 1;
1603 if (!finitef(a) || !finitef(b)) {
1604 a = finitef(a) ? 0 : copysignf(1.0, a);
1605 b = finitef(b) ? 0 : copysignf(1.0, b);
1607 if (a > b) return 1;
1608 if (a == b) return 0;
1611 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1614 float builtin_frem(float a, float b)
1620 /* functions for unsupported double instructions ******************************/
1623 double builtin_dadd(double a, double b)
1625 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1626 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1628 if (finite(b)) return a + b;
1632 if (finite(b)) return a;
1634 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1635 else return longBitsToDouble(DBL_NAN);
1641 double builtin_dsub(double a, double b)
1643 return builtin_dadd(a, builtin_dneg(b));
1647 double builtin_dmul(double a, double b)
1649 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1650 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1652 if (finite(b)) return a * b;
1654 if (a == 0) return longBitsToDouble(DBL_NAN);
1655 else return copysign(b, copysign(1.0, b) * a);
1660 if (b == 0) return longBitsToDouble(DBL_NAN);
1661 else return copysign(a, copysign(1.0, a) * b);
1664 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1670 /* builtin_ddiv ****************************************************************
1672 Implementation as described in VM Spec.
1674 *******************************************************************************/
1676 double builtin_ddiv(double a, double b)
1680 /* If neither value1' nor value2' is NaN, the sign of the result */
1681 /* is positive if both values have the same sign, negative if the */
1682 /* values have different signs. */
1688 /* If either value1' or value2' is NaN, the result is NaN. */
1690 return longBitsToDouble(DBL_NAN);
1693 /* Division of a finite value by an infinity results in a */
1694 /* signed zero, with the sign-producing rule just given. */
1696 /* is sign equal? */
1698 if (copysign(1.0, a) == copysign(1.0, b))
1707 /* If either value1' or value2' is NaN, the result is NaN. */
1709 return longBitsToDouble(DBL_NAN);
1711 } else if (finite(b)) {
1712 /* Division of an infinity by a finite value results in a signed */
1713 /* infinity, with the sign-producing rule just given. */
1715 /* is sign equal? */
1717 if (copysign(1.0, a) == copysign(1.0, b))
1718 return longBitsToDouble(DBL_POSINF);
1720 return longBitsToDouble(DBL_NEGINF);
1723 /* Division of an infinity by an infinity results in NaN. */
1725 return longBitsToDouble(DBL_NAN);
1731 /* builtin_dneg ****************************************************************
1733 Implemented as described in VM Spec.
1735 *******************************************************************************/
1737 double builtin_dneg(double a)
1740 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1747 /* If the operand is a zero, the result is the zero of opposite */
1753 /* If the operand is an infinity, the result is the infinity of */
1754 /* opposite sign. */
1756 return copysign(a, -copysign(1.0, a));
1760 #endif /* !SUPPORT_DOUBLE */
1763 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1764 s4 builtin_dcmpl(double a, double b)
1772 if (!finite(a) || !finite(b)) {
1773 a = finite(a) ? 0 : copysign(1.0, a);
1774 b = finite(b) ? 0 : copysign(1.0, b);
1787 s4 builtin_dcmpg(double a, double b)
1795 if (!finite(a) || !finite(b)) {
1796 a = finite(a) ? 0 : copysign(1.0, a);
1797 b = finite(b) ? 0 : copysign(1.0, b);
1808 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1811 double builtin_drem(double a, double b)
1817 /* conversion operations ******************************************************/
1819 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1820 float builtin_i2f(s4 a)
1822 float f = (float) a;
1825 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1828 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1829 double builtin_i2d(s4 a)
1831 double d = (double) a;
1834 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1837 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1838 float builtin_l2f(s8 a)
1840 float f = (float) a;
1843 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1846 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1847 double builtin_l2d(s8 a)
1849 double d = (double) a;
1852 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1855 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1856 s4 builtin_f2i(float a)
1860 i = builtin_d2i((double) a);
1871 if (a < (-2147483648))
1872 return (-2147483648);
1875 f = copysignf((float) 1.0, a);
1878 return (-2147483648); */
1880 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1883 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1884 s8 builtin_f2l(float a)
1888 l = builtin_d2l((double) a);
1895 if (a > 9223372036854775807L)
1896 return 9223372036854775807L;
1897 if (a < (-9223372036854775808L))
1898 return (-9223372036854775808L);
1903 f = copysignf((float) 1.0, a);
1905 return 9223372036854775807L;
1906 return (-9223372036854775808L); */
1908 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
1911 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1912 s4 builtin_d2i(double a)
1917 if (a >= 2147483647)
1919 if (a <= (-2147483647-1))
1920 return (-2147483647-1);
1925 d = copysign(1.0, a);
1928 return (-2147483647-1);
1930 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1933 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
1934 s8 builtin_d2l(double a)
1939 if (a >= 9223372036854775807LL)
1940 return 9223372036854775807LL;
1941 if (a <= (-9223372036854775807LL-1))
1942 return (-9223372036854775807LL-1);
1947 d = copysign(1.0, a);
1949 return 9223372036854775807LL;
1950 return (-9223372036854775807LL-1);
1952 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
1955 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
1956 double builtin_f2d(float a)
1958 if (finitef(a)) return (double) a;
1961 return longBitsToDouble(DBL_NAN);
1963 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1967 float builtin_d2f(double a)
1973 return intBitsToFloat(FLT_NAN);
1975 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1978 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
1981 /*============================================================================*/
1982 /* AUTOMATICALLY REPLACED FUNCTIONS */
1983 /*============================================================================*/
1985 /* builtin_arraycopy ***********************************************************
1987 Builtin for java.lang.System.arraycopy.
1989 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1991 *******************************************************************************/
1993 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
1994 java_handle_t *dest, s4 destStart, s4 len)
1996 arraydescriptor *sdesc;
1997 arraydescriptor *ddesc;
2000 if ((src == NULL) || (dest == NULL)) {
2001 exceptions_throw_nullpointerexception();
2008 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2009 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2011 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2012 exceptions_throw_arraystoreexception();
2016 // Check if offsets and length are positive.
2017 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2018 exceptions_throw_arrayindexoutofboundsexception();
2022 // Check if ranges are valid.
2023 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) sa.get_length()) ||
2024 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) {
2025 exceptions_throw_arrayindexoutofboundsexception();
2034 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2035 /* We copy primitive values or references of exactly the same type */
2037 s4 dataoffset = sdesc->dataoffset;
2038 s4 componentsize = sdesc->componentsize;
2040 LLNI_CRITICAL_START;
2042 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2043 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2044 u1, (size_t) len * componentsize);
2049 /* We copy references of different type */
2051 ObjectArray oas((java_handle_objectarray_t*) src);
2052 ObjectArray oad((java_handle_objectarray_t*) dest);
2054 if (destStart <= srcStart) {
2055 for (i = 0; i < len; i++) {
2056 java_handle_t* o = oas.get_element(srcStart + i);
2058 if (!builtin_canstore(oad.get_handle(), o))
2061 oad.set_element(destStart + i, o);
2065 /* XXX this does not completely obey the specification!
2066 If an exception is thrown only the elements above the
2067 current index have been copied. The specification
2068 requires that only the elements *below* the current
2069 index have been copied before the throw. */
2071 for (i = len - 1; i >= 0; i--) {
2072 java_handle_t* o = oas.get_element(srcStart + i);
2074 if (!builtin_canstore(oad.get_handle(), o))
2077 oad.set_element(destStart + i, o);
2084 /* builtin_nanotime ************************************************************
2086 Return the current time in nanoseconds.
2088 *******************************************************************************/
2090 s8 builtin_nanotime(void)
2095 if (gettimeofday(&tv, NULL) == -1)
2096 vm_abort("gettimeofday failed: %s", strerror(errno));
2098 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2100 return usecs * 1000;
2104 /* builtin_currenttimemillis ***************************************************
2106 Return the current time in milliseconds.
2108 *******************************************************************************/
2110 s8 builtin_currenttimemillis(void)
2114 msecs = builtin_nanotime() / 1000 / 1000;
2120 /* builtin_clone ***************************************************************
2122 Function for cloning objects or arrays.
2124 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2126 *******************************************************************************/
2128 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2130 arraydescriptor *ad;
2133 java_handle_t *co; /* cloned object header */
2135 /* get the array descriptor */
2137 ad = LLNI_vftbl_direct(o)->arraydesc;
2139 /* we are cloning an array */
2144 size = ad->dataoffset + ad->componentsize * a.get_length();
2146 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2151 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2152 /* XXX this is only a dirty hack to make Boehm work with handles */
2154 co = LLNI_WRAP((java_object_t *) co);
2157 LLNI_CRITICAL_START;
2159 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2161 #if defined(ENABLE_GC_CACAO)
2162 heap_init_objectheader(LLNI_DIRECT(co), size);
2165 #if defined(ENABLE_THREADS)
2166 Lockword(LLNI_DIRECT(co)->lockword).init();
2174 /* we are cloning a non-array */
2176 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2177 exceptions_throw_clonenotsupportedexception();
2181 /* get the class of the object */
2183 LLNI_class_get(o, c);
2185 /* create new object */
2187 co = builtin_new(c);
2192 LLNI_CRITICAL_START;
2194 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2196 #if defined(ENABLE_GC_CACAO)
2197 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2200 #if defined(ENABLE_THREADS)
2201 Lockword(LLNI_DIRECT(co)->lockword).init();
2210 #if defined(ENABLE_CYCLES_STATS)
2211 void builtin_print_cycles_stats(FILE *file)
2213 fprintf(file,"builtin cylce count statistics:\n");
2215 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2216 CYCLES_STATS_PRINT(builtin_new ,file);
2220 #endif /* defined(ENABLE_CYCLES_STATS) */
2223 #if defined(ENABLE_VMLOG)
2225 #include <vmlog_cacao.c>
2230 * These are local overrides for various environment variables in Emacs.
2231 * Please do not remove this and leave it at the end of the file, where
2232 * Emacs will automagically detect them.
2233 * ---------------------------------------------------------------------
2236 * indent-tabs-mode: t
2240 * vim:noexpandtab:sw=4:ts=4: