1 /* src/vm/builtin.c - functions for unsupported operations
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine 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/threads-common.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 /* initialize the builtin tables */
271 if (!builtintable_init())
274 /* sort builtin tables */
276 builtintable_sort_automatic();
282 /* builtintable_get_internal ***************************************************
284 Finds an entry in the builtintable for internal functions and
285 returns the a pointer to the structure.
287 *******************************************************************************/
289 builtintable_entry *builtintable_get_internal(functionptr fp)
291 builtintable_entry *bte;
293 for (bte = builtintable_internal; bte->fp != NULL; bte++) {
302 /* builtintable_get_automatic **************************************************
304 Finds an entry in the builtintable for functions which are replaced
305 automatically and returns the a pointer to the structure.
307 *******************************************************************************/
309 builtintable_entry *builtintable_get_automatic(s4 opcode)
311 builtintable_entry *first;
312 builtintable_entry *last;
313 builtintable_entry *middle;
317 /* calculate table size statically (`- 1' comment see builtintable.inc) */
319 entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
321 first = builtintable_automatic;
322 last = builtintable_automatic + entries;
324 while (entries > 0) {
326 middle = first + half;
328 if (middle->opcode < opcode) {
336 return (first != last ? first : NULL);
340 /* builtintable_replace_function ***********************************************
344 *******************************************************************************/
346 #if defined(ENABLE_JIT)
347 bool builtintable_replace_function(void *iptr_)
350 builtintable_entry *bte;
353 iptr = (instruction *) iptr_; /* twisti will kill me ;) */
355 /* get name and descriptor of the function */
358 case ICMD_INVOKESTATIC:
359 /* The instruction MUST be resolved, otherwise we run into
360 lazy loading troubles. Anyway, we should/can only replace
361 very VM-close functions. */
363 if (INSTRUCTION_IS_UNRESOLVED(iptr))
366 mr = iptr->sx.s23.s3.fmiref;
373 /* search the function table */
375 for (bte = builtintable_function; bte->fp != NULL; bte++) {
376 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
377 (mr->name == bte->name) &&
378 (mr->descriptor == bte->descriptor)) {
380 /* set the values in the instruction */
382 iptr->opc = bte->opcode;
383 iptr->sx.s23.s3.bte = bte;
385 if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
386 iptr->flags.bits |= INS_FLAG_CHECK;
388 iptr->flags.bits &= ~INS_FLAG_CHECK;
396 #endif /* defined(ENABLE_JIT) */
399 /*============================================================================*/
400 /* INTERNAL BUILTIN FUNCTIONS */
401 /*============================================================================*/
403 /* builtin_instanceof **********************************************************
405 Checks if an object is an instance of some given class (or subclass
406 of that class). If class is an interface, checks if the interface
410 1......o is an instance of class or implements the interface
411 0......otherwise or if o == NULL
413 NOTE: This builtin can be called from NATIVE code only.
415 *******************************************************************************/
417 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
424 LLNI_class_get(o, c);
426 return class_isanysubclass(c, class);
431 /* builtin_checkcast ***********************************************************
433 The same as builtin_instanceof but with the exception
434 that 1 is returned when (o == NULL).
436 NOTE: This builtin can be called from NATIVE code only.
438 *******************************************************************************/
440 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
447 LLNI_class_get(o, c);
449 if (class_isanysubclass(c, class))
456 /* builtin_descriptorscompatible ***********************************************
458 Checks if two array type descriptors are assignment compatible.
461 1......target = desc is possible
464 *******************************************************************************/
466 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
467 arraydescriptor *target)
472 if (desc->arraytype != target->arraytype)
475 if (desc->arraytype != ARRAYTYPE_OBJECT)
478 /* {both arrays are arrays of references} */
480 if (desc->dimension == target->dimension) {
481 /* an array which contains elements of interface types is
482 allowed to be casted to Object (JOWENN)*/
484 if ((desc->elementvftbl->baseval < 0) &&
485 (target->elementvftbl->baseval == 1))
488 return class_isanysubclass(desc->elementvftbl->class,
489 target->elementvftbl->class);
492 if (desc->dimension < target->dimension)
495 /* {desc has higher dimension than target} */
497 return class_isanysubclass(pseudo_class_Arraystub,
498 target->elementvftbl->class);
502 /* builtin_arraycheckcast ******************************************************
504 Checks if an object is really a subtype of the requested array
505 type. The object has to be an array to begin with. For simple
506 arrays (int, short, double, etc.) the types have to match exactly.
507 For arrays of objects, the type of elements in the array has to be
508 a subtype (or the same type) of the requested element type. For
509 arrays of arrays (which in turn can again be arrays of arrays), the
510 types at the lowest level have to satisfy the corresponding sub
513 NOTE: This is a FAST builtin and can be called from JIT code only.
515 *******************************************************************************/
517 s4 builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
519 arraydescriptor *desc;
524 desc = o->vftbl->arraydesc;
529 return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
533 /* builtin_fast_arrayinstanceof ************************************************
535 NOTE: This is a FAST builtin and can be called from JIT code only.
537 *******************************************************************************/
539 s4 builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
544 return builtin_fast_arraycheckcast(o, targetclass);
548 /* builtin_arrayinstanceof *****************************************************
550 NOTE: This builtin can be called from NATIVE code only.
552 *******************************************************************************/
554 s4 builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
560 result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
568 /* builtin_throw_exception *****************************************************
570 Sets the exception pointer with the thrown exception and prints some
571 debugging information.
573 NOTE: This is a FAST builtin and can be called from JIT code,
574 or from asm_vm_call_method.
576 *******************************************************************************/
578 void *builtin_throw_exception(java_object_t *xptr)
581 /* print exception trace */
583 if (opt_TraceExceptions)
584 trace_exception_builtin(xptr);
585 #endif /* !defined(NDEBUG) */
587 /* actually set the exception */
589 exceptions_set_exception(LLNI_QUICKWRAP(xptr));
591 /* Return a NULL pointer. This is required for vm_call_method to
592 check for an exception. This is for convenience. */
598 /* builtin_retrieve_exception **************************************************
600 Gets and clears the exception pointer of the current thread.
603 the exception object, or NULL if no exception was thrown.
605 NOTE: This is a FAST builtin and can be called from JIT code,
606 or from the signal handlers.
608 *******************************************************************************/
610 java_object_t *builtin_retrieve_exception(void)
615 /* actually get and clear the exception */
617 h = exceptions_get_and_clear_exception();
624 /* builtin_canstore ************************************************************
626 Checks, if an object can be stored in an array.
630 0......otherwise (throws an ArrayStoreException)
632 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
634 *******************************************************************************/
636 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
642 result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
646 /* if not possible, throw an exception */
649 exceptions_throw_arraystoreexception();
655 /* builtin_fast_canstore *******************************************************
657 Checks, if an object can be stored in an array.
661 0......otherwise (no exception thrown!)
663 NOTE: This is a FAST builtin and can be called from JIT code only.
665 *******************************************************************************/
667 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
669 arraydescriptor *desc;
670 arraydescriptor *valuedesc;
671 vftbl_t *componentvftbl;
680 /* The following is guaranteed (by verifier checks):
682 * *) oa->...vftbl->arraydesc != NULL
683 * *) oa->...vftbl->arraydesc->componentvftbl != NULL
684 * *) o->vftbl is not an interface vftbl
687 desc = oa->header.objheader.vftbl->arraydesc;
688 componentvftbl = desc->componentvftbl;
689 valuevftbl = o->vftbl;
690 valuedesc = valuevftbl->arraydesc;
692 if ((desc->dimension - 1) == 0) {
693 /* {oa is a one-dimensional array} */
694 /* {oa is an array of references} */
696 if (valuevftbl == componentvftbl)
699 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
701 baseval = componentvftbl->baseval;
704 /* an array of interface references */
706 result = ((valuevftbl->interfacetablelength > -baseval) &&
707 (valuevftbl->interfacetable[baseval] != NULL));
710 diffval = valuevftbl->baseval - componentvftbl->baseval;
711 result = diffval <= (uint32_t) componentvftbl->diffval;
714 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
716 else if (valuedesc == NULL) {
717 /* {oa has dimension > 1} */
718 /* {componentvftbl->arraydesc != NULL} */
720 /* check if o is an array */
725 /* {o is an array} */
727 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
736 /* This is an optimized version where a is guaranteed to be one-dimensional */
737 s4 builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
739 arraydescriptor *desc;
740 vftbl_t *elementvftbl;
749 /* The following is guaranteed (by verifier checks):
751 * *) a->...vftbl->arraydesc != NULL
752 * *) a->...vftbl->arraydesc->elementvftbl != NULL
753 * *) a->...vftbl->arraydesc->dimension == 1
754 * *) o->vftbl is not an interface vftbl
757 desc = a->header.objheader.vftbl->arraydesc;
758 elementvftbl = desc->elementvftbl;
759 valuevftbl = o->vftbl;
761 /* {a is a one-dimensional array} */
763 if (valuevftbl == elementvftbl)
766 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
768 baseval = elementvftbl->baseval;
771 /* an array of interface references */
772 result = ((valuevftbl->interfacetablelength > -baseval) &&
773 (valuevftbl->interfacetable[baseval] != NULL));
776 diffval = valuevftbl->baseval - elementvftbl->baseval;
777 result = diffval <= (uint32_t) elementvftbl->diffval;
780 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
786 /* This is an optimized version where a is guaranteed to be a
787 * one-dimensional array of a class type */
788 s4 builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
790 vftbl_t *elementvftbl;
798 /* The following is guaranteed (by verifier checks):
800 * *) a->...vftbl->arraydesc != NULL
801 * *) a->...vftbl->arraydesc->elementvftbl != NULL
802 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
803 * *) a->...vftbl->arraydesc->dimension == 1
804 * *) o->vftbl is not an interface vftbl
807 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
808 valuevftbl = o->vftbl;
810 /* {a is a one-dimensional array} */
812 if (valuevftbl == elementvftbl)
815 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
817 diffval = valuevftbl->baseval - elementvftbl->baseval;
818 result = diffval <= (uint32_t) elementvftbl->diffval;
820 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
826 /* builtin_new *****************************************************************
828 Creates a new instance of class c on the heap.
831 pointer to the object, or NULL if no memory is available
833 NOTE: This builtin can be called from NATIVE code only.
835 *******************************************************************************/
837 java_handle_t *builtin_new(classinfo *c)
840 #if defined(ENABLE_RT_TIMING)
841 struct timespec time_start, time_end;
843 #if defined(ENABLE_CYCLES_STATS)
844 u8 cycles_start, cycles_end;
847 RT_TIMING_GET_TIME(time_start);
848 CYCLES_STATS_GET(cycles_start);
850 /* is the class loaded */
852 assert(c->state & CLASS_LOADED);
854 /* check if we can instantiate this class */
856 if (c->flags & ACC_ABSTRACT) {
857 exceptions_throw_instantiationerror(c);
861 /* is the class linked */
863 if (!(c->state & CLASS_LINKED))
867 if (!(c->state & CLASS_INITIALIZED)) {
870 log_message_class("Initialize class (from builtin_new): ", c);
873 if (!initialize_class(c))
877 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
883 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
884 /* XXX this is only a dirty hack to make Boehm work with handles */
886 o = LLNI_WRAP((java_object_t *) o);
889 LLNI_vftbl_direct(o) = c->vftbl;
891 #if defined(ENABLE_THREADS)
892 lock_init_object_lock(LLNI_DIRECT(o));
895 CYCLES_STATS_GET(cycles_end);
896 RT_TIMING_GET_TIME(time_end);
898 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
899 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
905 /* builtin_java_new ************************************************************
907 NOTE: This is a SLOW builtin and can be called from JIT code only.
909 *******************************************************************************/
911 java_handle_t *builtin_java_new(java_handle_t *clazz)
913 return builtin_new(LLNI_classinfo_unwrap(clazz));
917 /* builtin_fast_new ************************************************************
919 Creates a new instance of class c on the heap.
922 pointer to the object, or NULL if no fast return
923 is possible for any reason.
925 NOTE: This is a FAST builtin and can be called from JIT code only.
927 *******************************************************************************/
929 java_object_t *builtin_fast_new(classinfo *c)
932 #if defined(ENABLE_RT_TIMING)
933 struct timespec time_start, time_end;
935 #if defined(ENABLE_CYCLES_STATS)
936 u8 cycles_start, cycles_end;
939 RT_TIMING_GET_TIME(time_start);
940 CYCLES_STATS_GET(cycles_start);
942 /* is the class loaded */
944 assert(c->state & CLASS_LOADED);
946 /* check if we can instantiate this class */
948 if (c->flags & ACC_ABSTRACT)
951 /* is the class linked */
953 if (!(c->state & CLASS_LINKED))
956 if (!(c->state & CLASS_INITIALIZED))
959 o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
960 c->finalizer, false);
967 #if defined(ENABLE_THREADS)
968 lock_init_object_lock(o);
971 CYCLES_STATS_GET(cycles_end);
972 RT_TIMING_GET_TIME(time_end);
974 CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
975 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
981 /* builtin_newarray ************************************************************
983 Creates an array with the given vftbl on the heap. This function
984 takes as class argument an array class.
987 pointer to the array or NULL if no memory is available
989 NOTE: This builtin can be called from NATIVE code only.
991 *******************************************************************************/
993 java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
995 arraydescriptor *desc;
1000 #if defined(ENABLE_RT_TIMING)
1001 struct timespec time_start, time_end;
1004 RT_TIMING_GET_TIME(time_start);
1006 desc = arrayclass->vftbl->arraydesc;
1007 dataoffset = desc->dataoffset;
1008 componentsize = desc->componentsize;
1011 exceptions_throw_negativearraysizeexception();
1015 actualsize = dataoffset + size * componentsize;
1017 /* check for overflow */
1019 if (((u4) actualsize) < ((u4) size)) {
1020 exceptions_throw_outofmemoryerror();
1024 a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
1029 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
1030 /* XXX this is only a dirty hack to make Boehm work with handles */
1032 a = LLNI_WRAP((java_object_t *) a);
1035 LLNI_vftbl_direct(a) = arrayclass->vftbl;
1037 #if defined(ENABLE_THREADS)
1038 lock_init_object_lock(LLNI_DIRECT(a));
1041 LLNI_array_size(a) = size;
1043 RT_TIMING_GET_TIME(time_end);
1044 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
1050 /* builtin_java_newarray *******************************************************
1052 NOTE: This is a SLOW builtin and can be called from JIT code only.
1054 *******************************************************************************/
1056 java_handle_t *builtin_java_newarray(s4 size, java_handle_t *arrayclazz)
1058 return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
1062 /* builtin_anewarray ***********************************************************
1064 Creates an array of references to the given class type on the heap.
1067 pointer to the array or NULL if no memory is
1070 NOTE: This builtin can be called from NATIVE code only.
1072 *******************************************************************************/
1074 java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
1076 classinfo *arrayclass;
1078 /* is class loaded */
1080 assert(componentclass->state & CLASS_LOADED);
1082 /* is class linked */
1084 if (!(componentclass->state & CLASS_LINKED))
1085 if (!link_class(componentclass))
1088 arrayclass = class_array_of(componentclass, true);
1093 return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
1097 /* builtin_newarray_type ****************************************************
1099 Creates an array of [type]s on the heap.
1102 pointer to the array or NULL if no memory is available
1104 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
1106 *******************************************************************************/
1108 #define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
1109 java_handle_##type##array_t *builtin_newarray_##type(s4 size) \
1111 return (java_handle_##type##array_t *) \
1112 builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
1115 BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
1116 BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
1117 BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
1118 BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
1119 BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
1120 BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
1121 BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
1122 BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
1125 /* builtin_multianewarray_intern ***********************************************
1127 Creates a multi-dimensional array on the heap. The dimensions are
1128 passed in an array of longs.
1131 n.............number of dimensions to create
1132 arrayclass....the array class
1133 dims..........array containing the size of each dimension to create
1136 pointer to the array or NULL if no memory is available
1138 ******************************************************************************/
1140 static java_handle_t *builtin_multianewarray_intern(int n,
1141 classinfo *arrayclass,
1146 classinfo *componentclass;
1149 /* create this dimension */
1151 size = (s4) dims[0];
1152 a = builtin_newarray(size, arrayclass);
1157 /* if this is the last dimension return */
1162 /* get the class of the components to create */
1164 componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1166 /* The verifier guarantees that the dimension count is in the range. */
1168 /* create the component arrays */
1170 for (i = 0; i < size; i++) {
1172 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1173 /* we save an s4 to a s8 slot, 8-byte aligned */
1175 builtin_multianewarray_intern(n, componentclass, dims + 2);
1177 builtin_multianewarray_intern(n, componentclass, dims + 1);
1183 array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
1190 /* builtin_multianewarray ******************************************************
1192 Wrapper for builtin_multianewarray_intern which checks all
1193 dimensions before we start allocating.
1195 NOTE: This is a SLOW builtin and can be called from JIT code only.
1197 ******************************************************************************/
1199 java_handle_objectarray_t *builtin_multianewarray(int n,
1200 java_handle_t *arrayclazz,
1207 /* check all dimensions before doing anything */
1209 for (i = 0; i < n; i++) {
1210 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1211 /* we save an s4 to a s8 slot, 8-byte aligned */
1212 size = (s4) dims[i * 2];
1214 size = (s4) dims[i];
1218 exceptions_throw_negativearraysizeexception();
1223 c = LLNI_classinfo_unwrap(arrayclazz);
1225 /* now call the real function */
1227 return (java_handle_objectarray_t *)
1228 builtin_multianewarray_intern(n, c, dims);
1232 /* builtin_verbosecall_enter ***************************************************
1234 Print method call with arguments for -verbose:call.
1236 XXX: Remove mew once all archs use the new tracer!
1238 *******************************************************************************/
1240 #if !defined(NDEBUG)
1241 #ifdef TRACE_ARGS_NUM
1242 void builtin_verbosecall_enter(s8 a0, s8 a1,
1243 # if TRACE_ARGS_NUM >= 4
1246 # if TRACE_ARGS_NUM >= 6
1249 # if TRACE_ARGS_NUM == 8
1254 log_text("builtin_verbosecall_enter: Do not call me anymore!");
1257 #endif /* !defined(NDEBUG) */
1260 /* builtin_verbosecall_exit ****************************************************
1262 Print method exit for -verbose:call.
1264 XXX: Remove mew once all archs use the new tracer!
1266 *******************************************************************************/
1268 #if !defined(NDEBUG)
1269 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1271 log_text("builtin_verbosecall_exit: Do not call me anymore!");
1273 #endif /* !defined(NDEBUG) */
1276 /*============================================================================*/
1277 /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
1278 /*============================================================================*/
1280 /*********** Functions for integer divisions *****************************
1282 On some systems (eg. DEC ALPHA), integer division is not supported by the
1283 CPU. These helper functions implement the missing functionality.
1285 ******************************************************************************/
1287 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1288 s4 builtin_idiv(s4 a, s4 b)
1297 s4 builtin_irem(s4 a, s4 b)
1305 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1308 /* functions for long arithmetics **********************************************
1310 On systems where 64 bit Integers are not supported by the CPU,
1311 these functions are needed.
1313 ******************************************************************************/
1315 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1316 s8 builtin_ladd(s8 a, s8 b)
1329 s8 builtin_lsub(s8 a, s8 b)
1342 s8 builtin_lneg(s8 a)
1354 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1357 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1358 s8 builtin_lmul(s8 a, s8 b)
1370 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1373 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1374 s8 builtin_ldiv(s8 a, s8 b)
1387 s8 builtin_lrem(s8 a, s8 b)
1399 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1402 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1403 s8 builtin_lshl(s8 a, s4 b)
1416 s8 builtin_lshr(s8 a, s4 b)
1429 s8 builtin_lushr(s8 a, s4 b)
1434 c = ((u8) a) >> (b & 63);
1441 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1444 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1445 s8 builtin_land(s8 a, s8 b)
1458 s8 builtin_lor(s8 a, s8 b)
1471 s8 builtin_lxor(s8 a, s8 b)
1483 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1486 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1487 s4 builtin_lcmp(s8 a, s8 b)
1501 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1504 /* functions for unsupported floating instructions ****************************/
1506 /* used to convert FLT_xxx defines into float values */
1508 static inline float intBitsToFloat(s4 i)
1517 /* used to convert DBL_xxx defines into double values */
1519 static inline float longBitsToDouble(s8 l)
1529 float builtin_fadd(float a, float b)
1531 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1532 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1543 if (copysignf(1.0, a) == copysignf(1.0, b))
1546 return intBitsToFloat(FLT_NAN);
1552 float builtin_fsub(float a, float b)
1554 return builtin_fadd(a, builtin_fneg(b));
1558 float builtin_fmul(float a, float b)
1560 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1561 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1563 if (finitef(b)) return a * b;
1565 if (a == 0) return intBitsToFloat(FLT_NAN);
1566 else return copysignf(b, copysignf(1.0, b)*a);
1571 if (b == 0) return intBitsToFloat(FLT_NAN);
1572 else return copysignf(a, copysignf(1.0, a)*b);
1575 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1581 /* builtin_ddiv ****************************************************************
1583 Implementation as described in VM Spec.
1585 *******************************************************************************/
1587 float builtin_fdiv(float a, float b)
1591 /* If neither value1' nor value2' is NaN, the sign of the result */
1592 /* is positive if both values have the same sign, negative if the */
1593 /* values have different signs. */
1599 /* If either value1' or value2' is NaN, the result is NaN. */
1601 return intBitsToFloat(FLT_NAN);
1604 /* Division of a finite value by an infinity results in a */
1605 /* signed zero, with the sign-producing rule just given. */
1607 /* is sign equal? */
1609 if (copysignf(1.0, a) == copysignf(1.0, b))
1618 /* If either value1' or value2' is NaN, the result is NaN. */
1620 return intBitsToFloat(FLT_NAN);
1622 } else if (finitef(b)) {
1623 /* Division of an infinity by a finite value results in a signed */
1624 /* infinity, with the sign-producing rule just given. */
1626 /* is sign equal? */
1628 if (copysignf(1.0, a) == copysignf(1.0, b))
1629 return intBitsToFloat(FLT_POSINF);
1631 return intBitsToFloat(FLT_NEGINF);
1634 /* Division of an infinity by an infinity results in NaN. */
1636 return intBitsToFloat(FLT_NAN);
1642 float builtin_fneg(float a)
1644 if (isnanf(a)) return a;
1646 if (finitef(a)) return -a;
1647 else return copysignf(a, -copysignf(1.0, a));
1650 #endif /* !SUPPORT_FLOAT */
1653 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
1654 s4 builtin_fcmpl(float a, float b)
1662 if (!finitef(a) || !finitef(b)) {
1663 a = finitef(a) ? 0 : copysignf(1.0, a);
1664 b = finitef(b) ? 0 : copysignf(1.0, b);
1677 s4 builtin_fcmpg(float a, float b)
1679 if (isnanf(a)) return 1;
1680 if (isnanf(b)) return 1;
1681 if (!finitef(a) || !finitef(b)) {
1682 a = finitef(a) ? 0 : copysignf(1.0, a);
1683 b = finitef(b) ? 0 : copysignf(1.0, b);
1685 if (a > b) return 1;
1686 if (a == b) return 0;
1689 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
1692 float builtin_frem(float a, float b)
1698 /* functions for unsupported double instructions ******************************/
1701 double builtin_dadd(double a, double b)
1703 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1704 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1706 if (finite(b)) return a + b;
1710 if (finite(b)) return a;
1712 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1713 else return longBitsToDouble(DBL_NAN);
1719 double builtin_dsub(double a, double b)
1721 return builtin_dadd(a, builtin_dneg(b));
1725 double builtin_dmul(double a, double b)
1727 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1728 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1730 if (finite(b)) return a * b;
1732 if (a == 0) return longBitsToDouble(DBL_NAN);
1733 else return copysign(b, copysign(1.0, b) * a);
1738 if (b == 0) return longBitsToDouble(DBL_NAN);
1739 else return copysign(a, copysign(1.0, a) * b);
1742 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1748 /* builtin_ddiv ****************************************************************
1750 Implementation as described in VM Spec.
1752 *******************************************************************************/
1754 double builtin_ddiv(double a, double b)
1758 /* If neither value1' nor value2' is NaN, the sign of the result */
1759 /* is positive if both values have the same sign, negative if the */
1760 /* values have different signs. */
1766 /* If either value1' or value2' is NaN, the result is NaN. */
1768 return longBitsToDouble(DBL_NAN);
1771 /* Division of a finite value by an infinity results in a */
1772 /* signed zero, with the sign-producing rule just given. */
1774 /* is sign equal? */
1776 if (copysign(1.0, a) == copysign(1.0, b))
1785 /* If either value1' or value2' is NaN, the result is NaN. */
1787 return longBitsToDouble(DBL_NAN);
1789 } else if (finite(b)) {
1790 /* Division of an infinity by a finite value results in a signed */
1791 /* infinity, with the sign-producing rule just given. */
1793 /* is sign equal? */
1795 if (copysign(1.0, a) == copysign(1.0, b))
1796 return longBitsToDouble(DBL_POSINF);
1798 return longBitsToDouble(DBL_NEGINF);
1801 /* Division of an infinity by an infinity results in NaN. */
1803 return longBitsToDouble(DBL_NAN);
1809 /* builtin_dneg ****************************************************************
1811 Implemented as described in VM Spec.
1813 *******************************************************************************/
1815 double builtin_dneg(double a)
1818 /* If the operand is NaN, the result is NaN (recall that NaN has no */
1825 /* If the operand is a zero, the result is the zero of opposite */
1831 /* If the operand is an infinity, the result is the infinity of */
1832 /* opposite sign. */
1834 return copysign(a, -copysign(1.0, a));
1838 #endif /* !SUPPORT_DOUBLE */
1841 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
1842 s4 builtin_dcmpl(double a, double b)
1850 if (!finite(a) || !finite(b)) {
1851 a = finite(a) ? 0 : copysign(1.0, a);
1852 b = finite(b) ? 0 : copysign(1.0, b);
1865 s4 builtin_dcmpg(double a, double b)
1873 if (!finite(a) || !finite(b)) {
1874 a = finite(a) ? 0 : copysign(1.0, a);
1875 b = finite(b) ? 0 : copysign(1.0, b);
1886 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
1889 double builtin_drem(double a, double b)
1895 /* conversion operations ******************************************************/
1898 s8 builtin_i2l(s4 i)
1910 s4 builtin_l2i(s8 l)
1921 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
1922 float builtin_i2f(s4 a)
1924 float f = (float) a;
1927 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
1930 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
1931 double builtin_i2d(s4 a)
1933 double d = (double) a;
1936 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
1939 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
1940 float builtin_l2f(s8 a)
1943 float f = (float) a;
1949 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
1952 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
1953 double builtin_l2d(s8 a)
1956 double d = (double) a;
1962 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
1965 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
1966 s4 builtin_f2i(float a)
1970 i = builtin_d2i((double) a);
1981 if (a < (-2147483648))
1982 return (-2147483648);
1985 f = copysignf((float) 1.0, a);
1988 return (-2147483648); */
1990 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
1993 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
1994 s8 builtin_f2l(float a)
1998 l = builtin_d2l((double) a);
2005 if (a > 9223372036854775807L)
2006 return 9223372036854775807L;
2007 if (a < (-9223372036854775808L))
2008 return (-9223372036854775808L);
2013 f = copysignf((float) 1.0, a);
2015 return 9223372036854775807L;
2016 return (-9223372036854775808L); */
2018 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2021 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2022 s4 builtin_d2i(double a)
2027 if (a >= 2147483647)
2029 if (a <= (-2147483647-1))
2030 return (-2147483647-1);
2035 d = copysign(1.0, a);
2038 return (-2147483647-1);
2040 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2043 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2044 s8 builtin_d2l(double a)
2049 if (a >= 9223372036854775807LL)
2050 return 9223372036854775807LL;
2051 if (a <= (-9223372036854775807LL-1))
2052 return (-9223372036854775807LL-1);
2057 d = copysign(1.0, a);
2059 return 9223372036854775807LL;
2060 return (-9223372036854775807LL-1);
2062 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2065 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2066 double builtin_f2d(float a)
2068 if (finitef(a)) return (double) a;
2071 return longBitsToDouble(DBL_NAN);
2073 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2077 float builtin_d2f(double a)
2083 return intBitsToFloat(FLT_NAN);
2085 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2088 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2091 /*============================================================================*/
2092 /* AUTOMATICALLY REPLACED FUNCTIONS */
2093 /*============================================================================*/
2095 /* builtin_arraycopy ***********************************************************
2097 Builtin for java.lang.System.arraycopy.
2099 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2101 *******************************************************************************/
2103 void builtin_arraycopy(java_handle_t *src, s4 srcStart,
2104 java_handle_t *dest, s4 destStart, s4 len)
2106 arraydescriptor *sdesc;
2107 arraydescriptor *ddesc;
2110 if ((src == NULL) || (dest == NULL)) {
2111 exceptions_throw_nullpointerexception();
2115 sdesc = LLNI_vftbl_direct(src)->arraydesc;
2116 ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2118 if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2119 exceptions_throw_arraystoreexception();
2123 /* we try to throw exception with the same message as SUN does */
2125 if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2126 (srcStart + len < 0) || (srcStart + len > LLNI_array_size(src)) ||
2127 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2128 exceptions_throw_arrayindexoutofboundsexception();
2132 if (sdesc->componentvftbl == ddesc->componentvftbl) {
2133 /* We copy primitive values or references of exactly the same type */
2135 s4 dataoffset = sdesc->dataoffset;
2136 s4 componentsize = sdesc->componentsize;
2138 LLNI_CRITICAL_START;
2140 MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
2141 ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
2142 u1, (size_t) len * componentsize);
2147 /* We copy references of different type */
2149 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2150 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2152 if (destStart <= srcStart) {
2153 for (i = 0; i < len; i++) {
2156 o = array_objectarray_element_get(oas, srcStart + i);
2158 if (!builtin_canstore(oad, o))
2161 array_objectarray_element_set(oad, destStart + i, o);
2165 /* XXX this does not completely obey the specification!
2166 If an exception is thrown only the elements above the
2167 current index have been copied. The specification
2168 requires that only the elements *below* the current
2169 index have been copied before the throw. */
2171 for (i = len - 1; i >= 0; i--) {
2174 o = array_objectarray_element_get(oas, srcStart + i);
2176 if (!builtin_canstore(oad, o))
2179 array_objectarray_element_set(oad, destStart + i, o);
2186 /* builtin_nanotime ************************************************************
2188 Return the current time in nanoseconds.
2190 *******************************************************************************/
2192 s8 builtin_nanotime(void)
2197 if (gettimeofday(&tv, NULL) == -1)
2198 vm_abort("gettimeofday failed: %s", strerror(errno));
2200 usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2202 return usecs * 1000;
2206 /* builtin_currenttimemillis ***************************************************
2208 Return the current time in milliseconds.
2210 *******************************************************************************/
2212 s8 builtin_currenttimemillis(void)
2216 msecs = builtin_nanotime() / 1000 / 1000;
2222 /* builtin_clone ***************************************************************
2224 Function for cloning objects or arrays.
2226 NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
2228 *******************************************************************************/
2230 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2232 arraydescriptor *ad;
2235 java_handle_t *co; /* cloned object header */
2237 /* get the array descriptor */
2239 ad = LLNI_vftbl_direct(o)->arraydesc;
2241 /* we are cloning an array */
2244 size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
2246 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2251 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
2252 /* XXX this is only a dirty hack to make Boehm work with handles */
2254 co = LLNI_WRAP((java_object_t *) co);
2257 LLNI_CRITICAL_START;
2259 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
2261 #if defined(ENABLE_GC_CACAO)
2262 heap_init_objectheader(LLNI_DIRECT(co), size);
2265 #if defined(ENABLE_THREADS)
2266 lock_init_object_lock(LLNI_DIRECT(co));
2274 /* we are cloning a non-array */
2276 if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2277 exceptions_throw_clonenotsupportedexception();
2281 /* get the class of the object */
2283 LLNI_class_get(o, c);
2285 /* create new object */
2287 co = builtin_new(c);
2292 LLNI_CRITICAL_START;
2294 MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
2296 #if defined(ENABLE_GC_CACAO)
2297 heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
2300 #if defined(ENABLE_THREADS)
2301 lock_init_object_lock(LLNI_DIRECT(co));
2310 #if defined(ENABLE_CYCLES_STATS)
2311 void builtin_print_cycles_stats(FILE *file)
2313 fprintf(file,"builtin cylce count statistics:\n");
2315 CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
2316 CYCLES_STATS_PRINT(builtin_new ,file);
2320 #endif /* defined(ENABLE_CYCLES_STATS) */
2323 #if defined(ENABLE_VMLOG)
2325 #include <vmlog_cacao.c>
2330 * These are local overrides for various environment variables in Emacs.
2331 * Please do not remove this and leave it at the end of the file, where
2332 * Emacs will automagically detect them.
2333 * ---------------------------------------------------------------------
2336 * indent-tabs-mode: t
2340 * vim:noexpandtab:sw=4:ts=4: