1 /* src/vm/builtin.c - 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)
50 #include "mm/gc-common.h"
51 #include "mm/memory.h"
53 #include "native/jni.h"
54 #include "native/llni.h"
56 #include "threads/lock-common.h"
57 #include "threads/thread.h"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
63 #include "vm/builtin.h"
64 #include "vm/cycles-stats.h"
65 #include "vm/exceptions.h"
66 #include "vm/global.h"
67 #include "vm/initialize.h"
68 #include "vm/primitive.h"
69 #include "vm/stringlocal.h"
71 #include "vm/jit/asmpart.h"
72 #include "vm/jit/trace.h"
74 #include "vmcore/class.h"
75 #include "vmcore/linker.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/options.h"
78 #include "vmcore/rt-timing.h"
80 #if defined(ENABLE_VMLOG)
81 #include <vmlog_cacao.h>
85 /* include builtin tables *****************************************************/
87 #include "vm/builtintable.inc"
90 CYCLES_STATS_DECLARE(builtin_new ,100,5)
91 CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
94 /*============================================================================*/
95 /* BUILTIN TABLE MANAGEMENT FUNCTIONS */
96 /*============================================================================*/
98 /* builtintable_init ***********************************************************
100 Parse the descriptors of builtin functions and create the parsed
103 *******************************************************************************/
105 static bool builtintable_init(void)
107 descriptor_pool *descpool;
108 builtintable_entry *bte;
112 /* mark start of 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)) {
135 /* release dump area */
143 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144 bte->descriptor = utf_new_char(bte->cdescriptor);
146 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
152 for (bte = builtintable_function; bte->fp != NULL; bte++) {
153 bte->classname = utf_new_char(bte->cclassname);
154 bte->name = utf_new_char(bte->cname);
155 bte->descriptor = utf_new_char(bte->cdescriptor);
157 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
163 /* create the class reference table */
165 (void) descriptor_pool_create_classrefs(descpool, NULL);
167 /* allocate space for the parsed descriptors */
169 descriptor_pool_alloc_parsed_descriptors(descpool);
171 /* Now parse all descriptors. NOTE: builtin-functions are treated
172 like static methods (no `this' pointer). */
174 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
176 descriptor_pool_parse_method_descriptor(descpool,
178 ACC_STATIC | ACC_METHOD_BUILTIN,
181 /* generate a builtin stub if we need one */
183 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
184 m = method_new_builtin(bte);
185 codegen_generate_stub_builtin(m, bte);
189 for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
191 descriptor_pool_parse_method_descriptor(descpool,
193 ACC_STATIC | ACC_METHOD_BUILTIN,
196 /* no stubs should be needed for this table */
198 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
201 for (bte = builtintable_function; bte->fp != NULL; bte++) {
203 descriptor_pool_parse_method_descriptor(descpool,
205 ACC_STATIC | ACC_METHOD_BUILTIN,
208 /* generate a builtin stub if we need one */
210 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
211 m = method_new_builtin(bte);
212 codegen_generate_stub_builtin(m, bte);
216 /* release dump area */
224 /* builtintable_comparator *****************************************************
226 qsort comparator for the automatic builtin table.
228 *******************************************************************************/
230 static int builtintable_comparator(const void *a, const void *b)
232 builtintable_entry *bte1;
233 builtintable_entry *bte2;
235 bte1 = (builtintable_entry *) a;
236 bte2 = (builtintable_entry *) b;
238 return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
242 /* builtintable_sort_automatic *************************************************
244 Sorts the automatic builtin table.
246 *******************************************************************************/
248 static void builtintable_sort_automatic(void)
252 /* calculate table size statically (`- 1' comment see builtintable.inc) */
254 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
256 qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
257 builtintable_comparator);
261 /* builtin_init ****************************************************************
263 Initialize the global table of builtin functions.
265 *******************************************************************************/
267 bool builtin_init(void)
269 TRACESUBSYSTEMINITIALIZATION("builtin_init");
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 bool 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 bool 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 bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
473 if (desc->arraytype != target->arraytype)
476 if (desc->arraytype != ARRAYTYPE_OBJECT)
479 /* {both arrays are arrays of references} */
481 if (desc->dimension == target->dimension) {
482 /* an array which contains elements of interface types is
483 allowed to be casted to Object (JOWENN)*/
485 if ((desc->elementvftbl->baseval < 0) &&
486 (target->elementvftbl->baseval == 1))
489 return class_isanysubclass(desc->elementvftbl->clazz,
490 target->elementvftbl->clazz);
493 if (desc->dimension < target->dimension)
496 /* {desc has higher dimension than target} */
498 return class_isanysubclass(pseudo_class_Arraystub,
499 target->elementvftbl->clazz);
503 /* builtin_arraycheckcast ******************************************************
505 Checks if an object is really a subtype of the requested array
506 type. The object has to be an array to begin with. For simple
507 arrays (int, short, double, etc.) the types have to match exactly.
508 For arrays of objects, the type of elements in the array has to be
509 a subtype (or the same type) of the requested element type. For
510 arrays of arrays (which in turn can again be arrays of arrays), the
511 types at the lowest level have to satisfy the corresponding sub
514 NOTE: This is a FAST builtin and can be called from JIT code only.
516 *******************************************************************************/
518 bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
520 arraydescriptor *desc;
525 desc = o->vftbl->arraydesc;
530 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
534 /* builtin_fast_arrayinstanceof ************************************************
536 NOTE: This is a FAST builtin and can be called from JIT code only.
538 *******************************************************************************/
540 bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
545 return builtin_fast_arraycheckcast(o, targetclass);
549 /* builtin_arrayinstanceof *****************************************************
551 NOTE: This builtin can be called from NATIVE code only.
553 *******************************************************************************/
555 bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
561 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
569 /* builtin_throw_exception *****************************************************
571 Sets the exception pointer with the thrown exception and prints some
572 debugging information.
574 NOTE: This is a FAST builtin and can be called from JIT code,
575 or from asm_vm_call_method.
577 *******************************************************************************/
579 void *builtin_throw_exception(java_object_t *xptr)
582 /* print exception trace */
584 if (opt_TraceExceptions)
585 trace_exception_builtin(xptr);
586 #endif /* !defined(NDEBUG) */
588 /* actually set the exception */
590 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
592 /* Return a NULL pointer. This is required for vm_call_method to
593 check for an exception. This is for convenience. */
599 /* builtin_retrieve_exception **************************************************
601 Gets and clears the exception pointer of the current thread.
604 the exception object, or NULL if no exception was thrown.
606 NOTE: This is a FAST builtin and can be called from JIT code,
607 or from the signal handlers.
609 *******************************************************************************/
611 java_object_t *builtin_retrieve_exception(void)
616 /* actually get and clear the exception */
618 h = exceptions_get_and_clear_exception();
625 /* builtin_canstore ************************************************************
627 Checks, if an object can be stored in an array.
631 0......otherwise (throws an ArrayStoreException)
633 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
635 *******************************************************************************/
637 bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
643 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
647 /* if not possible, throw an exception */
650 exceptions_throw_arraystoreexception();
656 /* builtin_fast_canstore *******************************************************
658 Checks, if an object can be stored in an array.
662 0......otherwise (no exception thrown!)
664 NOTE: This is a FAST builtin and can be called from JIT code only.
666 *******************************************************************************/
668 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
670 arraydescriptor *desc;
671 arraydescriptor *valuedesc;
672 vftbl_t *componentvftbl;
681 /* The following is guaranteed (by verifier checks):
683 * *) oa->...vftbl->arraydesc != NULL
684 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
685 * *) o->vftbl is not an interface vftbl
688 desc = oa->header.objheader.vftbl->arraydesc;
689 componentvftbl = desc->componentvftbl;
690 valuevftbl = o->vftbl;
691 valuedesc = valuevftbl->arraydesc;
693 if ((desc->dimension - 1) == 0) {
694 /* {oa is a one-dimensional array} */
695 /* {oa is an array of references} */
697 if (valuevftbl == componentvftbl)
700 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
702 baseval = componentvftbl->baseval;
705 /* an array of interface references */
707 result = ((valuevftbl->interfacetablelength > -baseval) &&
708 (valuevftbl->interfacetable[baseval] != NULL));
711 diffval = valuevftbl->baseval - componentvftbl->baseval;
712 result = diffval <= (uint32_t) componentvftbl->diffval;
715 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
717 else if (valuedesc == NULL) {
718 /* {oa has dimension > 1} */
719 /* {componentvftbl->arraydesc != NULL} */
721 /* check if o is an array */
726 /* {o is an array} */
728 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
737 /* This is an optimized version where a is guaranteed to be one-dimensional */
738 bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
740 arraydescriptor *desc;
741 vftbl_t *elementvftbl;
750 /* The following is guaranteed (by verifier checks):
752 * *) a->...vftbl->arraydesc != NULL
753 * *) a->...vftbl->arraydesc->elementvftbl != NULL
754 * *) a->...vftbl->arraydesc->dimension == 1
755 * *) o->vftbl is not an interface vftbl
758 desc = a->header.objheader.vftbl->arraydesc;
759 elementvftbl = desc->elementvftbl;
760 valuevftbl = o->vftbl;
762 /* {a is a one-dimensional array} */
764 if (valuevftbl == elementvftbl)
767 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
769 baseval = elementvftbl->baseval;
772 /* an array of interface references */
773 result = ((valuevftbl->interfacetablelength > -baseval) &&
774 (valuevftbl->interfacetable[baseval] != NULL));
777 diffval = valuevftbl->baseval - elementvftbl->baseval;
778 result = diffval <= (uint32_t) elementvftbl->diffval;
781 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
787 /* This is an optimized version where a is guaranteed to be a
788 * one-dimensional array of a class type */
789 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
791 vftbl_t *elementvftbl;
799 /* The following is guaranteed (by verifier checks):
801 * *) a->...vftbl->arraydesc != NULL
802 * *) a->...vftbl->arraydesc->elementvftbl != NULL
803 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
804 * *) a->...vftbl->arraydesc->dimension == 1
805 * *) o->vftbl is not an interface vftbl
808 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
809 valuevftbl = o->vftbl;
811 /* {a is a one-dimensional array} */
813 if (valuevftbl == elementvftbl)
816 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
818 diffval = valuevftbl->baseval - elementvftbl->baseval;
819 result = diffval <= (uint32_t) elementvftbl->diffval;
821 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
827 /* builtin_new *****************************************************************
829 Creates a new instance of class c on the heap.
832 pointer to the object, or NULL if no memory is available
834 NOTE: This builtin can be called from NATIVE code only.
836 *******************************************************************************/
838 java_handle_t *builtin_new(classinfo *c)
841 #if defined(ENABLE_RT_TIMING)
842 struct timespec time_start, time_end;
844 #if defined(ENABLE_CYCLES_STATS)
845 u8 cycles_start, cycles_end;
848 RT_TIMING_GET_TIME(time_start);
849 CYCLES_STATS_GET(cycles_start);
851 /* is the class loaded */
853 assert(c->state & CLASS_LOADED);
855 /* check if we can instantiate this class */
857 if (c->flags & ACC_ABSTRACT) {
858 exceptions_throw_instantiationerror(c);
862 /* is the class linked */
864 if (!(c->state & CLASS_LINKED))
868 if (!(c->state & CLASS_INITIALIZED)) {
871 log_message_class("Initialize class (from builtin_new): ", c);
874 if (!initialize_class(c))
878 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
884 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
885 /* XXX this is only a dirty hack to make Boehm work with handles */
887 o = LLNI_WRAP((java_object_t *) o);
890 LLNI_vftbl_direct(o) = c->vftbl;
892 #if defined(ENABLE_THREADS)
893 lock_init_object_lock(LLNI_DIRECT(o));
896 CYCLES_STATS_GET(cycles_end);
897 RT_TIMING_GET_TIME(time_end);
899 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
900 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
906 /* builtin_java_new ************************************************************
908 NOTE: This is a SLOW builtin and can be called from JIT code only.
910 *******************************************************************************/
912 java_handle_t *builtin_java_new(java_handle_t *clazz)
914 return builtin_new(LLNI_classinfo_unwrap(clazz));
918 /* builtin_fast_new ************************************************************
920 Creates a new instance of class c on the heap.
923 pointer to the object, or NULL if no fast return
924 is possible for any reason.
926 NOTE: This is a FAST builtin and can be called from JIT code only.
928 *******************************************************************************/
930 java_object_t *builtin_fast_new(classinfo *c)
933 #if defined(ENABLE_RT_TIMING)
934 struct timespec time_start, time_end;
936 #if defined(ENABLE_CYCLES_STATS)
937 u8 cycles_start, cycles_end;
940 RT_TIMING_GET_TIME(time_start);
941 CYCLES_STATS_GET(cycles_start);
943 /* is the class loaded */
945 assert(c->state & CLASS_LOADED);
947 /* check if we can instantiate this class */
949 if (c->flags & ACC_ABSTRACT)
952 /* is the class linked */
954 if (!(c->state & CLASS_LINKED))
957 if (!(c->state & CLASS_INITIALIZED))
960 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
961 c->finalizer, false);
968 #if defined(ENABLE_THREADS)
969 lock_init_object_lock(o);
972 CYCLES_STATS_GET(cycles_end);
973 RT_TIMING_GET_TIME(time_end);
975 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
976 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
982 /* builtin_newarray ************************************************************
984 Creates an array with the given vftbl on the heap. This function
985 takes as class argument an array class.
988 pointer to the array or NULL if no memory is available
990 NOTE: This builtin can be called from NATIVE code only.
992 *******************************************************************************/
994 java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
996 arraydescriptor *desc;
1001 #if defined(ENABLE_RT_TIMING)
1002 struct timespec time_start, time_end;
1005 RT_TIMING_GET_TIME(time_start);
1007 desc = arrayclass->vftbl->arraydesc;
1008 dataoffset = desc->dataoffset;
1009 componentsize = desc->componentsize;
1012 exceptions_throw_negativearraysizeexception();
1016 actualsize = dataoffset + size * componentsize;
1018 /* check for overflow */
1020 if (((u4) actualsize) < ((u4) size)) {
1021 exceptions_throw_outofmemoryerror();
1025 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1030 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1031 /* XXX this is only a dirty hack to make Boehm work with handles */
1033 a = LLNI_WRAP((java_object_t *) a);
1036 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1038 #if defined(ENABLE_THREADS)
1039 lock_init_object_lock(LLNI_DIRECT(a));
1042 LLNI_array_size(a) = size;
1044 RT_TIMING_GET_TIME(time_end);
1045 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1051 /* builtin_java_newarray *******************************************************
1053 NOTE: This is a SLOW builtin and can be called from JIT code only.
1055 *******************************************************************************/
1057 java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
1059 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1063 /* builtin_anewarray ***********************************************************
1065 Creates an array of references to the given class type on the heap.
1068 pointer to the array or NULL if no memory is
1071 NOTE: This builtin can be called from NATIVE code only.
1073 *******************************************************************************/
1075 java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
1077 classinfo *arrayclass;
1079 /* is class loaded */
1081 assert(componentclass->state & CLASS_LOADED);
1083 /* is class linked */
1085 if (!(componentclass->state & CLASS_LINKED))
1086 if (!link_class(componentclass))
1089 arrayclass = class_array_of(componentclass, true);
1094 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1098 /* builtin_newarray_type ****************************************************
1100 Creates an array of [type]s on the heap.
1103 pointer to the array or NULL if no memory is available
1105 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1107 *******************************************************************************/
1109 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1110 java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
1112 return (java_handle_##type##array_t *) \
1113 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1116 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1117 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1118 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1119 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1120 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1121 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1122 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1123 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1126 /* builtin_multianewarray_intern ***********************************************
1128 Creates a multi-dimensional array on the heap. The dimensions are
1129 passed in an array of longs.
1132 n.............number of dimensions to create
1133 arrayclass....the array class
1134 dims..........array containing the size of each dimension to create
1137 pointer to the array or NULL if no memory is available
1139 ******************************************************************************/
1141 static java_handle_t *builtin_multianewarray_intern(int n,
1142 classinfo *arrayclass,
1147 classinfo *componentclass;
1150 /* create this dimension */
1152 size = (s4) dims[0];
1153 a = builtin_newarray(size, arrayclass);
1158 /* if this is the last dimension return */
1163 /* get the class of the components to create */
1165 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
1167 /* The verifier guarantees that the dimension count is in the range. */
1169 /* create the component arrays */
1171 for (i = 0; i < size; i++) {
1173 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1174 /* we save an s4 to a s8 slot, 8-byte aligned */
1176 builtin_multianewarray_intern(n, componentclass, dims + 2);
1178 builtin_multianewarray_intern(n, componentclass, dims + 1);
1184 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1191 /* builtin_multianewarray ******************************************************
1193 Wrapper for builtin_multianewarray_intern which checks all
1194 dimensions before we start allocating.
1196 NOTE: This is a SLOW builtin and can be called from JIT code only.
1198 ******************************************************************************/
1200 java_handle_objectarray_t *builtin_multianewarray(int n,
1201 java_handle_t *arrayclazz,
1208 /* check all dimensions before doing anything */
1210 for (i = 0; i < n; i++) {
1211 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1212 /* we save an s4 to a s8 slot, 8-byte aligned */
1213 size = (s4) dims[i * 2];
1215 size = (s4) dims[i];
1219 exceptions_throw_negativearraysizeexception();
1224 c = LLNI_classinfo_unwrap(arrayclazz);
1226 /* now call the real function */
1228 return (java_handle_objectarray_t *)
1229 builtin_multianewarray_intern(n, c, dims);
1233 /* builtin_verbosecall_enter ***************************************************
1235 Print method call with arguments for -verbose:call.
1237 XXX: Remove mew once all archs use the new tracer!
1239 *******************************************************************************/
1241 #if !defined(NDEBUG)
1242 #ifdef TRACE_ARGS_NUM
1243 void builtin_verbosecall_enter(s8 a0, s8 a1,
1244 # if TRACE_ARGS_NUM >= 4
1247 # if TRACE_ARGS_NUM >= 6
1250 # if TRACE_ARGS_NUM == 8
1255 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1258 #endif /* !defined(NDEBUG) */
1261 /* builtin_verbosecall_exit ****************************************************
1263 Print method exit for -verbose:call.
1265 XXX: Remove mew once all archs use the new tracer!
1267 *******************************************************************************/
1269 #if !defined(NDEBUG)
1270 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1272 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1274 #endif /* !defined(NDEBUG) */
1277 /*============================================================================*/
1278 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1279 /*============================================================================*/
1281 /*********** Functions for integer divisions *****************************
1283 On some systems (eg. DEC ALPHA), integer division is not supported by the
1284 CPU. These helper functions implement the missing functionality.
1286 ******************************************************************************/
1288 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1289 s4 builtin_idiv(s4 a, s4 b)
1298 s4 builtin_irem(s4 a, s4 b)
1306 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1309 /* functions for long arithmetics **********************************************
1311 On systems where 64 bit Integers are not supported by the CPU,
1312 these functions are needed.
1314 ******************************************************************************/
1316 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1317 s8 builtin_ladd(s8 a, s8 b)
1330 s8 builtin_lsub(s8 a, s8 b)
1343 s8 builtin_lneg(s8 a)
1355 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1358 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1359 s8 builtin_lmul(s8 a, s8 b)
1371 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1374 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1375 s8 builtin_ldiv(s8 a, s8 b)
1388 s8 builtin_lrem(s8 a, s8 b)
1400 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1403 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1404 s8 builtin_lshl(s8 a, s4 b)
1417 s8 builtin_lshr(s8 a, s4 b)
1430 s8 builtin_lushr(s8 a, s4 b)
1435 c = ((u8) a) >> (b & 63);
1442 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1445 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1446 s8 builtin_land(s8 a, s8 b)
1459 s8 builtin_lor(s8 a, s8 b)
1472 s8 builtin_lxor(s8 a, s8 b)
1484 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1487 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1488 s4 builtin_lcmp(s8 a, s8 b)
1502 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1505 /* functions for unsupported floating instructions ****************************/
1507 /* used to convert FLT_xxx defines into float values */
1509 static inline float intBitsToFloat(s4 i)
1518 /* used to convert DBL_xxx defines into double values */
1520 static inline float longBitsToDouble(s8 l)
1530 float builtin_fadd(float a, float b)
1532 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1533 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1544 if (copysignf(1.0, a) == copysignf(1.0, b))
1547 return intBitsToFloat(FLT_NAN);
1553 float builtin_fsub(float a, float b)
1555 return builtin_fadd(a, builtin_fneg(b));
1559 float builtin_fmul(float a, float b)
1561 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1562 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1564 if (finitef(b)) return a * b;
1566 if (a == 0) return intBitsToFloat(FLT_NAN);
1567 else return copysignf(b, copysignf(1.0, b)*a);
1572 if (b == 0) return intBitsToFloat(FLT_NAN);
1573 else return copysignf(a, copysignf(1.0, a)*b);
1576 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1582 /* builtin_ddiv ****************************************************************
1584 Implementation as described in VM Spec.
1586 *******************************************************************************/
1588 float builtin_fdiv(float a, float b)
1592 /* If neither value1' nor value2' is NaN, the sign of the result */
1593 /* is positive if both values have the same sign, negative if the */
1594 /* values have different signs. */
1600 /* If either value1' or value2' is NaN, the result is NaN. */
1602 return intBitsToFloat(FLT_NAN);
1605 /* Division of a finite value by an infinity results in a */
1606 /* signed zero, with the sign-producing rule just given. */
1608 /* is sign equal? */
1610 if (copysignf(1.0, a) == copysignf(1.0, b))
1619 /* If either value1' or value2' is NaN, the result is NaN. */
1621 return intBitsToFloat(FLT_NAN);
1623 } else if (finitef(b)) {
1624 /* Division of an infinity by a finite value results in a signed */
1625 /* infinity, with the sign-producing rule just given. */
1627 /* is sign equal? */
1629 if (copysignf(1.0, a) == copysignf(1.0, b))
1630 return intBitsToFloat(FLT_POSINF);
1632 return intBitsToFloat(FLT_NEGINF);
1635 /* Division of an infinity by an infinity results in NaN. */
1637 return intBitsToFloat(FLT_NAN);
1643 float builtin_fneg(float a)
1645 if (isnanf(a)) return a;
1647 if (finitef(a)) return -a;
1648 else return copysignf(a, -copysignf(1.0, a));
1651 #endif /* !SUPPORT_FLOAT */
1654 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1655 s4 builtin_fcmpl(float a, float b)
1663 if (!finitef(a) || !finitef(b)) {
1664 a = finitef(a) ? 0 : copysignf(1.0, a);
1665 b = finitef(b) ? 0 : copysignf(1.0, b);
1678 s4 builtin_fcmpg(float a, float b)
1680 if (isnanf(a)) return 1;
1681 if (isnanf(b)) return 1;
1682 if (!finitef(a) || !finitef(b)) {
1683 a = finitef(a) ? 0 : copysignf(1.0, a);
1684 b = finitef(b) ? 0 : copysignf(1.0, b);
1686 if (a > b) return 1;
1687 if (a == b) return 0;
1690 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1693 float builtin_frem(float a, float b)
1699 /* functions for unsupported double instructions ******************************/
1702 double builtin_dadd(double a, double b)
1704 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1705 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1707 if (finite(b)) return a + b;
1711 if (finite(b)) return a;
1713 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1714 else return longBitsToDouble(DBL_NAN);
1720 double builtin_dsub(double a, double b)
1722 return builtin_dadd(a, builtin_dneg(b));
1726 double builtin_dmul(double a, double b)
1728 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1729 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1731 if (finite(b)) return a * b;
1733 if (a == 0) return longBitsToDouble(DBL_NAN);
1734 else return copysign(b, copysign(1.0, b) * a);
1739 if (b == 0) return longBitsToDouble(DBL_NAN);
1740 else return copysign(a, copysign(1.0, a) * b);
1743 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1749 /* builtin_ddiv ****************************************************************
1751 Implementation as described in VM Spec.
1753 *******************************************************************************/
1755 double builtin_ddiv(double a, double b)
1759 /* If neither value1' nor value2' is NaN, the sign of the result */
1760 /* is positive if both values have the same sign, negative if the */
1761 /* values have different signs. */
1767 /* If either value1' or value2' is NaN, the result is NaN. */
1769 return longBitsToDouble(DBL_NAN);
1772 /* Division of a finite value by an infinity results in a */
1773 /* signed zero, with the sign-producing rule just given. */
1775 /* is sign equal? */
1777 if (copysign(1.0, a) == copysign(1.0, b))
1786 /* If either value1' or value2' is NaN, the result is NaN. */
1788 return longBitsToDouble(DBL_NAN);
1790 } else if (finite(b)) {
1791 /* Division of an infinity by a finite value results in a signed */
1792 /* infinity, with the sign-producing rule just given. */
1794 /* is sign equal? */
1796 if (copysign(1.0, a) == copysign(1.0, b))
1797 return longBitsToDouble(DBL_POSINF);
1799 return longBitsToDouble(DBL_NEGINF);
1802 /* Division of an infinity by an infinity results in NaN. */
1804 return longBitsToDouble(DBL_NAN);
1810 /* builtin_dneg ****************************************************************
1812 Implemented as described in VM Spec.
1814 *******************************************************************************/
1816 double builtin_dneg(double a)
1819 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1826 /* If the operand is a zero, the result is the zero of opposite */
1832 /* If the operand is an infinity, the result is the infinity of */
1833 /* opposite sign. */
1835 return copysign(a, -copysign(1.0, a));
1839 #endif /* !SUPPORT_DOUBLE */
1842 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1843 s4 builtin_dcmpl(double a, double b)
1851 if (!finite(a) || !finite(b)) {
1852 a = finite(a) ? 0 : copysign(1.0, a);
1853 b = finite(b) ? 0 : copysign(1.0, b);
1866 s4 builtin_dcmpg(double a, double b)
1874 if (!finite(a) || !finite(b)) {
1875 a = finite(a) ? 0 : copysign(1.0, a);
1876 b = finite(b) ? 0 : copysign(1.0, b);
1887 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1890 double builtin_drem(double a, double b)
1896 /* conversion operations ******************************************************/
1899 s8 builtin_i2l(s4 i)
1911 s4 builtin_l2i(s8 l)
1922 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1923 float builtin_i2f(s4 a)
1925 float f = (float) a;
1928 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1931 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1932 double builtin_i2d(s4 a)
1934 double d = (double) a;
1937 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1940 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1941 float builtin_l2f(s8 a)
1944 float f = (float) a;
1950 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1953 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1954 double builtin_l2d(s8 a)
1957 double d = (double) a;
1963 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1966 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1967 s4 builtin_f2i(float a)
1971 i = builtin_d2i((double) a);
1982 if (a < (-2147483648))
1983 return (-2147483648);
1986 f = copysignf((float) 1.0, a);
1989 return (-2147483648); */
1991 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1994 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1995 s8 builtin_f2l(float a)
1999 l = builtin_d2l((double) a);
2006 if (a > 9223372036854775807L)
2007 return 9223372036854775807L;
2008 if (a < (-9223372036854775808L))
2009 return (-9223372036854775808L);
2014 f = copysignf((float) 1.0, a);
2016 return 9223372036854775807L;
2017 return (-9223372036854775808L); */
2019 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2022 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2023 s4 builtin_d2i(double a)
2028 if (a >= 2147483647)
2030 if (a <= (-2147483647-1))
2031 return (-2147483647-1);
2036 d = copysign(1.0, a);
2039 return (-2147483647-1);
2041 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2044 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2045 s8 builtin_d2l(double a)
2050 if (a >= 9223372036854775807LL)
2051 return 9223372036854775807LL;
2052 if (a <= (-9223372036854775807LL-1))
2053 return (-9223372036854775807LL-1);
2058 d = copysign(1.0, a);
2060 return 9223372036854775807LL;
2061 return (-9223372036854775807LL-1);
2063 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2066 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2067 double builtin_f2d(float a)
2069 if (finitef(a)) return (double) a;
2072 return longBitsToDouble(DBL_NAN);
2074 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2078 float builtin_d2f(double a)
2084 return intBitsToFloat(FLT_NAN);
2086 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2089 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2092 /*============================================================================*/
2093 /* AUTOMATICALLY REPLACED FUNCTIONS */
2094 /*============================================================================*/
2096 /* builtin_arraycopy ***********************************************************
2098 Builtin for java.lang.System.arraycopy.
2100 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2102 *******************************************************************************/
2104 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2105 java_handle_t *dest, s4 destStart, s4 len)
2107 arraydescriptor *sdesc;
2108 arraydescriptor *ddesc;
2111 if ((src == NULL) || (dest == NULL)) {
2112 exceptions_throw_nullpointerexception();
2116 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2117 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2119 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2120 exceptions_throw_arraystoreexception();
2124 /* we try to throw exception with the same message as SUN does */
2126 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2127 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2128 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2129 exceptions_throw_arrayindexoutofboundsexception();
2133 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2134 /* We copy primitive values or references of exactly the same type */
2136 s4 dataoffset = sdesc->dataoffset;
2137 s4 componentsize = sdesc->componentsize;
2139 LLNI_CRITICAL_START;
2141 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2142 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2143 u1, (size_t) len * componentsize);
2148 /* We copy references of different type */
2150 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2151 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2153 if (destStart <= srcStart) {
2154 for (i = 0; i < len; i++) {
2157 o = array_objectarray_element_get(oas, srcStart + i);
2159 if (!builtin_canstore(oad, o))
2162 array_objectarray_element_set(oad, destStart + i, o);
2166 /* XXX this does not completely obey the specification!
2167 If an exception is thrown only the elements above the
2168 current index have been copied. The specification
2169 requires that only the elements *below* the current
2170 index have been copied before the throw. */
2172 for (i = len - 1; i >= 0; i--) {
2175 o = array_objectarray_element_get(oas, srcStart + i);
2177 if (!builtin_canstore(oad, o))
2180 array_objectarray_element_set(oad, destStart + i, o);
2187 /* builtin_nanotime ************************************************************
2189 Return the current time in nanoseconds.
2191 *******************************************************************************/
2193 s8 builtin_nanotime(void)
2198 if (gettimeofday(&tv, NULL) == -1)
2199 vm_abort("gettimeofday failed: %s", strerror(errno));
2201 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2203 return usecs * 1000;
2207 /* builtin_currenttimemillis ***************************************************
2209 Return the current time in milliseconds.
2211 *******************************************************************************/
2213 s8 builtin_currenttimemillis(void)
2217 msecs = builtin_nanotime() / 1000 / 1000;
2223 /* builtin_clone ***************************************************************
2225 Function for cloning objects or arrays.
2227 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2229 *******************************************************************************/
2231 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2233 arraydescriptor *ad;
2236 java_handle_t *co; /* cloned object header */
2238 /* get the array descriptor */
2240 ad = LLNI_vftbl_direct(o)->arraydesc;
2242 /* we are cloning an array */
2245 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2247 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2252 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2253 /* XXX this is only a dirty hack to make Boehm work with handles */
2255 co = LLNI_WRAP((java_object_t *) co);
2258 LLNI_CRITICAL_START;
2260 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2262 #if defined(ENABLE_GC_CACAO)
2263 heap_init_objectheader(LLNI_DIRECT(co), size);
2266 #if defined(ENABLE_THREADS)
2267 lock_init_object_lock(LLNI_DIRECT(co));
2275 /* we are cloning a non-array */
2277 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2278 exceptions_throw_clonenotsupportedexception();
2282 /* get the class of the object */
2284 LLNI_class_get(o, c);
2286 /* create new object */
2288 co = builtin_new(c);
2293 LLNI_CRITICAL_START;
2295 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2297 #if defined(ENABLE_GC_CACAO)
2298 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2301 #if defined(ENABLE_THREADS)
2302 lock_init_object_lock(LLNI_DIRECT(co));
2311 #if defined(ENABLE_CYCLES_STATS)
2312 void builtin_print_cycles_stats(FILE *file)
2314 fprintf(file,"builtin cylce count statistics:\n");
2316 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2317 CYCLES_STATS_PRINT(builtin_new ,file);
2321 #endif /* defined(ENABLE_CYCLES_STATS) */
2324 #if defined(ENABLE_VMLOG)
2326 #include <vmlog_cacao.c>
2331 * These are local overrides for various environment variables in Emacs.
2332 * Please do not remove this and leave it at the end of the file, where
2333 * Emacs will automagically detect them.
2334 * ---------------------------------------------------------------------
2337 * indent-tabs-mode: t
2341 * vim:noexpandtab:sw=4:ts=4: