1 /* src/vm/jit/builtin.cpp - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007, 2008
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/stubs.hpp"
79 #include "vm/jit/trace.hpp"
81 #if defined(ENABLE_VMLOG)
82 #include <vmlog_cacao.h>
86 /* include builtin tables *****************************************************/
88 #include "vm/jit/builtintable.inc"
91 CYCLES_STATS_DECLARE(builtin_new ,100,5)
92 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
95 /*============================================================================*/
96 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
97 /*============================================================================*/
99 /* builtintable_init ***********************************************************
101 Parse the descriptors of builtin functions and create the parsed
104 *******************************************************************************/
106 static bool builtintable_init(void)
108 descriptor_pool *descpool;
109 builtintable_entry *bte;
112 // Create new dump memory area.
115 /* create a new descriptor pool */
117 descpool = descriptor_pool_new(class_java_lang_Object);
119 /* add some entries we need */
121 if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
124 if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
127 /* first add all descriptors to the pool */
129 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130 bte->name = utf_new_char(bte->cname);
131 bte->descriptor = utf_new_char(bte->cdescriptor);
133 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
137 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
138 bte->descriptor = utf_new_char(bte->cdescriptor);
140 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
144 for (bte = builtintable_function; bte->fp != NULL; bte++) {
145 bte->classname = utf_new_char(bte->cclassname);
146 bte->name = utf_new_char(bte->cname);
147 bte->descriptor = utf_new_char(bte->cdescriptor);
149 if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
153 /* create the class reference table */
155 (void) descriptor_pool_create_classrefs(descpool, NULL);
157 /* allocate space for the parsed descriptors */
159 descriptor_pool_alloc_parsed_descriptors(descpool);
161 /* Now parse all descriptors. NOTE: builtin-functions are treated
162 like static methods (no `this' pointer). */
164 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
166 descriptor_pool_parse_method_descriptor(descpool,
168 ACC_STATIC | ACC_METHOD_BUILTIN,
171 /* generate a builtin stub if we need one */
173 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
174 m = method_new_builtin(bte);
175 BuiltinStub::generate(m, bte);
179 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
181 descriptor_pool_parse_method_descriptor(descpool,
183 ACC_STATIC | ACC_METHOD_BUILTIN,
186 /* no stubs should be needed for this table */
188 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
191 for (bte = builtintable_function; bte->fp != NULL; bte++) {
193 descriptor_pool_parse_method_descriptor(descpool,
195 ACC_STATIC | ACC_METHOD_BUILTIN,
198 /* generate a builtin stub if we need one */
200 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
201 m = method_new_builtin(bte);
202 BuiltinStub::generate(m, bte);
210 /* builtintable_comparator *****************************************************
212 qsort comparator for the automatic builtin table.
214 *******************************************************************************/
216 static int builtintable_comparator(const void *a, const void *b)
218 builtintable_entry *bte1;
219 builtintable_entry *bte2;
221 bte1 = (builtintable_entry *) a;
222 bte2 = (builtintable_entry *) b;
224 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
228 /* builtintable_sort_automatic *************************************************
230 Sorts the automatic builtin table.
232 *******************************************************************************/
234 static void builtintable_sort_automatic(void)
238 /* calculate table size statically (`- 1' comment see builtintable.inc) */
240 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
242 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
243 builtintable_comparator);
247 /* builtin_init ****************************************************************
249 Initialize the global table of builtin functions.
251 *******************************************************************************/
253 bool builtin_init(void)
255 TRACESUBSYSTEMINITIALIZATION("builtin_init");
257 /* initialize the builtin tables */
259 if (!builtintable_init())
262 /* sort builtin tables */
264 builtintable_sort_automatic();
270 /* builtintable_get_internal ***************************************************
272 Finds an entry in the builtintable for internal functions and
273 returns the a pointer to the structure.
275 *******************************************************************************/
277 builtintable_entry *builtintable_get_internal(functionptr fp)
279 builtintable_entry *bte;
281 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
290 /* builtintable_get_automatic **************************************************
292 Finds an entry in the builtintable for functions which are replaced
293 automatically and returns the a pointer to the structure.
295 *******************************************************************************/
297 builtintable_entry *builtintable_get_automatic(s4 opcode)
299 builtintable_entry *first;
300 builtintable_entry *last;
301 builtintable_entry *middle;
305 /* calculate table size statically (`- 1' comment see builtintable.inc) */
307 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
309 first = builtintable_automatic;
310 last = builtintable_automatic + entries;
312 while (entries > 0) {
314 middle = first + half;
316 if (middle->opcode < opcode) {
324 return (first != last ? first : NULL);
328 /* builtintable_replace_function ***********************************************
332 *******************************************************************************/
334 #if defined(ENABLE_JIT)
335 bool builtintable_replace_function(void *iptr_)
338 builtintable_entry *bte;
341 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
343 /* get name and descriptor of the function */
346 case ICMD_INVOKESTATIC:
347 /* The instruction MUST be resolved, otherwise we run into
348 lazy loading troubles. Anyway, we should/can only replace
349 very VM-close functions. */
351 if (INSTRUCTION_IS_UNRESOLVED(iptr))
354 mr = iptr->sx.s23.s3.fmiref;
361 /* search the function table */
363 for (bte = builtintable_function; bte->fp != NULL; bte++) {
364 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
365 (mr->name == bte->name) &&
366 (mr->descriptor == bte->descriptor)) {
368 /* set the values in the instruction */
370 iptr->opc = bte->opcode;
371 iptr->sx.s23.s3.bte = bte;
373 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
374 iptr->flags.bits |= INS_FLAG_CHECK;
376 iptr->flags.bits &= ~INS_FLAG_CHECK;
384 #endif /* defined(ENABLE_JIT) */
387 /*============================================================================*/
388 /* INTERNAL BUILTIN FUNCTIONS */
389 /*============================================================================*/
391 /* builtin_instanceof **********************************************************
393 Checks if an object is an instance of some given class (or subclass
394 of that class). If class is an interface, checks if the interface
398 1......o is an instance of class or implements the interface
399 0......otherwise or if o == NULL
401 NOTE: This builtin can be called from NATIVE code only.
403 *******************************************************************************/
405 bool builtin_instanceof(java_handle_t *o, classinfo *c)
412 LLNI_class_get(o, oc);
414 return class_isanysubclass(oc, c);
419 /* builtin_checkcast ***********************************************************
421 The same as builtin_instanceof but with the exception
422 that 1 is returned when (o == NULL).
424 NOTE: This builtin can be called from NATIVE code only.
426 *******************************************************************************/
428 bool builtin_checkcast(java_handle_t *o, classinfo *c)
435 LLNI_class_get(o, oc);
437 if (class_isanysubclass(oc, c))
444 /* builtin_arraycheckcast ******************************************************
446 Checks if an object is really a subtype of the requested array
447 type. The object has to be an array to begin with. For simple
448 arrays (int, short, double, etc.) the types have to match exactly.
449 For arrays of objects, the type of elements in the array has to be
450 a subtype (or the same type) of the requested element type. For
451 arrays of arrays (which in turn can again be arrays of arrays), the
452 types at the lowest level have to satisfy the corresponding sub
455 NOTE: This is a FAST builtin and can be called from JIT code only.
457 *******************************************************************************/
459 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
461 arraydescriptor *desc;
466 desc = o->vftbl->arraydesc;
471 return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
475 /* builtin_fast_arrayinstanceof ************************************************
477 NOTE: This is a FAST builtin and can be called from JIT code only.
479 *******************************************************************************/
481 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
486 return builtin_fast_arraycheckcast(o, targetclass);
490 /* builtin_arrayinstanceof *****************************************************
492 NOTE: This builtin can be called from NATIVE code only.
494 *******************************************************************************/
496 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
502 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
510 /* builtin_throw_exception *****************************************************
512 Sets the exception pointer with the thrown exception and prints some
513 debugging information.
515 NOTE: This is a FAST builtin and can be called from JIT code,
516 or from asm_vm_call_method.
518 *******************************************************************************/
520 void *builtin_throw_exception(java_object_t *xptr)
523 /* print exception trace */
525 if (opt_TraceExceptions)
526 trace_exception_builtin(xptr);
527 #endif /* !defined(NDEBUG) */
529 /* actually set the exception */
531 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
533 /* Return a NULL pointer. This is required for vm_call_method to
534 check for an exception. This is for convenience. */
540 /* builtin_retrieve_exception **************************************************
542 Gets and clears the exception pointer of the current thread.
545 the exception object, or NULL if no exception was thrown.
547 NOTE: This is a FAST builtin and can be called from JIT code,
548 or from the signal handlers.
550 *******************************************************************************/
552 java_object_t *builtin_retrieve_exception(void)
557 /* actually get and clear the exception */
559 h = exceptions_get_and_clear_exception();
566 /* builtin_canstore ************************************************************
568 Checks, if an object can be stored in an array.
572 0......otherwise (throws an ArrayStoreException)
574 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
576 *******************************************************************************/
578 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
584 result = builtin_fast_canstore((java_objectarray_t*) LLNI_DIRECT(oa), LLNI_UNWRAP(o));
588 /* if not possible, throw an exception */
591 exceptions_throw_arraystoreexception();
597 /* fast_subtype_check **********************************************************
599 Checks if s is a subtype of t, using both the restricted subtype relation
600 and the overflow array (see Cliff Click and John Rose: Fast subtype checking
604 1......s is a subtype of t.
607 *******************************************************************************/
609 bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
611 if (s->subtype_display[t->subtype_depth] == t)
613 if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
615 return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
619 /* builtin_fast_canstore *******************************************************
621 Checks, if an object can be stored in an array.
625 0......otherwise (no exception thrown!)
627 NOTE: This is a FAST builtin and can be called from JIT code only.
629 *******************************************************************************/
631 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
633 arraydescriptor *desc;
634 arraydescriptor *valuedesc;
635 vftbl_t *componentvftbl;
643 /* The following is guaranteed (by verifier checks):
645 * *) oa->...vftbl->arraydesc != NULL
646 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
647 * *) o->vftbl is not an interface vftbl
650 desc = oa->header.objheader.vftbl->arraydesc;
651 componentvftbl = desc->componentvftbl;
652 valuevftbl = o->vftbl;
653 valuedesc = valuevftbl->arraydesc;
655 if ((desc->dimension - 1) == 0) {
656 /* {oa is a one-dimensional array} */
657 /* {oa is an array of references} */
659 if (valuevftbl == componentvftbl)
662 LOCK_CLASSRENUMBER_LOCK;
664 baseval = componentvftbl->baseval;
667 /* an array of interface references */
669 result = ((valuevftbl->interfacetablelength > -baseval) &&
670 (valuevftbl->interfacetable[baseval] != NULL));
674 result = fast_subtype_check(valuevftbl, componentvftbl);
676 uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
677 result = diffval <= (uint32_t) componentvftbl->diffval;
681 UNLOCK_CLASSRENUMBER_LOCK;
683 else if (valuedesc == NULL) {
684 /* {oa has dimension > 1} */
685 /* {componentvftbl->arraydesc != NULL} */
687 /* check if o is an array */
692 /* {o is an array} */
694 result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
703 /* This is an optimized version where a is guaranteed to be one-dimensional */
704 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
706 arraydescriptor *desc;
707 vftbl_t *elementvftbl;
715 /* The following is guaranteed (by verifier checks):
717 * *) a->...vftbl->arraydesc != NULL
718 * *) a->...vftbl->arraydesc->elementvftbl != NULL
719 * *) a->...vftbl->arraydesc->dimension == 1
720 * *) o->vftbl is not an interface vftbl
723 desc = a->header.objheader.vftbl->arraydesc;
724 elementvftbl = desc->elementvftbl;
725 valuevftbl = o->vftbl;
727 /* {a is a one-dimensional array} */
729 if (valuevftbl == elementvftbl)
732 LOCK_CLASSRENUMBER_LOCK;
734 baseval = elementvftbl->baseval;
737 /* an array of interface references */
738 result = ((valuevftbl->interfacetablelength > -baseval) &&
739 (valuevftbl->interfacetable[baseval] != NULL));
743 result = fast_subtype_check(valuevftbl, elementvftbl);
745 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
746 result = diffval <= (uint32_t) elementvftbl->diffval;
750 UNLOCK_CLASSRENUMBER_LOCK;
756 /* This is an optimized version where a is guaranteed to be a
757 * one-dimensional array of a class type */
758 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
760 vftbl_t *elementvftbl;
767 /* The following is guaranteed (by verifier checks):
769 * *) a->...vftbl->arraydesc != NULL
770 * *) a->...vftbl->arraydesc->elementvftbl != NULL
771 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
772 * *) a->...vftbl->arraydesc->dimension == 1
773 * *) o->vftbl is not an interface vftbl
776 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
777 valuevftbl = o->vftbl;
779 /* {a is a one-dimensional array} */
781 if (valuevftbl == elementvftbl)
784 LOCK_CLASSRENUMBER_LOCK;
787 result = fast_subtype_check(valuevftbl, elementvftbl);
789 uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
790 result = diffval <= (uint32_t) elementvftbl->diffval;
793 UNLOCK_CLASSRENUMBER_LOCK;
799 /* builtin_new *****************************************************************
801 Creates a new instance of class c on the heap.
804 pointer to the object, or NULL if no memory is available
806 NOTE: This builtin can be called from NATIVE code only.
808 *******************************************************************************/
810 java_handle_t *builtin_new(classinfo *c)
813 #if defined(ENABLE_RT_TIMING)
814 struct timespec time_start, time_end;
816 #if defined(ENABLE_CYCLES_STATS)
817 u8 cycles_start, cycles_end;
820 RT_TIMING_GET_TIME(time_start);
821 CYCLES_STATS_GET(cycles_start);
823 /* is the class loaded */
825 assert(c->state & CLASS_LOADED);
827 /* check if we can instantiate this class */
829 if (c->flags & ACC_ABSTRACT) {
830 exceptions_throw_instantiationerror(c);
834 /* is the class linked */
836 if (!(c->state & CLASS_LINKED))
840 if (!(c->state & CLASS_INITIALIZED)) {
843 log_message_class("Initialize class (from builtin_new): ", c);
846 if (!initialize_class(c))
850 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
856 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
857 /* XXX this is only a dirty hack to make Boehm work with handles */
859 o = LLNI_WRAP((java_object_t *) o);
862 LLNI_vftbl_direct(o) = c->vftbl;
864 #if defined(ENABLE_THREADS)
865 LLNI_DIRECT(o)->lockword.init();
868 CYCLES_STATS_GET(cycles_end);
869 RT_TIMING_GET_TIME(time_end);
871 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
872 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
877 #if defined(ENABLE_ESCAPE_REASON)
878 java_handle_t *builtin_escape_reason_new(classinfo *c) {
879 print_escape_reasons();
880 return builtin_java_new(c);
884 #if defined(ENABLE_TLH)
885 java_handle_t *builtin_tlh_new(classinfo *c)
888 # if defined(ENABLE_RT_TIMING)
889 struct timespec time_start, time_end;
891 # if defined(ENABLE_CYCLES_STATS)
892 u8 cycles_start, cycles_end;
895 RT_TIMING_GET_TIME(time_start);
896 CYCLES_STATS_GET(cycles_start);
898 /* is the class loaded */
900 assert(c->state & CLASS_LOADED);
902 /* check if we can instantiate this class */
904 if (c->flags & ACC_ABSTRACT) {
905 exceptions_throw_instantiationerror(c);
909 /* is the class linked */
911 if (!(c->state & CLASS_LINKED))
915 if (!(c->state & CLASS_INITIALIZED)) {
916 # if !defined(NDEBUG)
918 log_message_class("Initialize class (from builtin_new): ", c);
921 if (!initialize_class(c))
926 o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
931 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
938 # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
939 /* XXX this is only a dirty hack to make Boehm work with handles */
941 o = LLNI_WRAP((java_object_t *) o);
944 LLNI_vftbl_direct(o) = c->vftbl;
946 # if defined(ENABLE_THREADS)
947 LLNI_DIRECT(o)->lockword.init();
950 CYCLES_STATS_GET(cycles_end);
951 RT_TIMING_GET_TIME(time_end);
954 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
955 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
963 /* builtin_java_new ************************************************************
965 NOTE: This is a SLOW builtin and can be called from JIT code only.
967 *******************************************************************************/
969 java_handle_t *builtin_java_new(java_handle_t *clazz)
971 return builtin_new(LLNI_classinfo_unwrap(clazz));
975 /* builtin_fast_new ************************************************************
977 Creates a new instance of class c on the heap.
980 pointer to the object, or NULL if no fast return
981 is possible for any reason.
983 NOTE: This is a FAST builtin and can be called from JIT code only.
985 *******************************************************************************/
987 java_object_t *builtin_fast_new(classinfo *c)
990 #if defined(ENABLE_RT_TIMING)
991 struct timespec time_start, time_end;
993 #if defined(ENABLE_CYCLES_STATS)
994 u8 cycles_start, cycles_end;
997 RT_TIMING_GET_TIME(time_start);
998 CYCLES_STATS_GET(cycles_start);
1000 /* is the class loaded */
1002 assert(c->state & CLASS_LOADED);
1004 /* check if we can instantiate this class */
1006 if (c->flags & ACC_ABSTRACT)
1009 /* is the class linked */
1011 if (!(c->state & CLASS_LINKED))
1014 if (!(c->state & CLASS_INITIALIZED))
1017 o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
1018 c->finalizer, false);
1023 o->vftbl = c->vftbl;
1025 #if defined(ENABLE_THREADS)
1026 LLNI_DIRECT(o)->lockword.init();
1029 CYCLES_STATS_GET(cycles_end);
1030 RT_TIMING_GET_TIME(time_end);
1032 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
1033 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
1039 /* builtin_java_newarray *******************************************************
1041 Creates an array with the given vftbl on the heap. This function
1042 takes as class argument an array class.
1045 pointer to the array or NULL if no memory is available
1047 NOTE: This is a SLOW builtin and can be called from JIT code only.
1049 *******************************************************************************/
1051 java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1053 #if defined(ENABLE_RT_TIMING)
1054 struct timespec time_start, time_end;
1057 RT_TIMING_GET_TIME(time_start);
1059 classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
1061 // Allocate a new array with given size and class on the heap
1062 Array a(size, arrayclass);
1064 RT_TIMING_GET_TIME(time_end);
1065 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1067 return a.get_handle();
1071 /* builtin_newarray_type ****************************************************
1073 Creates an array of [type]s on the heap.
1076 pointer to the array or NULL if no memory is available
1078 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1080 *******************************************************************************/
1082 #define BUILTIN_NEWARRAY_TYPE(type, name) \
1083 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1085 name##Array a(size); \
1086 return a.get_handle(); \
1089 BUILTIN_NEWARRAY_TYPE(boolean, Boolean)
1090 BUILTIN_NEWARRAY_TYPE(byte, Byte)
1091 BUILTIN_NEWARRAY_TYPE(char, Char)
1092 BUILTIN_NEWARRAY_TYPE(short, Short)
1093 BUILTIN_NEWARRAY_TYPE(int, Int)
1094 BUILTIN_NEWARRAY_TYPE(long, Long)
1095 BUILTIN_NEWARRAY_TYPE(float, Float)
1096 BUILTIN_NEWARRAY_TYPE(double, Double)
1099 /* builtin_multianewarray_intern ***********************************************
1101 Creates a multi-dimensional array on the heap. The dimensions are
1102 passed in an array of longs.
1105 n.............number of dimensions to create
1106 arrayclass....the array class
1107 dims..........array containing the size of each dimension to create
1110 pointer to the array or NULL if no memory is available
1112 ******************************************************************************/
1114 static java_handle_array_t *builtin_multianewarray_intern(int n,
1115 classinfo *arrayclass,
1120 /* create this dimension */
1122 int32_t size = (int32_t) dims[0];
1123 Array a(size, arrayclass);
1128 /* if this is the last dimension return */
1131 return a.get_handle();
1133 /* get the class of the components to create */
1135 classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1137 /* The verifier guarantees that the dimension count is in the range. */
1139 /* create the component arrays */
1141 ObjectArray oa(a.get_handle());
1143 for (i = 0; i < size; i++) {
1144 java_handle_array_t *ea =
1145 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1146 /* we save an s4 to a s8 slot, 8-byte aligned */
1148 builtin_multianewarray_intern(n, componentclass, dims + 2);
1150 builtin_multianewarray_intern(n, componentclass, dims + 1);
1156 oa.set_element(i, (java_handle_t*) ea);
1159 return a.get_handle();
1163 /* builtin_multianewarray ******************************************************
1165 Wrapper for builtin_multianewarray_intern which checks all
1166 dimensions before we start allocating.
1168 NOTE: This is a SLOW builtin and can be called from JIT code only.
1170 ******************************************************************************/
1172 java_handle_objectarray_t *builtin_multianewarray(int n,
1173 java_handle_t *arrayclazz,
1180 /* check all dimensions before doing anything */
1182 for (i = 0; i < n; i++) {
1183 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1184 /* we save an s4 to a s8 slot, 8-byte aligned */
1185 size = (s4) dims[i * 2];
1187 size = (s4) dims[i];
1191 exceptions_throw_negativearraysizeexception();
1196 c = LLNI_classinfo_unwrap(arrayclazz);
1198 /* now call the real function */
1200 return (java_handle_objectarray_t *)
1201 builtin_multianewarray_intern(n, c, dims);
1205 /* builtin_verbosecall_enter ***************************************************
1207 Print method call with arguments for -verbose:call.
1209 XXX: Remove mew once all archs use the new tracer!
1211 *******************************************************************************/
1213 #if !defined(NDEBUG)
1214 #ifdef TRACE_ARGS_NUM
1215 void builtin_verbosecall_enter(s8 a0, s8 a1,
1216 # if TRACE_ARGS_NUM >= 4
1219 # if TRACE_ARGS_NUM >= 6
1222 # if TRACE_ARGS_NUM == 8
1227 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1230 #endif /* !defined(NDEBUG) */
1233 /* builtin_verbosecall_exit ****************************************************
1235 Print method exit for -verbose:call.
1237 XXX: Remove mew once all archs use the new tracer!
1239 *******************************************************************************/
1241 #if !defined(NDEBUG)
1242 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1244 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1246 #endif /* !defined(NDEBUG) */
1249 /*============================================================================*/
1250 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1251 /*============================================================================*/
1253 /*********** Functions for integer divisions *****************************
1255 On some systems (eg. DEC ALPHA), integer division is not supported by the
1256 CPU. These helper functions implement the missing functionality.
1258 ******************************************************************************/
1260 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1261 s4 builtin_idiv(s4 a, s4 b)
1270 s4 builtin_irem(s4 a, s4 b)
1278 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1281 /* functions for long arithmetics **********************************************
1283 On systems where 64 bit Integers are not supported by the CPU,
1284 these functions are needed.
1286 ******************************************************************************/
1288 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1289 s8 builtin_ladd(s8 a, s8 b)
1298 s8 builtin_lsub(s8 a, s8 b)
1307 s8 builtin_lneg(s8 a)
1315 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1318 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1319 s8 builtin_lmul(s8 a, s8 b)
1327 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1330 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1331 s8 builtin_ldiv(s8 a, s8 b)
1340 s8 builtin_lrem(s8 a, s8 b)
1348 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1351 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1352 s8 builtin_lshl(s8 a, s4 b)
1361 s8 builtin_lshr(s8 a, s4 b)
1370 s8 builtin_lushr(s8 a, s4 b)
1374 c = ((u8) a) >> (b & 63);
1378 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1381 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1382 s8 builtin_land(s8 a, s8 b)
1391 s8 builtin_lor(s8 a, s8 b)
1400 s8 builtin_lxor(s8 a, s8 b)
1408 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1411 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1412 s4 builtin_lcmp(s8 a, s8 b)
1422 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1425 /* functions for unsupported floating instructions ****************************/
1427 /* used to convert FLT_xxx defines into float values */
1429 static inline float intBitsToFloat(s4 i)
1438 /* used to convert DBL_xxx defines into double values */
1440 static inline float longBitsToDouble(s8 l)
1450 float builtin_fadd(float a, float b)
1452 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1453 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1464 if (copysignf(1.0, a) == copysignf(1.0, b))
1467 return intBitsToFloat(FLT_NAN);
1473 float builtin_fsub(float a, float b)
1475 return builtin_fadd(a, builtin_fneg(b));
1479 float builtin_fmul(float a, float b)
1481 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1482 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1484 if (finitef(b)) return a * b;
1486 if (a == 0) return intBitsToFloat(FLT_NAN);
1487 else return copysignf(b, copysignf(1.0, b)*a);
1492 if (b == 0) return intBitsToFloat(FLT_NAN);
1493 else return copysignf(a, copysignf(1.0, a)*b);
1496 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1502 /* builtin_ddiv ****************************************************************
1504 Implementation as described in VM Spec.
1506 *******************************************************************************/
1508 float builtin_fdiv(float a, float b)
1512 /* If neither value1' nor value2' is NaN, the sign of the result */
1513 /* is positive if both values have the same sign, negative if the */
1514 /* values have different signs. */
1520 /* If either value1' or value2' is NaN, the result is NaN. */
1522 return intBitsToFloat(FLT_NAN);
1525 /* Division of a finite value by an infinity results in a */
1526 /* signed zero, with the sign-producing rule just given. */
1528 /* is sign equal? */
1530 if (copysignf(1.0, a) == copysignf(1.0, b))
1539 /* If either value1' or value2' is NaN, the result is NaN. */
1541 return intBitsToFloat(FLT_NAN);
1543 } else if (finitef(b)) {
1544 /* Division of an infinity by a finite value results in a signed */
1545 /* infinity, with the sign-producing rule just given. */
1547 /* is sign equal? */
1549 if (copysignf(1.0, a) == copysignf(1.0, b))
1550 return intBitsToFloat(FLT_POSINF);
1552 return intBitsToFloat(FLT_NEGINF);
1555 /* Division of an infinity by an infinity results in NaN. */
1557 return intBitsToFloat(FLT_NAN);
1563 float builtin_fneg(float a)
1565 if (isnanf(a)) return a;
1567 if (finitef(a)) return -a;
1568 else return copysignf(a, -copysignf(1.0, a));
1571 #endif /* !SUPPORT_FLOAT */
1574 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1575 s4 builtin_fcmpl(float a, float b)
1583 if (!finitef(a) || !finitef(b)) {
1584 a = finitef(a) ? 0 : copysignf(1.0, a);
1585 b = finitef(b) ? 0 : copysignf(1.0, b);
1598 s4 builtin_fcmpg(float a, float b)
1600 if (isnanf(a)) return 1;
1601 if (isnanf(b)) return 1;
1602 if (!finitef(a) || !finitef(b)) {
1603 a = finitef(a) ? 0 : copysignf(1.0, a);
1604 b = finitef(b) ? 0 : copysignf(1.0, b);
1606 if (a > b) return 1;
1607 if (a == b) return 0;
1610 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1613 float builtin_frem(float a, float b)
1619 /* functions for unsupported double instructions ******************************/
1622 double builtin_dadd(double a, double b)
1624 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1625 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1627 if (finite(b)) return a + b;
1631 if (finite(b)) return a;
1633 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1634 else return longBitsToDouble(DBL_NAN);
1640 double builtin_dsub(double a, double b)
1642 return builtin_dadd(a, builtin_dneg(b));
1646 double builtin_dmul(double a, double b)
1648 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1649 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1651 if (finite(b)) return a * b;
1653 if (a == 0) return longBitsToDouble(DBL_NAN);
1654 else return copysign(b, copysign(1.0, b) * a);
1659 if (b == 0) return longBitsToDouble(DBL_NAN);
1660 else return copysign(a, copysign(1.0, a) * b);
1663 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1669 /* builtin_ddiv ****************************************************************
1671 Implementation as described in VM Spec.
1673 *******************************************************************************/
1675 double builtin_ddiv(double a, double b)
1679 /* If neither value1' nor value2' is NaN, the sign of the result */
1680 /* is positive if both values have the same sign, negative if the */
1681 /* values have different signs. */
1687 /* If either value1' or value2' is NaN, the result is NaN. */
1689 return longBitsToDouble(DBL_NAN);
1692 /* Division of a finite value by an infinity results in a */
1693 /* signed zero, with the sign-producing rule just given. */
1695 /* is sign equal? */
1697 if (copysign(1.0, a) == copysign(1.0, b))
1706 /* If either value1' or value2' is NaN, the result is NaN. */
1708 return longBitsToDouble(DBL_NAN);
1710 } else if (finite(b)) {
1711 /* Division of an infinity by a finite value results in a signed */
1712 /* infinity, with the sign-producing rule just given. */
1714 /* is sign equal? */
1716 if (copysign(1.0, a) == copysign(1.0, b))
1717 return longBitsToDouble(DBL_POSINF);
1719 return longBitsToDouble(DBL_NEGINF);
1722 /* Division of an infinity by an infinity results in NaN. */
1724 return longBitsToDouble(DBL_NAN);
1730 /* builtin_dneg ****************************************************************
1732 Implemented as described in VM Spec.
1734 *******************************************************************************/
1736 double builtin_dneg(double a)
1739 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1746 /* If the operand is a zero, the result is the zero of opposite */
1752 /* If the operand is an infinity, the result is the infinity of */
1753 /* opposite sign. */
1755 return copysign(a, -copysign(1.0, a));
1759 #endif /* !SUPPORT_DOUBLE */
1762 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1763 s4 builtin_dcmpl(double a, double b)
1771 if (!finite(a) || !finite(b)) {
1772 a = finite(a) ? 0 : copysign(1.0, a);
1773 b = finite(b) ? 0 : copysign(1.0, b);
1786 s4 builtin_dcmpg(double a, double b)
1794 if (!finite(a) || !finite(b)) {
1795 a = finite(a) ? 0 : copysign(1.0, a);
1796 b = finite(b) ? 0 : copysign(1.0, b);
1807 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1810 double builtin_drem(double a, double b)
1816 /* conversion operations ******************************************************/
1818 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1819 float builtin_i2f(s4 a)
1821 float f = (float) a;
1824 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1827 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1828 double builtin_i2d(s4 a)
1830 double d = (double) a;
1833 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1836 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1837 float builtin_l2f(s8 a)
1839 float f = (float) a;
1842 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1845 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1846 double builtin_l2d(s8 a)
1848 double d = (double) a;
1851 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1854 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1855 s4 builtin_f2i(float a)
1859 i = builtin_d2i((double) a);
1870 if (a < (-2147483648))
1871 return (-2147483648);
1874 f = copysignf((float) 1.0, a);
1877 return (-2147483648); */
1879 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1882 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1883 s8 builtin_f2l(float a)
1887 l = builtin_d2l((double) a);
1894 if (a > 9223372036854775807L)
1895 return 9223372036854775807L;
1896 if (a < (-9223372036854775808L))
1897 return (-9223372036854775808L);
1902 f = copysignf((float) 1.0, a);
1904 return 9223372036854775807L;
1905 return (-9223372036854775808L); */
1907 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
1910 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1911 s4 builtin_d2i(double a)
1916 if (a >= 2147483647)
1918 if (a <= (-2147483647-1))
1919 return (-2147483647-1);
1924 d = copysign(1.0, a);
1927 return (-2147483647-1);
1929 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1932 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
1933 s8 builtin_d2l(double a)
1938 if (a >= 9223372036854775807LL)
1939 return 9223372036854775807LL;
1940 if (a <= (-9223372036854775807LL-1))
1941 return (-9223372036854775807LL-1);
1946 d = copysign(1.0, a);
1948 return 9223372036854775807LL;
1949 return (-9223372036854775807LL-1);
1951 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
1954 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
1955 double builtin_f2d(float a)
1957 if (finitef(a)) return (double) a;
1960 return longBitsToDouble(DBL_NAN);
1962 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1966 float builtin_d2f(double a)
1972 return intBitsToFloat(FLT_NAN);
1974 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1977 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
1980 /*============================================================================*/
1981 /* AUTOMATICALLY REPLACED FUNCTIONS */
1982 /*============================================================================*/
1984 /* builtin_arraycopy ***********************************************************
1986 Builtin for java.lang.System.arraycopy.
1988 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1990 *******************************************************************************/
1992 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
1993 java_handle_t *dest, s4 destStart, s4 len)
1995 arraydescriptor *sdesc;
1996 arraydescriptor *ddesc;
1999 if ((src == NULL) || (dest == NULL)) {
2000 exceptions_throw_nullpointerexception();
2007 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2008 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2010 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2011 exceptions_throw_arraystoreexception();
2015 // Check if offsets and length are positive.
2016 if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
2017 exceptions_throw_arrayindexoutofboundsexception();
2021 // Check if ranges are valid.
2022 if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) sa.get_length()) ||
2023 (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) {
2024 exceptions_throw_arrayindexoutofboundsexception();
2033 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2034 /* We copy primitive values or references of exactly the same type */
2036 s4 dataoffset = sdesc->dataoffset;
2037 s4 componentsize = sdesc->componentsize;
2039 LLNI_CRITICAL_START;
2041 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2042 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2043 u1, (size_t) len * componentsize);
2048 /* We copy references of different type */
2050 ObjectArray oas((java_handle_objectarray_t*) src);
2051 ObjectArray oad((java_handle_objectarray_t*) dest);
2053 if (destStart <= srcStart) {
2054 for (i = 0; i < len; i++) {
2055 java_handle_t* o = oas.get_element(srcStart + i);
2057 if (!builtin_canstore(oad.get_handle(), o))
2060 oad.set_element(destStart + i, o);
2064 /* XXX this does not completely obey the specification!
2065 If an exception is thrown only the elements above the
2066 current index have been copied. The specification
2067 requires that only the elements *below* the current
2068 index have been copied before the throw. */
2070 for (i = len - 1; i >= 0; i--) {
2071 java_handle_t* o = oas.get_element(srcStart + i);
2073 if (!builtin_canstore(oad.get_handle(), o))
2076 oad.set_element(destStart + i, o);
2083 /* builtin_nanotime ************************************************************
2085 Return the current time in nanoseconds.
2087 *******************************************************************************/
2089 s8 builtin_nanotime(void)
2094 if (gettimeofday(&tv, NULL) == -1)
2095 vm_abort("gettimeofday failed: %s", strerror(errno));
2097 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2099 return usecs * 1000;
2103 /* builtin_currenttimemillis ***************************************************
2105 Return the current time in milliseconds.
2107 *******************************************************************************/
2109 s8 builtin_currenttimemillis(void)
2113 msecs = builtin_nanotime() / 1000 / 1000;
2119 /* builtin_clone ***************************************************************
2121 Function for cloning objects or arrays.
2123 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2125 *******************************************************************************/
2127 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2129 arraydescriptor *ad;
2132 java_handle_t *co; /* cloned object header */
2134 /* get the array descriptor */
2136 ad = LLNI_vftbl_direct(o)->arraydesc;
2138 /* we are cloning an array */
2143 size = ad->dataoffset + ad->componentsize * a.get_length();
2145 co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2150 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2151 /* XXX this is only a dirty hack to make Boehm work with handles */
2153 co = LLNI_WRAP((java_object_t *) co);
2156 LLNI_CRITICAL_START;
2158 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2160 #if defined(ENABLE_GC_CACAO)
2161 heap_init_objectheader(LLNI_DIRECT(co), size);
2164 #if defined(ENABLE_THREADS)
2165 LLNI_DIRECT(co)->lockword.init();
2173 /* we are cloning a non-array */
2175 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2176 exceptions_throw_clonenotsupportedexception();
2180 /* get the class of the object */
2182 LLNI_class_get(o, c);
2184 /* create new object */
2186 co = builtin_new(c);
2191 LLNI_CRITICAL_START;
2193 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2195 #if defined(ENABLE_GC_CACAO)
2196 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2199 #if defined(ENABLE_THREADS)
2200 LLNI_DIRECT(co)->lockword.init();
2209 #if defined(ENABLE_CYCLES_STATS)
2210 void builtin_print_cycles_stats(FILE *file)
2212 fprintf(file,"builtin cylce count statistics:\n");
2214 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2215 CYCLES_STATS_PRINT(builtin_new ,file);
2219 #endif /* defined(ENABLE_CYCLES_STATS) */
2222 #if defined(ENABLE_VMLOG)
2224 #include <vmlog_cacao.c>
2229 * These are local overrides for various environment variables in Emacs.
2230 * Please do not remove this and leave it at the end of the file, where
2231 * Emacs will automagically detect them.
2232 * ---------------------------------------------------------------------
2235 * indent-tabs-mode: t
2239 * vim:noexpandtab:sw=4:ts=4: