* Updated to jitcache-arm-x86 branch d4f6023b26c5+d1b5b1c106ac
authorRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:17:15 +0000 (16:17 +0200)
committerRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:17:15 +0000 (16:17 +0200)
--HG--
branch : jitcache-arm-x86
rename : src/vm/builtin.c => src/vm/jit/builtin.cpp
rename : src/vm/builtin.h => src/vm/jit/builtin.hpp
rename : src/vm/jit/code.c => src/vm/jit/code.cpp
rename : src/vm/jit/code.h => src/vm/jit/code.hpp
rename : src/vm/jit/codegen-common.c => src/vm/jit/codegen-common.cpp
rename : src/vm/jit/jit.c => src/vm/jit/jit.cpp
rename : src/vm/jit/patcher-common.c => src/vm/jit/patcher-common.cpp
rename : src/vm/jit/patcher-common.h => src/vm/jit/patcher-common.hpp

27 files changed:
1  2 
configure.ac
src/vm/class.c
src/vm/class.h
src/vm/jit/Makefile.am
src/vm/jit/arm/codegen.c
src/vm/jit/arm/patcher.c
src/vm/jit/builtin.cpp
src/vm/jit/builtin.hpp
src/vm/jit/code.cpp
src/vm/jit/code.hpp
src/vm/jit/codegen-common.cpp
src/vm/jit/i386/codegen.c
src/vm/jit/i386/patcher.c
src/vm/jit/jit.cpp
src/vm/jit/jitcache.cpp
src/vm/jit/jitcache.hpp
src/vm/jit/linenumbertable.hpp
src/vm/jit/patcher-common.cpp
src/vm/jit/patcher-common.hpp
src/vm/options.c
src/vm/options.h
src/vm/os.hpp
src/vm/references.h
src/vm/resolve.c
src/vm/statistics.c
src/vm/statistics.h
src/vm/vm.cpp

diff --cc configure.ac
Simple merge
diff --cc src/vm/class.c
index a775a758a6ba884c1e135bb8c2bfbbe7f57de671,1774c3ac0f6fdd46d20cd2578176fae8b9538a12..1fa771c7b2e013a8689ed1cd64d01a152825736b
@@@ -50,9 -51,8 +51,9 @@@
  #include "vm/global.h"
  #include "vm/globals.hpp"
  #include "vm/javaobjects.hpp"
 +#include "vm/jit/jitcache.hpp"
  #include "vm/linker.h"
- #include "vm/loader.h"
+ #include "vm/loader.hpp"
  #include "vm/options.h"
  #include "vm/resolve.h"
  
@@@ -176,11 -176,8 +177,11 @@@ classinfo *class_create_classinfo(utf *
  
        if (classname != utf_not_named_yet)
                class_set_packagename(c);
 +#if defined (ENABLE_JITCACHE)
 +    c->cache_file_fd = 0;
 +#endif
  
-       LOCK_INIT_OBJECT_LOCK(&c->object.header);
+       Lockword_init(&(c->object.header.lockword));
  
        return c;
  }
diff --cc src/vm/class.h
Simple merge
index 6b248b46610f51badd4037d14cde9d014055ff16,ce48bfff76f1f82a75b9aca5e1209cc6f3469d3c..c8d27ba749d5334d83230a0ae1d4c9c6e27790f8
@@@ -114,17 -114,9 +114,17 @@@ TRAP_SOURCES = 
        trap.h
  endif
  
 +if ENABLE_JITCACHE
 +JITCACHE_SOURCES = \
 +      jitcache.cpp \
 +      jitcache.hpp
 +
 +endif
 +
 +
  if ENABLE_REPLACEMENT
  REPLACE_SOURCES += \
-       replace.c
+       replace.cpp
  endif
  
  if ENABLE_VERIFIER
@@@ -181,14 -175,13 +183,14 @@@ libjit_la_SOURCES = 
        methodtree.h \
        parse.c \
        parse.h \
-       patcher-common.c \
-       patcher-common.h \
+       patcher-common.cpp \
+       patcher-common.hpp \
        $(RECOMPILE_SOURCES) \
        $(REG_SOURCES) \
 +      $(JITCACHE_SOURCES) \
        $(REPLACE_SOURCES) \
-       show.c \
-       show.h \
+       show.cpp \
+       show.hpp \
        $(STACK_SOURCES) \
        stacktrace.cpp \
        stacktrace.hpp \
index c62b078f730dcf2be55dc1496c0a60e6e6123c9c,09f3d0b5f2cb5c0d260d06faa7a807b5963748db..efe6d3d746eac7d775dae8bc56eb9495294cb972
  
  #include "vm/jit/abi.h"
  #include "vm/jit/asmpart.h"
- #include "vm/jit/codegen-common.h"
+ #include "vm/jit/codegen-common.hpp"
  #include "vm/jit/dseg.h"
- #include "vm/jit/emit-common.h"
- #include "vm/jit/jit.h"
+ #include "vm/jit/emit-common.hpp"
+ #include "vm/jit/jit.hpp"
 +#include "vm/jit/jitcache.hpp"
- #include "vm/jit/linenumbertable.h"
+ #include "vm/jit/linenumbertable.hpp"
  #include "vm/jit/methodheader.h"
  #include "vm/jit/parse.h"
- #include "vm/jit/patcher-common.h"
+ #include "vm/jit/patcher-common.hpp"
  #include "vm/jit/reg.h"
  
  #if defined(ENABLE_LSRA)
Simple merge
index 0000000000000000000000000000000000000000,c735a277c54f1b14aee2f8a5d3de7638f15cd50e..f4d23e8eb90c3fd8bceab46c14a26f230851ec21
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2340 +1,2415 @@@
+ /* src/vm/jit/builtin.cpp - functions for unsupported operations
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+    Contains C functions for JavaVM Instructions that cannot be
+    translated to machine language directly. Consequently, the
+    generated machine code for these instructions contains function
+    calls instead of machine instructions, using the C calling
+    convention.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/time.h>
+ #include "vm/types.h"
+ #include "arch.h"
+ #include "md-abi.h"
+ #include "fdlibm/fdlibm.h"
+ #if defined(__CYGWIN__) && defined(Bias)
+ # undef Bias
+ #endif
+ #include "mm/gc.hpp"
+ #include "mm/memory.h"
+ #include "native/llni.h"
+ #include "threads/lock.hpp"
+ #include "threads/mutex.hpp"
+ #include "threads/thread.hpp"
+ #include "toolbox/logging.h"
+ #include "toolbox/util.h"
+ #include "vm/array.hpp"
+ #include "vm/jit/builtin.hpp"
+ #include "vm/class.h"
+ #include "vm/cycles-stats.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/initialize.h"
+ #include "vm/linker.h"
+ #include "vm/loader.hpp"
+ #include "vm/options.h"
+ #include "vm/primitive.hpp"
+ #include "vm/rt-timing.h"
+ #include "vm/string.hpp"
+ #include "vm/jit/asmpart.h"
+ #include "vm/jit/stubs.hpp"
+ #include "vm/jit/trace.hpp"
+ #if defined(ENABLE_VMLOG)
+ #include <vmlog_cacao.h>
+ #endif
+ /* include builtin tables *****************************************************/
+ #include "vm/jit/builtintable.inc"
+ CYCLES_STATS_DECLARE(builtin_new         ,100,5)
+ CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
+ /*============================================================================*/
+ /* BUILTIN TABLE MANAGEMENT FUNCTIONS                                         */
+ /*============================================================================*/
+ /* builtintable_init ***********************************************************
+    Parse the descriptors of builtin functions and create the parsed
+    descriptors.
+ *******************************************************************************/
+ static bool builtintable_init(void)
+ {
+       descriptor_pool    *descpool;
+       builtintable_entry *bte;
+       methodinfo         *m;
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+       /* create a new descriptor pool */
+       descpool = descriptor_pool_new(class_java_lang_Object);
+       /* add some entries we need */
+       if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
+               return false;
+       if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
+               return false;
+       /* first add all descriptors to the pool */
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               bte->name       = utf_new_char(bte->cname);
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               bte->classname  = utf_new_char(bte->cclassname);
+               bte->name       = utf_new_char(bte->cname);
+               bte->descriptor = utf_new_char(bte->cdescriptor);
+               if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+                       return false;
+       }
+       /* create the class reference table */
+       (void) descriptor_pool_create_classrefs(descpool, NULL);
+       /* allocate space for the parsed descriptors */
+       descriptor_pool_alloc_parsed_descriptors(descpool);
+       /* Now parse all descriptors.  NOTE: builtin-functions are treated
+          like static methods (no `this' pointer). */
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+               /* generate a builtin stub if we need one */
+               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+                       m = method_new_builtin(bte);
+                       BuiltinStub::generate(m, bte);
+               }
+       }
+       for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+               /* no stubs should be needed for this table */
+               assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
+       }
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+               /* generate a builtin stub if we need one */
+               if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+                       m = method_new_builtin(bte);
+                       BuiltinStub::generate(m, bte);
+               }
+       }
+       return true;
+ }
+ /* builtintable_comparator *****************************************************
+    qsort comparator for the automatic builtin table.
+ *******************************************************************************/
+ static int builtintable_comparator(const void *a, const void *b)
+ {
+       builtintable_entry *bte1;
+       builtintable_entry *bte2;
+       bte1 = (builtintable_entry *) a;
+       bte2 = (builtintable_entry *) b;
+       return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
+ }
+ /* builtintable_sort_automatic *************************************************
+    Sorts the automatic builtin table.
+ *******************************************************************************/
+ static void builtintable_sort_automatic(void)
+ {
+       s4 entries;
+       /* calculate table size statically (`- 1' comment see builtintable.inc) */
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
+                 builtintable_comparator);
+ }
+ /* builtin_init ****************************************************************
+    Initialize the global table of builtin functions.
+ *******************************************************************************/
+ bool builtin_init(void)
+ {
+       TRACESUBSYSTEMINITIALIZATION("builtin_init");
+       /* initialize the builtin tables */
+       if (!builtintable_init())
+               return false;
+       /* sort builtin tables */
+       builtintable_sort_automatic();
+       return true;
+ }
++/* builtintable_get_by_key *****************************************************
++
++   Returns a key for the given builtintable_entry object which is suitable
++   for retrieving the instance again by calling builtintable_get_by_key.
++
++   The key can be regarded fixed between multiple runs of the JVM.
++
++*******************************************************************************/
++
++s4 builtintable_get_key(builtintable_entry *bte)
++{
++      s4 entries;
++/*
++      int i;
++      entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
++      for (i = 0; i < entries; i++)
++              if (&builtintable_internal[i] == bte)
++                      return i + 1;
++
++      entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
++      for (i = 0; i < entries; i++)
++              if (&builtintable_automatic[i] == bte)
++                      return -i;
++
++      entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
++      for (i = 0; i < entries; i++)
++              if (&builtintable_function[i] == bte)
++                      return -1000 - i;
++*/
++
++      entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
++      if (&builtintable_internal[0] <= bte
++              && &builtintable_internal[entries - 1] >= bte)
++      {
++              return (s4) (bte - &builtintable_internal[0]) + 1;
++      }
++
++      entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
++      if (&builtintable_automatic[0] <= bte
++              && &builtintable_automatic[entries - 1] >= bte)
++      {
++              return -(s4) (bte - &builtintable_automatic[0]);
++      }
++
++      entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
++      if (&builtintable_function[0] <= bte
++              && &builtintable_function[entries - 1] >= bte)
++      {
++              return -1000 - (s4) (bte - &builtintable_function[0]);
++      }
++
++      /* builtintable_entry is not in our tables. */
++      assert (0);
++
++      return 0;
++}
++
++/* builtintable_get_by_key *****************************************************
++
++   Retrieves an entry in the internal and automatic builtin functions tables
++   using a key that was retrived previously with builtintable_get_key()
++
++*******************************************************************************/
++
++builtintable_entry *builtintable_get_by_key(s4 key)
++{
++      /* If key is positive it is the index into builtintable_internal. If it is
++       * negative it is the index into builtintable_automatic. If it is <= -1000
++     * it is the index into builtintable_function.
++     */
++      return (key > 0)
++              ? &builtintable_internal[key - 1]
++              : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
++}
++
+ /* builtintable_get_internal ***************************************************
+    Finds an entry in the builtintable for internal functions and
+    returns the a pointer to the structure.
+ *******************************************************************************/
+ builtintable_entry *builtintable_get_internal(functionptr fp)
+ {
+       builtintable_entry *bte;
+       for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+               if (bte->fp == fp)
+                       return bte;
+       }
+       return NULL;
+ }
+ /* builtintable_get_automatic **************************************************
+    Finds an entry in the builtintable for functions which are replaced
+    automatically and returns the a pointer to the structure.
+ *******************************************************************************/
+ builtintable_entry *builtintable_get_automatic(s4 opcode)
+ {
+       builtintable_entry *first;
+       builtintable_entry *last;
+       builtintable_entry *middle;
+       s4                  half;
+       s4                  entries;
+       /* calculate table size statically (`- 1' comment see builtintable.inc) */
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       first = builtintable_automatic;
+       last = builtintable_automatic + entries;
+       while (entries > 0) {
+               half = entries / 2;
+               middle = first + half;
+               if (middle->opcode < opcode) {
+                       first = middle + 1;
+                       entries -= half + 1;
+               }
+               else
+                       entries = half;
+       }
+       return (first != last ? first : NULL);
+ }
+ /* builtintable_replace_function ***********************************************
+    XXX
+ *******************************************************************************/
+ #if defined(ENABLE_JIT)
+ bool builtintable_replace_function(void *iptr_)
+ {
+       constant_FMIref    *mr;
+       builtintable_entry *bte;
+       instruction        *iptr;
+       iptr = (instruction *) iptr_; /* twisti will kill me ;) */
+       /* get name and descriptor of the function */
+       switch (iptr->opc) {
+       case ICMD_INVOKESTATIC:
+               /* The instruction MUST be resolved, otherwise we run into
+                  lazy loading troubles.  Anyway, we should/can only replace
+                  very VM-close functions. */
+               if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                       return false;
+               mr = iptr->sx.s23.s3.fmiref;
+               break;  
+       default:
+               return false;
+       }
+       /* search the function table */
+       for (bte = builtintable_function; bte->fp != NULL; bte++) {
+               if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
+                       (mr->name                == bte->name) &&
+                       (mr->descriptor          == bte->descriptor)) {
+                       /* set the values in the instruction */
+                       iptr->opc           = bte->opcode;
+                       iptr->sx.s23.s3.bte = bte;
+                       if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
+                               iptr->flags.bits |= INS_FLAG_CHECK;
+                       else
+                               iptr->flags.bits &= ~INS_FLAG_CHECK;
+                       return true;
+               }
+       }
+       return false;
+ }
+ #endif /* defined(ENABLE_JIT) */
+ /*============================================================================*/
+ /* INTERNAL BUILTIN FUNCTIONS                                                 */
+ /*============================================================================*/
+ /* builtin_instanceof **********************************************************
+    Checks if an object is an instance of some given class (or subclass
+    of that class). If class is an interface, checks if the interface
+    is implemented.
+    RETURN VALUE:
+      1......o is an instance of class or implements the interface
+      0......otherwise or if o == NULL
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ bool builtin_instanceof(java_handle_t *o, classinfo *c)
+ {
+       classinfo *oc;
+       if (o == NULL)
+               return 0;
+       LLNI_class_get(o, oc);
+       return class_isanysubclass(oc, c);
+ }
+ /* builtin_checkcast ***********************************************************
+    The same as builtin_instanceof but with the exception
+    that 1 is returned when (o == NULL).
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ bool builtin_checkcast(java_handle_t *o, classinfo *c)
+ {
+       classinfo *oc;
+       if (o == NULL)
+               return 1;
+       LLNI_class_get(o, oc);
+       if (class_isanysubclass(oc, c))
+               return 1;
+       return 0;
+ }
+ /* builtin_descriptorscompatible ***********************************************
+    Checks if two array type descriptors are assignment compatible.
+    RETURN VALUE:
+       1......target = desc is possible
+       0......otherwise
+                       
+ *******************************************************************************/
+ static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
+ {
+       if (desc == target)
+               return 1;
+       if (desc->arraytype != target->arraytype)
+               return 0;
+       if (desc->arraytype != ARRAYTYPE_OBJECT)
+               return 1;
+       
+       /* {both arrays are arrays of references} */
+       if (desc->dimension == target->dimension) {
+               if (!desc->elementvftbl)
+                       return 0;
+               /* an array which contains elements of interface types is
+            allowed to be casted to Object (JOWENN)*/
+               if ((desc->elementvftbl->baseval < 0) &&
+                       (target->elementvftbl->baseval == 1))
+                       return 1;
+               return class_isanysubclass(desc->elementvftbl->clazz,
+                                                                  target->elementvftbl->clazz);
+       }
+       if (desc->dimension < target->dimension)
+               return 0;
+       /* {desc has higher dimension than target} */
+       return class_isanysubclass(pseudo_class_Arraystub,
+                                                          target->elementvftbl->clazz);
+ }
+ /* builtin_arraycheckcast ******************************************************
+    Checks if an object is really a subtype of the requested array
+    type.  The object has to be an array to begin with. For simple
+    arrays (int, short, double, etc.) the types have to match exactly.
+    For arrays of objects, the type of elements in the array has to be
+    a subtype (or the same type) of the requested element type. For
+    arrays of arrays (which in turn can again be arrays of arrays), the
+    types at the lowest level have to satisfy the corresponding sub
+    class relation.
+    NOTE: This is a FAST builtin and can be called from JIT code only.
+ *******************************************************************************/
+ bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
+ {
+       arraydescriptor *desc;
+       if (o == NULL)
+               return 1;
+       desc = o->vftbl->arraydesc;
+       if (desc == NULL)
+               return 0;
+  
+       return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+ }
+ /* builtin_fast_arrayinstanceof ************************************************
+    NOTE: This is a FAST builtin and can be called from JIT code only.
+ *******************************************************************************/
+ bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
+ {
+       if (o == NULL)
+               return 0;
+       return builtin_fast_arraycheckcast(o, targetclass);
+ }
+ /* builtin_arrayinstanceof *****************************************************
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
+ {
+       bool result;
+       LLNI_CRITICAL_START;
+       result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
+       LLNI_CRITICAL_END;
+       return result;
+ }
+ /* builtin_throw_exception *****************************************************
+    Sets the exception pointer with the thrown exception and prints some
+    debugging information.
+    
+    NOTE: This is a FAST builtin and can be called from JIT code,
+    or from asm_vm_call_method.
+ *******************************************************************************/
+ void *builtin_throw_exception(java_object_t *xptr)
+ {
+ #if !defined(NDEBUG)
+       /* print exception trace */
+       if (opt_TraceExceptions)
+               trace_exception_builtin(xptr);
+ #endif /* !defined(NDEBUG) */
+       /* actually set the exception */
+       exceptions_set_exception(LLNI_QUICKWRAP(xptr));
+       /* Return a NULL pointer.  This is required for vm_call_method to
+          check for an exception.  This is for convenience. */
+       return NULL;
+ }
+ /* builtin_retrieve_exception **************************************************
+    Gets and clears the exception pointer of the current thread.
+    RETURN VALUE:
+       the exception object, or NULL if no exception was thrown.
+    NOTE: This is a FAST builtin and can be called from JIT code,
+    or from the signal handlers.
+ *******************************************************************************/
+ java_object_t *builtin_retrieve_exception(void)
+ {
+       java_handle_t *h;
+       java_object_t *o;
+       /* actually get and clear the exception */
+       h = exceptions_get_and_clear_exception();
+       o = LLNI_UNWRAP(h);
+       return o;
+ }
+ /* builtin_canstore ************************************************************
+    Checks, if an object can be stored in an array.
+    RETURN VALUE:
+       1......possible
+       0......otherwise (throws an ArrayStoreException)
+    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+ *******************************************************************************/
+ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
+ {
+       bool result;
+       LLNI_CRITICAL_START;
+       result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
+       LLNI_CRITICAL_END;
+       /* if not possible, throw an exception */
+       if (result == 0)
+               exceptions_throw_arraystoreexception();
+       return result;
+ }
+ /* builtin_fast_canstore *******************************************************
+    Checks, if an object can be stored in an array.
+    RETURN VALUE:
+       1......possible
+       0......otherwise (no exception thrown!)
+    NOTE: This is a FAST builtin and can be called from JIT code only.
+ *******************************************************************************/
+ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
+ {
+       arraydescriptor *desc;
+       arraydescriptor *valuedesc;
+       vftbl_t         *componentvftbl;
+       vftbl_t         *valuevftbl;
+       int32_t          baseval;
+       uint32_t         diffval;
+       bool             result;
+       if (o == NULL)
+               return 1;
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) oa->...vftbl->arraydesc != NULL
+        *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
+        *     *) o->vftbl is not an interface vftbl
+        */
+       desc           = oa->header.objheader.vftbl->arraydesc;
+       componentvftbl = desc->componentvftbl;
+       valuevftbl     = o->vftbl;
+       valuedesc      = valuevftbl->arraydesc;
+       if ((desc->dimension - 1) == 0) {
+               /* {oa is a one-dimensional array} */
+               /* {oa is an array of references} */
+               
+               if (valuevftbl == componentvftbl)
+                       return 1;
+               linker_classrenumber_mutex->lock();
+               baseval = componentvftbl->baseval;
+               if (baseval <= 0) {
+                       /* an array of interface references */
+                       result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                         (valuevftbl->interfacetable[baseval] != NULL));
+               }
+               else {
+                       diffval = valuevftbl->baseval - componentvftbl->baseval;
+                       result  = diffval <= (uint32_t) componentvftbl->diffval;
+               }
+               linker_classrenumber_mutex->unlock();
+       }
+       else if (valuedesc == NULL) {
+               /* {oa has dimension > 1} */
+               /* {componentvftbl->arraydesc != NULL} */
+               /* check if o is an array */
+               return 0;
+       }
+       else {
+               /* {o is an array} */
+               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       }
+       /* return result */
+       return result;
+ }
+ /* This is an optimized version where a is guaranteed to be one-dimensional */
+ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
+ {
+       arraydescriptor *desc;
+       vftbl_t         *elementvftbl;
+       vftbl_t         *valuevftbl;
+       int32_t          baseval;
+       uint32_t         diffval;
+       bool             result;
+       
+       if (o == NULL)
+               return 1;
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) a->...vftbl->arraydesc != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
+        *     *) a->...vftbl->arraydesc->dimension == 1
+        *     *) o->vftbl is not an interface vftbl
+        */
+       desc = a->header.objheader.vftbl->arraydesc;
+     elementvftbl = desc->elementvftbl;
+       valuevftbl = o->vftbl;
+       /* {a is a one-dimensional array} */
+       
+       if (valuevftbl == elementvftbl)
+               return 1;
+       linker_classrenumber_mutex->lock();
+       baseval = elementvftbl->baseval;
+       if (baseval <= 0) {
+               /* an array of interface references */
+               result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                 (valuevftbl->interfacetable[baseval] != NULL));
+       }
+       else {
+               diffval = valuevftbl->baseval - elementvftbl->baseval;
+               result  = diffval <= (uint32_t) elementvftbl->diffval;
+       }
+       linker_classrenumber_mutex->unlock();
+       return result;
+ }
+ /* This is an optimized version where a is guaranteed to be a
+  * one-dimensional array of a class type */
+ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
+ {
+       vftbl_t  *elementvftbl;
+       vftbl_t  *valuevftbl;
+       uint32_t  diffval;
+       bool      result;
+       
+       if (o == NULL)
+               return 1;
+       /* The following is guaranteed (by verifier checks):
+        *
+        *     *) a->...vftbl->arraydesc != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl != NULL
+        *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
+        *     *) a->...vftbl->arraydesc->dimension == 1
+        *     *) o->vftbl is not an interface vftbl
+        */
+     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
+       valuevftbl = o->vftbl;
+       /* {a is a one-dimensional array} */
+       
+       if (valuevftbl == elementvftbl)
+               return 1;
+       linker_classrenumber_mutex->lock();
+       diffval = valuevftbl->baseval - elementvftbl->baseval;
+       result  = diffval <= (uint32_t) elementvftbl->diffval;
+       linker_classrenumber_mutex->unlock();
+       return result;
+ }
+ /* builtin_new *****************************************************************
+    Creates a new instance of class c on the heap.
+    RETURN VALUE:
+       pointer to the object, or NULL if no memory is available
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ java_handle_t *builtin_new(classinfo *c)
+ {
+       java_handle_t *o;
+ #if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+ #endif
+ #if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+ #endif
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+       /* is the class loaded */
+       assert(c->state & CLASS_LOADED);
+       /* check if we can instantiate this class */
+       if (c->flags & ACC_ABSTRACT) {
+               exceptions_throw_instantiationerror(c);
+               return NULL;
+       }
+       /* is the class linked */
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+       if (!(c->state & CLASS_INITIALIZED)) {
+ #if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class (from builtin_new): ", c);
+ #endif
+               if (!initialize_class(c))
+                       return NULL;
+       }
+       o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                       c->finalizer, true);
+       if (!o)
+               return NULL;
+ #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+       o = LLNI_WRAP((java_object_t *) o);
+ #endif
+       LLNI_vftbl_direct(o) = c->vftbl;
+ #if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+ #endif
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+       return o;
+ }
+ #if defined(ENABLE_ESCAPE_REASON)
+ java_handle_t *builtin_escape_reason_new(classinfo *c) {
+       print_escape_reasons();
+       return builtin_java_new(c);
+ }
+ #endif
+ #if defined(ENABLE_TLH)
+ java_handle_t *builtin_tlh_new(classinfo *c)
+ {
+       java_handle_t *o;
+ # if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+ # endif
+ # if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+ # endif
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+       /* is the class loaded */
+       assert(c->state & CLASS_LOADED);
+       /* check if we can instantiate this class */
+       if (c->flags & ACC_ABSTRACT) {
+               exceptions_throw_instantiationerror(c);
+               return NULL;
+       }
+       /* is the class linked */
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+       if (!(c->state & CLASS_INITIALIZED)) {
+ # if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class (from builtin_new): ", c);
+ # endif
+               if (!initialize_class(c))
+                       return NULL;
+       }
+       /*
+       o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
+       */
+       o = NULL;
+       if (o == NULL) {
+               o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                               c->finalizer, true);
+       }
+       if (!o)
+               return NULL;
+ # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+       o = LLNI_WRAP((java_object_t *) o);
+ # endif
+       LLNI_vftbl_direct(o) = c->vftbl;
+ # if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+ # endif
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+ /*
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+ */
+       return o;
+ }
+ #endif
+ /* builtin_java_new ************************************************************
+    NOTE: This is a SLOW builtin and can be called from JIT code only.
+ *******************************************************************************/
+ java_handle_t *builtin_java_new(java_handle_t *clazz)
+ {
+       return builtin_new(LLNI_classinfo_unwrap(clazz));
+ }
+ /* builtin_fast_new ************************************************************
+    Creates a new instance of class c on the heap.
+    RETURN VALUE:
+       pointer to the object, or NULL if no fast return
+       is possible for any reason.
+    NOTE: This is a FAST builtin and can be called from JIT code only.
+ *******************************************************************************/
+ java_object_t *builtin_fast_new(classinfo *c)
+ {
+       java_object_t *o;
+ #if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+ #endif
+ #if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+ #endif
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+       /* is the class loaded */
+       assert(c->state & CLASS_LOADED);
+       /* check if we can instantiate this class */
+       if (c->flags & ACC_ABSTRACT)
+               return NULL;
+       /* is the class linked */
+       if (!(c->state & CLASS_LINKED))
+               return NULL;
+       if (!(c->state & CLASS_INITIALIZED))
+               return NULL;
+       o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                                                       c->finalizer, false);
+       if (!o)
+               return NULL;
+       o->vftbl = c->vftbl;
+ #if defined(ENABLE_THREADS)
+       LLNI_DIRECT(o)->lockword.init();
+ #endif
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+       return o;
+ }
+ /* builtin_newarray ************************************************************
+    Creates an array with the given vftbl on the heap. This function
+    takes as class argument an array class.
+    RETURN VALUE:
+       pointer to the array or NULL if no memory is available
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
+ {
+       arraydescriptor *desc;
+       s4               dataoffset;
+       s4               componentsize;
+       s4               actualsize;
+       java_handle_t   *a;
+ #if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+ #endif
+       RT_TIMING_GET_TIME(time_start);
+       desc          = arrayclass->vftbl->arraydesc;
+       dataoffset    = desc->dataoffset;
+       componentsize = desc->componentsize;
+       if (size < 0) {
+               exceptions_throw_negativearraysizeexception();
+               return NULL;
+       }
+       actualsize = dataoffset + size * componentsize;
+       /* check for overflow */
+       if (((u4) actualsize) < ((u4) size)) {
+               exceptions_throw_outofmemoryerror();
+               return NULL;
+       }
+       a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+       if (a == NULL)
+               return NULL;
+ #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+       a = LLNI_WRAP((java_object_t *) a);
+ #endif
+       LLNI_vftbl_direct(a) = arrayclass->vftbl;
+ #if defined(ENABLE_THREADS)
+       LLNI_DIRECT(a)->lockword.init();
+ #endif
+       LLNI_array_size(a) = size;
+       RT_TIMING_GET_TIME(time_end);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
+       return a;
+ }
+ /* builtin_java_newarray *******************************************************
+    NOTE: This is a SLOW builtin and can be called from JIT code only.
+ *******************************************************************************/
+ java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
+ {
+       return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
+ }
+ /* builtin_anewarray ***********************************************************
+    Creates an array of references to the given class type on the heap.
+    RETURN VALUE:
+       pointer to the array or NULL if no memory is
+       available
+    NOTE: This builtin can be called from NATIVE code only.
+ *******************************************************************************/
+ java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
+ {
+       classinfo *arrayclass;
+       
+       /* is class loaded */
+       assert(componentclass->state & CLASS_LOADED);
+       /* is class linked */
+       if (!(componentclass->state & CLASS_LINKED))
+               if (!link_class(componentclass))
+                       return NULL;
+       arrayclass = class_array_of(componentclass, true);
+       if (!arrayclass)
+               return NULL;
+       return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
+ }
+ /* builtin_newarray_type ****************************************************
+    Creates an array of [type]s on the heap.
+       
+    RETURN VALUE:
+       pointer to the array or NULL if no memory is available
+    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+ *******************************************************************************/
+ #define BUILTIN_NEWARRAY_TYPE(type, arraytype)                             \
+ java_handle_##type##array_t *builtin_newarray_##type(int32_t size)              \
+ {                                                                          \
+       return (java_handle_##type##array_t *)                                 \
+               builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
+ }
+ BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
+ BUILTIN_NEWARRAY_TYPE(byte,    ARRAYTYPE_BYTE)
+ BUILTIN_NEWARRAY_TYPE(char,    ARRAYTYPE_CHAR)
+ BUILTIN_NEWARRAY_TYPE(short,   ARRAYTYPE_SHORT)
+ BUILTIN_NEWARRAY_TYPE(int,     ARRAYTYPE_INT)
+ BUILTIN_NEWARRAY_TYPE(long,    ARRAYTYPE_LONG)
+ BUILTIN_NEWARRAY_TYPE(float,   ARRAYTYPE_FLOAT)
+ BUILTIN_NEWARRAY_TYPE(double,  ARRAYTYPE_DOUBLE)
+ /* builtin_multianewarray_intern ***********************************************
+    Creates a multi-dimensional array on the heap. The dimensions are
+    passed in an array of longs.
+    ARGUMENTS:
+       n.............number of dimensions to create
+       arrayclass....the array class
+       dims..........array containing the size of each dimension to create
+    RETURN VALUE:
+       pointer to the array or NULL if no memory is available
+ ******************************************************************************/
+ static java_handle_t *builtin_multianewarray_intern(int n,
+                                                                                                       classinfo *arrayclass,
+                                                                                                       long *dims)
+ {
+       s4             size;
+       java_handle_t *a;
+       classinfo     *componentclass;
+       s4             i;
+       /* create this dimension */
+       size = (s4) dims[0];
+       a = builtin_newarray(size, arrayclass);
+       if (!a)
+               return NULL;
+       /* if this is the last dimension return */
+       if (!--n)
+               return a;
+       /* get the class of the components to create */
+       componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
+       /* The verifier guarantees that the dimension count is in the range. */
+       /* create the component arrays */
+       for (i = 0; i < size; i++) {
+               java_handle_t *ea =
+ #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+                       /* we save an s4 to a s8 slot, 8-byte aligned */
+                       builtin_multianewarray_intern(n, componentclass, dims + 2);
+ #else
+                       builtin_multianewarray_intern(n, componentclass, dims + 1);
+ #endif
+               if (!ea)
+                       return NULL;
+               array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
+       }
+       return a;
+ }
+ /* builtin_multianewarray ******************************************************
+    Wrapper for builtin_multianewarray_intern which checks all
+    dimensions before we start allocating.
+    NOTE: This is a SLOW builtin and can be called from JIT code only.
+ ******************************************************************************/
+ java_handle_objectarray_t *builtin_multianewarray(int n,
+                                                                                                 java_handle_t *arrayclazz,
+                                                                                                 long *dims)
+ {
+       classinfo *c;
+       s4         i;
+       s4         size;
+       /* check all dimensions before doing anything */
+       for (i = 0; i < n; i++) {
+ #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+               /* we save an s4 to a s8 slot, 8-byte aligned */
+               size = (s4) dims[i * 2];
+ #else
+               size = (s4) dims[i];
+ #endif
+               if (size < 0) {
+                       exceptions_throw_negativearraysizeexception();
+                       return NULL;
+               }
+       }
+       c = LLNI_classinfo_unwrap(arrayclazz);
+       /* now call the real function */
+       return (java_handle_objectarray_t *)
+               builtin_multianewarray_intern(n, c, dims);
+ }
+ /* builtin_verbosecall_enter ***************************************************
+    Print method call with arguments for -verbose:call.
+    XXX: Remove mew once all archs use the new tracer!
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ #ifdef TRACE_ARGS_NUM
+ void builtin_verbosecall_enter(s8 a0, s8 a1,
+ # if TRACE_ARGS_NUM >= 4
+                                                          s8 a2, s8 a3,
+ # endif
+ # if TRACE_ARGS_NUM >= 6
+                                                          s8 a4, s8 a5,
+ # endif
+ # if TRACE_ARGS_NUM == 8
+                                                          s8 a6, s8 a7,
+ # endif
+                                                          methodinfo *m)
+ {
+       log_text("builtin_verbosecall_enter: Do not call me anymore!");
+ }
+ #endif
+ #endif /* !defined(NDEBUG) */
+ /* builtin_verbosecall_exit ****************************************************
+    Print method exit for -verbose:call.
+    XXX: Remove mew once all archs use the new tracer!
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
+ {
+       log_text("builtin_verbosecall_exit: Do not call me anymore!");
+ }
+ #endif /* !defined(NDEBUG) */
+ /*============================================================================*/
+ /* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS                                */
+ /*============================================================================*/
+ /*********** Functions for integer divisions *****************************
+  
+       On some systems (eg. DEC ALPHA), integer division is not supported by the
+       CPU. These helper functions implement the missing functionality.
+ ******************************************************************************/
+ #if !SUPPORT_DIVISION || defined(DISABLE_GC)
+ s4 builtin_idiv(s4 a, s4 b)
+ {
+       s4 c;
+       c = a / b;
+       return c;
+ }
+ s4 builtin_irem(s4 a, s4 b)
+ {
+       s4 c;
+       c = a % b;
+       return c;
+ }
+ #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
+ /* functions for long arithmetics **********************************************
+    On systems where 64 bit Integers are not supported by the CPU,
+    these functions are needed.
+ ******************************************************************************/
+ #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
+ s8 builtin_ladd(s8 a, s8 b)
+ {
+       s8 c;
+       c = a + b; 
+       return c;
+ }
+ s8 builtin_lsub(s8 a, s8 b)
+ {
+       s8 c;
+       c = a - b; 
+       return c;
+ }
+ s8 builtin_lneg(s8 a)
+ {
+       s8 c;
+       c = -a;
+       return c;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
+ #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
+ s8 builtin_lmul(s8 a, s8 b)
+ {
+       s8 c;
+       c = a * b; 
+       return c;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
+ #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
+ s8 builtin_ldiv(s8 a, s8 b)
+ {
+       s8 c;
+       c = a / b; 
+       return c;
+ }
+ s8 builtin_lrem(s8 a, s8 b)
+ {
+       s8 c;
+       c = a % b; 
+       return c;
+ }
+ #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
+ #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
+ s8 builtin_lshl(s8 a, s4 b)
+ {
+       s8 c;
+       c = a << (b & 63);
+       return c;
+ }
+ s8 builtin_lshr(s8 a, s4 b)
+ {
+       s8 c;
+       c = a >> (b & 63);
+       return c;
+ }
+ s8 builtin_lushr(s8 a, s4 b)
+ {
+       s8 c;
+       c = ((u8) a) >> (b & 63);
+       return c;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
+ #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
+ s8 builtin_land(s8 a, s8 b)
+ {
+       s8 c;
+       c = a & b; 
+       return c;
+ }
+ s8 builtin_lor(s8 a, s8 b)
+ {
+       s8 c;
+       c = a | b; 
+       return c;
+ }
+ s8 builtin_lxor(s8 a, s8 b) 
+ {
+       s8 c;
+       c = a ^ b; 
+       return c;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
+ #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
+ s4 builtin_lcmp(s8 a, s8 b)
+ { 
+       if (a < b)
+               return -1;
+       if (a > b)
+               return 1;
+       return 0;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
+ /* functions for unsupported floating instructions ****************************/
+ /* used to convert FLT_xxx defines into float values */
+ static inline float intBitsToFloat(s4 i)
+ {
+       imm_union imb;
+       imb.i = i;
+       return imb.f;
+ }
+ /* used to convert DBL_xxx defines into double values */
+ static inline float longBitsToDouble(s8 l)
+ {
+       imm_union imb;
+       imb.l = l;
+       return imb.d;
+ }
+ #if !SUPPORT_FLOAT
+ float builtin_fadd(float a, float b)
+ {
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+       if (finitef(a)) {
+               if (finitef(b))
+                       return a + b;
+               else
+                       return b;
+       }
+       else {
+               if (finitef(b))
+                       return a;
+               else {
+                       if (copysignf(1.0, a) == copysignf(1.0, b))
+                               return a;
+                       else
+                               return intBitsToFloat(FLT_NAN);
+               }
+       }
+ }
+ float builtin_fsub(float a, float b)
+ {
+       return builtin_fadd(a, builtin_fneg(b));
+ }
+ float builtin_fmul(float a, float b)
+ {
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+       if (finitef(a)) {
+               if (finitef(b)) return a * b;
+               else {
+                       if (a == 0) return intBitsToFloat(FLT_NAN);
+                       else return copysignf(b, copysignf(1.0, b)*a);
+               }
+       }
+       else {
+               if (finitef(b)) {
+                       if (b == 0) return intBitsToFloat(FLT_NAN);
+                       else return copysignf(a, copysignf(1.0, a)*b);
+               }
+               else {
+                       return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+               }
+       }
+ }
+ /* builtin_ddiv ****************************************************************
+    Implementation as described in VM Spec.
+ *******************************************************************************/
+ float builtin_fdiv(float a, float b)
+ {
+       if (finitef(a)) {
+               if (finitef(b)) {
+                       /* If neither value1' nor value2' is NaN, the sign of the result */
+                       /* is positive if both values have the same sign, negative if the */
+                       /* values have different signs. */
+                       return a / b;
+               } else {
+                       if (isnanf(b)) {
+                               /* If either value1' or value2' is NaN, the result is NaN. */
+                               return intBitsToFloat(FLT_NAN);
+                       } else {
+                               /* Division of a finite value by an infinity results in a */
+                               /* signed zero, with the sign-producing rule just given. */
+                               /* is sign equal? */
+                               if (copysignf(1.0, a) == copysignf(1.0, b))
+                                       return 0.0;
+                               else
+                                       return -0.0;
+                       }
+               }
+       } else {
+               if (isnanf(a)) {
+                       /* If either value1' or value2' is NaN, the result is NaN. */
+                       return intBitsToFloat(FLT_NAN);
+               } else if (finitef(b)) {
+                       /* Division of an infinity by a finite value results in a signed */
+                       /* infinity, with the sign-producing rule just given. */
+                       /* is sign equal? */
+                       if (copysignf(1.0, a) == copysignf(1.0, b))
+                               return intBitsToFloat(FLT_POSINF);
+                       else
+                               return intBitsToFloat(FLT_NEGINF);
+               } else {
+                       /* Division of an infinity by an infinity results in NaN. */
+                       return intBitsToFloat(FLT_NAN);
+               }
+       }
+ }
+ float builtin_fneg(float a)
+ {
+       if (isnanf(a)) return a;
+       else {
+               if (finitef(a)) return -a;
+               else return copysignf(a, -copysignf(1.0, a));
+       }
+ }
+ #endif /* !SUPPORT_FLOAT */
+ #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
+ s4 builtin_fcmpl(float a, float b)
+ {
+       if (isnanf(a))
+               return -1;
+       if (isnanf(b))
+               return -1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0,     a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+       }
+       if (a > b)
+               return 1;
+       if (a == b)
+               return 0;
+       return -1;
+ }
+ s4 builtin_fcmpg(float a, float b)
+ {
+       if (isnanf(a)) return 1;
+       if (isnanf(b)) return 1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0, a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+       }
+       if (a > b) return 1;
+       if (a == b) return 0;
+       return -1;
+ }
+ #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
+ float builtin_frem(float a, float b)
+ {
+       return fmodf(a, b);
+ }
+ /* functions for unsupported double instructions ******************************/
+ #if !SUPPORT_DOUBLE
+ double builtin_dadd(double a, double b)
+ {
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
+       if (finite(a)) {
+               if (finite(b)) return a + b;
+               else return b;
+       }
+       else {
+               if (finite(b)) return a;
+               else {
+                       if (copysign(1.0, a)==copysign(1.0, b)) return a;
+                       else return longBitsToDouble(DBL_NAN);
+               }
+       }
+ }
+ double builtin_dsub(double a, double b)
+ {
+       return builtin_dadd(a, builtin_dneg(b));
+ }
+ double builtin_dmul(double a, double b)
+ {
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
+       if (finite(a)) {
+               if (finite(b)) return a * b;
+               else {
+                       if (a == 0) return longBitsToDouble(DBL_NAN);
+                       else return copysign(b, copysign(1.0, b) * a);
+               }
+       }
+       else {
+               if (finite(b)) {
+                       if (b == 0) return longBitsToDouble(DBL_NAN);
+                       else return copysign(a, copysign(1.0, a) * b);
+               }
+               else {
+                       return copysign(a, copysign(1.0, a) * copysign(1.0, b));
+               }
+       }
+ }
+ /* builtin_ddiv ****************************************************************
+    Implementation as described in VM Spec.
+ *******************************************************************************/
+ double builtin_ddiv(double a, double b)
+ {
+       if (finite(a)) {
+               if (finite(b)) {
+                       /* If neither value1' nor value2' is NaN, the sign of the result */
+                       /* is positive if both values have the same sign, negative if the */
+                       /* values have different signs. */
+                       return a / b;
+               } else {
+                       if (isnan(b)) {
+                               /* If either value1' or value2' is NaN, the result is NaN. */
+                               return longBitsToDouble(DBL_NAN);
+                       } else {
+                               /* Division of a finite value by an infinity results in a */
+                               /* signed zero, with the sign-producing rule just given. */
+                               /* is sign equal? */
+                               if (copysign(1.0, a) == copysign(1.0, b))
+                                       return 0.0;
+                               else
+                                       return -0.0;
+                       }
+               }
+       } else {
+               if (isnan(a)) {
+                       /* If either value1' or value2' is NaN, the result is NaN. */
+                       return longBitsToDouble(DBL_NAN);
+               } else if (finite(b)) {
+                       /* Division of an infinity by a finite value results in a signed */
+                       /* infinity, with the sign-producing rule just given. */
+                       /* is sign equal? */
+                       if (copysign(1.0, a) == copysign(1.0, b))
+                               return longBitsToDouble(DBL_POSINF);
+                       else
+                               return longBitsToDouble(DBL_NEGINF);
+               } else {
+                       /* Division of an infinity by an infinity results in NaN. */
+                       return longBitsToDouble(DBL_NAN);
+               }
+       }
+ }
+ /* builtin_dneg ****************************************************************
+    Implemented as described in VM Spec.
+ *******************************************************************************/
+ double builtin_dneg(double a)
+ {
+       if (isnan(a)) {
+               /* If the operand is NaN, the result is NaN (recall that NaN has no */
+               /* sign). */
+               return a;
+       } else {
+               if (finite(a)) {
+                       /* If the operand is a zero, the result is the zero of opposite */
+                       /* sign. */
+                       return -a;
+               } else {
+                       /* If the operand is an infinity, the result is the infinity of */
+                       /* opposite sign. */
+                       return copysign(a, -copysign(1.0, a));
+               }
+       }
+ }
+ #endif /* !SUPPORT_DOUBLE */
+ #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
+ s4 builtin_dcmpl(double a, double b)
+ {
+       if (isnan(a))
+               return -1;
+       if (isnan(b))
+               return -1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+       }
+       if (a > b)
+               return 1;
+       if (a == b)
+               return 0;
+       return -1;
+ }
+ s4 builtin_dcmpg(double a, double b)
+ {
+       if (isnan(a))
+               return 1;
+       if (isnan(b))
+               return 1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+       }
+       if (a > b)
+               return 1;
+       if (a == b)
+               return 0;
+       return -1;
+ }
+ #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
+ double builtin_drem(double a, double b)
+ {
+       return fmod(a, b);
+ }
+ /* conversion operations ******************************************************/
+ #if !(SUPPORT_FLOAT && SUPPORT_I2F)
+ float builtin_i2f(s4 a)
+ {
+       float f = (float) a;
+       return f;
+ }
+ #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
+ #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
+ double builtin_i2d(s4 a)
+ {
+       double d = (double) a;
+       return d;
+ }
+ #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
+ #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
+ float builtin_l2f(s8 a)
+ {
+       float f = (float) a;
+       return f;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
+ #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
+ double builtin_l2d(s8 a)
+ {
+       double d = (double) a;
+       return d;
+ }
+ #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
+ #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+ s4 builtin_f2i(float a) 
+ {
+       s4 i;
+       i = builtin_d2i((double) a);
+       return i;
+       /*      float f;
+       
+               if (isnanf(a))
+               return 0;
+               if (finitef(a)) {
+               if (a > 2147483647)
+               return 2147483647;
+               if (a < (-2147483648))
+               return (-2147483648);
+               return (s4) a;
+               }
+               f = copysignf((float) 1.0, a);
+               if (f > 0)
+               return 2147483647;
+               return (-2147483648); */
+ }
+ #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+ #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
+ s8 builtin_f2l(float a)
+ {
+       s8 l;
+       l = builtin_d2l((double) a);
+       return l;
+       /*      float f;
+       
+               if (finitef(a)) {
+               if (a > 9223372036854775807L)
+               return 9223372036854775807L;
+               if (a < (-9223372036854775808L))
+               return (-9223372036854775808L);
+               return (s8) a;
+               }
+               if (isnanf(a))
+               return 0;
+               f = copysignf((float) 1.0, a);
+               if (f > 0)
+               return 9223372036854775807L;
+               return (-9223372036854775808L); */
+ }
+ #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
+ #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+ s4 builtin_d2i(double a) 
+ { 
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 2147483647)
+                       return 2147483647;
+               if (a <= (-2147483647-1))
+                       return (-2147483647-1);
+               return (s4) a;
+       }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 2147483647;
+       return (-2147483647-1);
+ }
+ #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+ #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
+ s8 builtin_d2l(double a)
+ {
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 9223372036854775807LL)
+                       return 9223372036854775807LL;
+               if (a <= (-9223372036854775807LL-1))
+                       return (-9223372036854775807LL-1);
+               return (s8) a;
+       }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 9223372036854775807LL;
+       return (-9223372036854775807LL-1);
+ }
+ #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
+ #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
+ double builtin_f2d(float a)
+ {
+       if (finitef(a)) return (double) a;
+       else {
+               if (isnanf(a))
+                       return longBitsToDouble(DBL_NAN);
+               else
+                       return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
+       }
+ }
+ float builtin_d2f(double a)
+ {
+       if (finite(a))
+               return (float) a;
+       else {
+               if (isnan(a))
+                       return intBitsToFloat(FLT_NAN);
+               else
+                       return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
+       }
+ }
+ #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
+ /*============================================================================*/
+ /* AUTOMATICALLY REPLACED FUNCTIONS                                           */
+ /*============================================================================*/
+ /* builtin_arraycopy ***********************************************************
+    Builtin for java.lang.System.arraycopy.
+    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+ *******************************************************************************/
+ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+                                          java_handle_t *dest, s4 destStart, s4 len)
+ {
+       arraydescriptor *sdesc;
+       arraydescriptor *ddesc;
+       s4               i;
+       if ((src == NULL) || (dest == NULL)) {
+               exceptions_throw_nullpointerexception();
+               return;
+       }
+       sdesc = LLNI_vftbl_direct(src)->arraydesc;
+       ddesc = LLNI_vftbl_direct(dest)->arraydesc;
+       if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
+               exceptions_throw_arraystoreexception();
+               return;
+       }
+       // Check if offsets and length are positive.
+       if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
+       // Check if ranges are valid.
+       if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
+               (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return;
+       }
+       // Special case.
+       if (len == 0) {
+               return;
+       }
+       if (sdesc->componentvftbl == ddesc->componentvftbl) {
+               /* We copy primitive values or references of exactly the same type */
+               s4 dataoffset = sdesc->dataoffset;
+               s4 componentsize = sdesc->componentsize;
+               LLNI_CRITICAL_START;
+               MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
+                         ((u1 *) LLNI_DIRECT(src))  + dataoffset + componentsize * srcStart,
+                         u1, (size_t) len * componentsize);
+               LLNI_CRITICAL_END;
+       }
+       else {
+               /* We copy references of different type */
+               java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
+               java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
+  
+               if (destStart <= srcStart) {
+                       for (i = 0; i < len; i++) {
+                               java_handle_t *o;
+                               o = array_objectarray_element_get(oas, srcStart + i);
+                               if (!builtin_canstore(oad, o))
+                                       return;
+                               array_objectarray_element_set(oad, destStart + i, o);
+                       }
+               }
+               else {
+                       /* XXX this does not completely obey the specification!
+                          If an exception is thrown only the elements above the
+                          current index have been copied. The specification
+                          requires that only the elements *below* the current
+                          index have been copied before the throw. */
+                       for (i = len - 1; i >= 0; i--) {
+                               java_handle_t *o;
+                               o = array_objectarray_element_get(oas, srcStart + i);
+                               if (!builtin_canstore(oad, o))
+                                       return;
+                               array_objectarray_element_set(oad, destStart + i, o);
+                       }
+               }
+       }
+ }
+ /* builtin_nanotime ************************************************************
+    Return the current time in nanoseconds.
+ *******************************************************************************/
+ s8 builtin_nanotime(void)
+ {
+       struct timeval tv;
+       s8             usecs;
+       if (gettimeofday(&tv, NULL) == -1)
+               vm_abort("gettimeofday failed: %s", strerror(errno));
+       usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
+       return usecs * 1000;
+ }
+ /* builtin_currenttimemillis ***************************************************
+    Return the current time in milliseconds.
+ *******************************************************************************/
+ s8 builtin_currenttimemillis(void)
+ {
+       s8 msecs;
+       msecs = builtin_nanotime() / 1000 / 1000;
+       return msecs;
+ }
+ /* builtin_clone ***************************************************************
+    Function for cloning objects or arrays.
+    NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+ *******************************************************************************/
+ java_handle_t *builtin_clone(void *env, java_handle_t *o)
+ {
+       arraydescriptor *ad;
+       u4               size;
+       classinfo       *c;
+       java_handle_t   *co;                /* cloned object header               */
+       /* get the array descriptor */
+       ad = LLNI_vftbl_direct(o)->arraydesc;
+       /* we are cloning an array */
+       if (ad != NULL) {
+               size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
+         
+               co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+               if (co == NULL)
+                       return NULL;
+ #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+               /* XXX this is only a dirty hack to make Boehm work with handles */
+               co = LLNI_WRAP((java_object_t *) co);
+ #endif
+               LLNI_CRITICAL_START;
+               MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
+ #if defined(ENABLE_GC_CACAO)
+               heap_init_objectheader(LLNI_DIRECT(co), size);
+ #endif
+ #if defined(ENABLE_THREADS)
+               LLNI_DIRECT(co)->lockword.init();
+ #endif
+               LLNI_CRITICAL_END;
+               return co;
+       }
+     
+     /* we are cloning a non-array */
+     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
+         exceptions_throw_clonenotsupportedexception();
+         return NULL;
+     }
+       /* get the class of the object */
+       LLNI_class_get(o, c);
+       /* create new object */
+     co = builtin_new(c);
+     if (co == NULL)
+         return NULL;
+       LLNI_CRITICAL_START;
+       MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
+ #if defined(ENABLE_GC_CACAO)
+       heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
+ #endif
+ #if defined(ENABLE_THREADS)
+       LLNI_DIRECT(co)->lockword.init();
+ #endif
+       LLNI_CRITICAL_END;
+     return co;
+ }
+ #if defined(ENABLE_CYCLES_STATS)
+ void builtin_print_cycles_stats(FILE *file)
+ {
+       fprintf(file,"builtin cylce count statistics:\n");
+       CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
+       CYCLES_STATS_PRINT(builtin_new         ,file);
+       fprintf(file,"\n");
+ }
+ #endif /* defined(ENABLE_CYCLES_STATS) */
+ #if defined(ENABLE_VMLOG)
+ #define NDEBUG
+ #include <vmlog_cacao.c>
+ #endif
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,2a03455299c52069529db48f81d0e9b410789cb4..3a7747dc291bf6702747dfd5b0ffec69f1615a05
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,350 +1,352 @@@
 - * must be an entry in the builtin_desc table in jit/jit.c.
+ /* src/vm/jit/builtin.hpp - prototypes of builtin functions
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #ifndef _BUILTIN_HPP
+ #define _BUILTIN_HPP
+ /* forward typedefs ***********************************************************/
+ typedef struct builtintable_entry builtintable_entry;
+ #include "config.h"
+ #include "vm/types.h"
+ #include "arch.h"
+ #include "md-abi.h"
+ #include "toolbox/logging.h"
+ #include "vm/descriptor.h"
+ #include "vm/utf8.h"
+ /* define infinity for floating point numbers */
+ #define FLT_NAN     0x7fc00000
+ #define FLT_POSINF  0x7f800000
+ #define FLT_NEGINF  0xff800000
+ /* define infinity for double floating point numbers */
+ #define DBL_NAN     0x7ff8000000000000LL
+ #define DBL_POSINF  0x7ff0000000000000LL
+ #define DBL_NEGINF  0xfff0000000000000LL
+ /* float versions are not defined in GNU classpath's fdlibm */
+ #define copysignf    copysign
+ #define finitef      finite
+ #define fmodf        fmod
+ #define isnanf       isnan
+ /* builtin functions table ****************************************************/
+ struct builtintable_entry {
+       s4           opcode;                /* opcode which is replaced           */
+       u4           flags;                 /* e.g. check for exception           */
+       functionptr  fp;                    /* function pointer of builtin        */
+       u1          *stub;                  /* pointer to builtin stub code       */
+       const char*  cclassname;            /* char name of the class             */
+       const char*  cname;                 /* char name of the function          */
+       const char*  cdescriptor;           /* char name of the descriptor        */
+       utf         *classname;             /* class of the function              */
+       utf         *name;                  /* name of the function               */
+       utf         *descriptor;            /* descriptor of the function         */
+       methoddesc  *md;
+ };
+ /* builtin table flag defines *************************************************/
+ #define BUILTINTABLE_FLAG_STUB         0x0001 /* builtin needs a stub         */
+ #define BUILTINTABLE_FLAG_EXCEPTION    0x0002 /* check for excepion on return */
+ /* function prototypes ********************************************************/
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ bool builtin_init(void);
++s4                                    builtintable_get_key(builtintable_entry *);
++builtintable_entry *builtintable_get_by_key(s4 key);
+ builtintable_entry *builtintable_get_internal(functionptr fp);
+ builtintable_entry *builtintable_get_automatic(s4 opcode);
+ bool builtintable_replace_function(void *iptr);
+ /**********************************************************************/
+ /* BUILTIN FUNCTIONS                                                  */
+ /**********************************************************************/
+ /* NOTE: Builtin functions which are used in the BUILTIN* opcodes must
+  * have a BUILTIN_... macro defined as seen below. In code dealing
+  * with the BUILTIN* opcodes the functions may only be addressed by
+  * these macros, never by their actual name! (This helps to make this
+  * code more portable.)
+  *
+  * C and assembler code which does not deal with the BUILTIN* opcodes,
+  * can use the builtin functions normally (like all other functions).
+  *
+  * IMPORTANT:
+  * For each builtin function which is used in a BUILTIN* opcode there
++ * must be an entry in the tables in vm/builtintable.inc.
+  *
+  * Below each prototype is either the BUILTIN_ macro definition or a
+  * comment specifiying that this function is not used in BUILTIN*
+  * opcodes.
+  *
+  * (The BUILTIN* opcodes are ICMD_BUILTIN1, ICMD_BUILTIN2 and
+  * ICMD_BUILTIN3.)
+  */
+ bool builtin_instanceof(java_handle_t *obj, classinfo *c);
+ /* NOT AN OP */
+ bool builtin_checkcast(java_handle_t *obj, classinfo *c);
+ /* NOT AN OP */
+ bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
+ /* NOT AN OP */
+ bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
+ #define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
+ bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
+ #define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
+ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
+ /* NOT AN OP */
+ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
+ #define BUILTIN_FAST_canstore (functionptr) builtin_fast_canstore
+ void *builtin_throw_exception(java_object_t *exception);
+ /* NOT AN OP */
+ java_object_t *builtin_retrieve_exception(void);
+ /* NOT AN OP */
+ java_handle_t *builtin_new(classinfo *c);
+ /* NOT AN OP */
+ java_handle_t *builtin_java_new(java_handle_t *c);
+ #define BUILTIN_new (functionptr) builtin_java_new
+ #if defined(ENABLE_TLH)
+ #define BUILTIN_tlh_new (functionptr) builtin_tlh_new
+ java_handle_t *builtin_tlh_new(classinfo *c);
+ #endif
+ #if defined(ENABLE_ESCAPE_REASON)
+ #define BUILTIN_escape_reason_new (functionptr)builtin_escape_reason_new
+ java_handle_t *builtin_escape_reason_new(classinfo *c);
+ #endif
+ java_object_t *builtin_fast_new(classinfo *c);
+ #define BUILTIN_FAST_new (functionptr) builtin_fast_new
+ java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
+ /* NOT AN OP */
+ java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass);
+ #define BUILTIN_newarray (functionptr) builtin_java_newarray
+ java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
+ /* NOT AN OP */
+ java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size);
+ #define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean
+ java_handle_chararray_t *builtin_newarray_char(int32_t size);
+ #define BUILTIN_newarray_char (functionptr) builtin_newarray_char
+ java_handle_floatarray_t *builtin_newarray_float(int32_t size);
+ #define BUILTIN_newarray_float (functionptr) builtin_newarray_float
+ java_handle_doublearray_t *builtin_newarray_double(int32_t size);
+ #define BUILTIN_newarray_double (functionptr) builtin_newarray_double
+ java_handle_bytearray_t *builtin_newarray_byte(int32_t size);
+ #define BUILTIN_newarray_byte (functionptr) builtin_newarray_byte
+ java_handle_shortarray_t *builtin_newarray_short(int32_t size);
+ #define BUILTIN_newarray_short (functionptr) builtin_newarray_short
+ java_handle_intarray_t *builtin_newarray_int(int32_t size);
+ #define BUILTIN_newarray_int (functionptr) builtin_newarray_int
+ java_handle_longarray_t *builtin_newarray_long(int32_t size);
+ #define BUILTIN_newarray_long (functionptr) builtin_newarray_long
+ java_handle_objectarray_t *builtin_multianewarray(int n,
+                                                                                                 java_handle_t *arrayclass,
+                                                                                                 long *dims);
+ #define BUILTIN_multianewarray (functionptr) builtin_multianewarray
+ #if defined(TRACE_ARGS_NUM)
+ void builtin_verbosecall_enter(s8 a0, s8 a1,
+ # if TRACE_ARGS_NUM >= 4
+                                                          s8 a2, s8 a3,
+ # endif
+ # if TRACE_ARGS_NUM >= 6
+                                                          s8 a4, s8 a5,
+ # endif
+ # if TRACE_ARGS_NUM == 8
+                                                          s8 a6, s8 a7,
+ # endif
+                                                          methodinfo *m);
+ /* NOT AN OP */
+ #endif /* defined(TRACE_ARGS_NUM) */
+ void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+ /* NOT AN OP */
+ s4 builtin_idiv(s4 a, s4 b);
+ #define BUILTIN_idiv (functionptr) builtin_idiv
+ s4 builtin_irem(s4 a, s4 b);
+ #define BUILTIN_irem (functionptr) builtin_irem
+ s8 builtin_ladd(s8 a, s8 b);
+ #define BUILTIN_ladd (functionptr) builtin_ladd
+ s8 builtin_lsub(s8 a, s8 b);
+ #define BUILTIN_lsub (functionptr) builtin_lsub
+ s8 builtin_lmul(s8 a, s8 b);
+ #define BUILTIN_lmul (functionptr) builtin_lmul
+ s8 builtin_ldiv(s8 a, s8 b);
+ #define BUILTIN_ldiv (functionptr) builtin_ldiv
+ s8 builtin_lrem(s8 a, s8 b);
+ #define BUILTIN_lrem (functionptr) builtin_lrem
+ s8 builtin_lshl(s8 a, s4 b);
+ #define BUILTIN_lshl (functionptr) builtin_lshl
+ s8 builtin_lshr(s8 a, s4 b);
+ #define BUILTIN_lshr (functionptr) builtin_lshr
+ s8 builtin_lushr(s8 a, s4 b);
+ #define BUILTIN_lushr (functionptr) builtin_lushr
+ s8 builtin_land(s8 a, s8 b);
+ #define BUILTIN_land (functionptr) builtin_land
+ s8 builtin_lor(s8 a, s8 b);
+ #define BUILTIN_lor (functionptr) builtin_lor
+ s8 builtin_lxor(s8 a, s8 b);
+ #define BUILTIN_lxor (functionptr) builtin_lxor
+ s8 builtin_lneg(s8 a);
+ #define BUILTIN_lneg (functionptr) builtin_lneg
+ s4 builtin_lcmp(s8 a, s8 b);
+ #define BUILTIN_lcmp (functionptr) builtin_lcmp
+ float builtin_fadd(float a, float b);
+ #define BUILTIN_fadd (functionptr) builtin_fadd
+ float builtin_fsub(float a, float b);
+ #define BUILTIN_fsub (functionptr) builtin_fsub
+ float builtin_fmul(float a, float b);
+ #define BUILTIN_fmul (functionptr) builtin_fmul
+ float builtin_fdiv(float a, float b);
+ #define BUILTIN_fdiv (functionptr) builtin_fdiv
+ float builtin_fneg(float a);         
+ #define BUILTIN_fneg (functionptr) builtin_fneg
+ s4 builtin_fcmpl(float a, float b);  
+ #define BUILTIN_fcmpl (functionptr) builtin_fcmpl
+ s4 builtin_fcmpg(float a, float b);  
+ #define BUILTIN_fcmpg (functionptr) builtin_fcmpg
+ float builtin_frem(float a, float b);
+ #define BUILTIN_frem (functionptr) builtin_frem
+ double builtin_dadd(double a, double b);
+ #define BUILTIN_dadd (functionptr) builtin_dadd
+ double builtin_dsub(double a, double b);
+ #define BUILTIN_dsub (functionptr) builtin_dsub
+ double builtin_dmul(double a, double b);
+ #define BUILTIN_dmul (functionptr) builtin_dmul
+ double builtin_ddiv(double a, double b);
+ #define BUILTIN_ddiv (functionptr) builtin_ddiv
+ double builtin_dneg(double a);          
+ #define BUILTIN_dneg (functionptr) builtin_dneg
+ s4 builtin_dcmpl(double a, double b);   
+ #define BUILTIN_dcmpl (functionptr) builtin_dcmpl
+ s4 builtin_dcmpg(double a, double b);   
+ #define BUILTIN_dcmpg (functionptr) builtin_dcmpg
+ double builtin_drem(double a, double b);
+ #define BUILTIN_drem (functionptr) builtin_drem
+ float    builtin_i2f(s4 i);
+ #define BUILTIN_i2f (functionptr) builtin_i2f
+ double   builtin_i2d(s4 i);
+ #define BUILTIN_i2d (functionptr) builtin_i2d
+ float    builtin_l2f(s8 l);
+ #define BUILTIN_l2f (functionptr) builtin_l2f
+ double   builtin_l2d(s8 l);
+ #define BUILTIN_l2d (functionptr) builtin_l2d
+ s4       builtin_f2i(float a);
+ #define BUILTIN_f2i (functionptr) builtin_f2i
+ s4       asm_builtin_f2i(float a);
+ /* NOT AN OP */
+ s8       builtin_f2l(float a);
+ #define BUILTIN_f2l (functionptr) builtin_f2l
+ s8       asm_builtin_f2l(float a);
+ /* NOT AN OP */
+ double   builtin_f2d(float a);
+ #define BUILTIN_f2d (functionptr) builtin_f2d
+ s4       builtin_d2i(double a);
+ #define BUILTIN_d2i (functionptr) builtin_d2i
+ s4       asm_builtin_d2i(double a);
+ /* NOT AN OP */
+ s8       builtin_d2l(double a);
+ #define BUILTIN_d2l (functionptr) builtin_d2l
+ s8       asm_builtin_d2l(double a);
+ /* NOT AN OP */
+ float    builtin_d2f(double a);
+ #define BUILTIN_d2f (functionptr) builtin_d2f
+ java_handle_t *builtin_clone(void *env, java_handle_t *o);
+ #define BUILTIN_clone (functionptr) builtin_clone
+ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+                                          java_handle_t *dest, s4 destStart, s4 len);
+ #define BUILTIN_arraycopy (functionptr) builtin_arraycopy
+ s8 builtin_nanotime(void);
+ s8 builtin_currenttimemillis(void);
+ #define BUILTIN_currenttimemillis (functionptr) builtin_currenttimemillis
+ #if defined(ENABLE_CYCLES_STATS)
+ void builtin_print_cycles_stats(FILE *file);
+ #endif
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif // _BUILTIN_HPP
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,b39852d2ed7a8f20024421d435153fc70bb2bb25..a991de2895c9938070b835979e3b0d4f39c9430f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,289 +1,299 @@@
 -#if defined(ENABLE_STATISTICS)
+ /* src/vm/jit/code.cpp - codeinfo struct for representing compiled code
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <stdint.h>
+ #include "arch.h"
+ #include "mm/memory.h"
+ #include "vm/options.h"
+ #include "vm/vm.hpp"
+ #include "vm/jit/code.hpp"
+ #include "vm/jit/codegen-common.hpp"
++#include "vm/jit/jitcache.hpp"
+ #include "vm/jit/patcher-common.hpp"
+ #include "vm/jit/methodtree.h"
+ /* code_init *******************************************************************
+    Initialize the code-subsystem.
+ *******************************************************************************/
+ void code_init(void)
+ {
+       /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
+       if (OFFSET(codeinfo, m) != 0)
+               vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
+ }
+ /* code_codeinfo_new ***********************************************************
+    Create a new codeinfo for the given method.
+    
+    IN:
+        m................method to create a new codeinfo for
+    The following fields are set in codeinfo:
+        m
+        patchers
++         cachedrefs
+    RETURN VALUE:
+        a new, initialized codeinfo, or
+          NULL if an exception occurred.
+   
+ *******************************************************************************/
+ codeinfo *code_codeinfo_new(methodinfo *m)
+ {
+       codeinfo *code;
+       code = NEW(codeinfo);
+       code->m = m;
+       patcher_list_create(code);
++#if defined (ENABLE_JITCACHE)
++      jitcache_list_create(code);
++#endif
++
++#if defined (ENABLE_STATISTICS)
+       if (opt_stat)
+               size_codeinfo += sizeof(codeinfo);
+ #endif
+       return code;
+ }
+ /* code_find_codeinfo_for_pc ***************************************************
+    Return the codeinfo for the compilation unit that contains the
+    given PC.
+    ARGUMENTS:
+        pc...............machine code position
+    RETURN VALUE:
+        the codeinfo * for the given PC
+ *******************************************************************************/
+ codeinfo *code_find_codeinfo_for_pc(void *pc)
+ {
+       void *pv;
+       pv = methodtree_find(pc);
+       return code_get_codeinfo_for_pv(pv);
+ }
+ /* code_find_codeinfo_for_pc ***************************************************
+    Return the codeinfo for the compilation unit that contains the
+    given PC. This method does not check the return value and is used
+    by the GC.
+    IN:
+        pc...............machine code position
+    RETURN VALUE:
+        the codeinfo * for the given PC, or NULL
+ *******************************************************************************/
+ codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
+ {
+       void *pv;
+       pv = methodtree_find_nocheck(pc);
+       if (pv == NULL)
+               return NULL;
+       return code_get_codeinfo_for_pv(pv);
+ }
+ /* code_get_methodinfo_for_pv **************************************************
+    Return the methodinfo for the given PV.
+    IN:
+        pv...............PV
+    RETURN VALUE:
+        the methodinfo *
+ *******************************************************************************/
+ methodinfo *code_get_methodinfo_for_pv(void *pv)
+ {
+       codeinfo *code;
+       code = code_get_codeinfo_for_pv(pv);
+       /* This is the case for asm_vm_call_method. */
+       if (code == NULL)
+               return NULL;
+       return code->m;
+ }
+ /* code_get_sync_slot_count ****************************************************
+    Return the number of stack slots used for storing the synchronized object
+    (and the return value around lock_monitor_exit calls) by the given code.
+    
+    IN:
+        code.............the codeinfo of the code in question
+                           (must be != NULL)
+    RETURN VALUE:
+        the number of stack slots used for synchronization
+   
+ *******************************************************************************/
+ #if defined(ENABLE_REPLACEMENT)
+ int code_get_sync_slot_count(codeinfo *code)
+ {
+ #ifdef ENABLE_THREADS
+       int count;
+       
+       assert(code);
+       if (!checksync)
+               return 0;
+       if (!code_is_synchronized(code))
+               return 0;
+       count = 1;
+ #if defined(__POWERPC__)
+       /* powerpc needs an extra slot */
+       count++;
+ #endif
+       return count;
+ #else /* !ENABLE_THREADS */
+       
+       return 0;
+ #endif /* ENABLE_THREADS */
+ }
+ #endif /* defined(ENABLE_REPLACEMENT) */
+ /* code_codeinfo_free **********************************************************
+    Free the memory used by a codeinfo.
+    
+    IN:
+        code.............the codeinfo to free
+ *******************************************************************************/
+ void code_codeinfo_free(codeinfo *code)
+ {
+       if (code == NULL)
+               return;
+       if (code->mcode != NULL)
+               CFREE((void *) (ptrint) code->mcode, code->mcodelength);
+       patcher_list_free(code);
++#if defined(ENABLE_JITCACHE)
++      jitcache_list_free(code);
++#endif
++
+ #if defined(ENABLE_REPLACEMENT)
+       replace_free_replacement_points(code);
+ #endif
+       FREE(code, codeinfo);
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_codeinfo -= sizeof(codeinfo);
+ #endif
+ }
+ /* code_free_code_of_method ****************************************************
+    Free all codeinfos of the given method
+    
+    IN:
+        m................the method of which the codeinfos are to be freed
+ *******************************************************************************/
+ void code_free_code_of_method(methodinfo *m)
+ {
+       codeinfo *nextcode;
+       codeinfo *code;
+       if (!m)
+               return;
+       
+       nextcode = m->code;
+       while (nextcode) {
+               code = nextcode;
+               nextcode = code->prev;
+               code_codeinfo_free(code);
+       }
+       m->code = NULL;
+ }
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,cd082dd19f93b2963be4985037c6e11e7f771da1..fcdb08c686b06ecaf75b4e3a0973751e32e24dfb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,252 +1,263 @@@
+ /* src/vm/jit/code.hpp - codeinfo struct for representing compiled code
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #ifndef _CODE_HPP
+ #define _CODE_HPP
+ #include "config.h"
+ #include <assert.h>
+ #include <stdint.h>
+ #include "vm/types.h"
+ #include "toolbox/list.hpp"
+ #include "vm/global.h"
+ #include "vm/method.h"
+ #include "vm/jit/exceptiontable.h"
++#if defined (ENABLE_JITCACHE)
++#include "vm/jit/jitcache.hpp"
++#endif
+ #include "vm/jit/linenumbertable.hpp"
+ #include "vm/jit/methodheader.h"
+ #include "vm/jit/patcher-common.hpp"
+ #include "vm/jit/replace.hpp"
+ /* constants ******************************************************************/
+ #define CODE_FLAG_INVALID         0x0001
+ #define CODE_FLAG_LEAFMETHOD      0x0002
+ #define CODE_FLAG_SYNCHRONIZED    0x0004
+ #define CODE_FLAG_TLH             0x0008
+ /* codeinfo *******************************************************************
+    A codeinfo represents a particular realization of a method in
+    machine code.
+    ATTENTION: The methodinfo entry in the code-structure MUST have the
+    offset 0, otherwise we have a problem in our compiler stub. This is
+    checked with an assert in code_init().
+ *******************************************************************************/
+ struct codeinfo {
+       methodinfo   *m;                    /* method this is a realization of    */
+       codeinfo     *prev;                 /* previous codeinfo of this method   */
+       uint32_t      flags;                /* OR of CODE_FLAG_ constants         */
+       u1            optlevel;             /* optimization level of this code    */
+       s4            basicblockcount;      /* number of basic blocks             */
+       int32_t       synchronizedoffset;   /* stack offset of synchronized obj.  */
+       /* machine code */
+       u1           *mcode;                /* pointer to machine code            */
+       u1           *entrypoint;           /* machine code entry point           */
+       s4            mcodelength;          /* length of generated machine code   */
+       exceptiontable_t  *exceptiontable;
+       LinenumberTable* linenumbertable;
+       /* patcher list */
+ #ifdef __cplusplus
+       List<patchref_t>* patchers;
+ #else
+       List*         patchers;
+ #endif
++#if defined (ENABLE_JITCACHE)
++#ifdef __cplusplus
++      List<cachedref_t>* cachedrefs;
++#else
++      List*         cachedrefs;
++#endif
++#endif
++
+       /* replacement */                                   
+       s4            stackframesize;       /* size of the stackframe in slots    */
+ #if defined(ENABLE_REPLACEMENT)
+       rplpoint     *rplpoints;            /* replacement points                 */
+       rplalloc     *regalloc;             /* register allocation info           */
+       s4            rplpointcount;        /* number of replacement points       */
+       s4            globalcount;          /* number of global allocations       */
+       s4            regalloccount;        /* number of total allocations        */
+       s4            memuse;               /* number of arg + local slots        */
+       u1            savedintcount;        /* number of callee saved int regs    */
+       u1            savedfltcount;        /* number of callee saved flt regs    */
+ # if defined(HAS_ADDRESS_REGISTER_FILE)
+       u1            savedadrcount;        /* number of callee saved adr regs    */
+ # endif
+       u1           *savedmcode;           /* saved code under patches           */
+ #endif
+ #if defined(ENABLE_PROFILING)
+       u4            frequency;            /* number of method invocations       */
+       u4           *bbfrequency;                  
+       s8            cycles;               /* number of cpu cycles               */
+ #endif
+ };
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ /* inline functions ***********************************************************/
+ /* code_xxx_invalid ************************************************************
+    Functions for CODE_FLAG_INVALID.
+ *******************************************************************************/
+ inline static int code_is_invalid(codeinfo *code)
+ {
+       return (code->flags & CODE_FLAG_INVALID);
+ }
+ inline static void code_flag_invalid(codeinfo *code)
+ {
+       code->flags |= CODE_FLAG_INVALID;
+ }
+ inline static void code_unflag_invalid(codeinfo *code)
+ {
+       code->flags &= ~CODE_FLAG_INVALID;
+ }
+ /* code_xxx_leafmethod *********************************************************
+    Functions for CODE_FLAG_LEAFMETHOD.
+ *******************************************************************************/
+ inline static int code_is_leafmethod(codeinfo *code)
+ {
+       return (code->flags & CODE_FLAG_LEAFMETHOD);
+ }
+ inline static void code_flag_leafmethod(codeinfo *code)
+ {
+       code->flags |= CODE_FLAG_LEAFMETHOD;
+ }
+ inline static void code_unflag_leafmethod(codeinfo *code)
+ {
+       code->flags &= ~CODE_FLAG_LEAFMETHOD;
+ }
+ /* code_xxx_synchronized *******************************************************
+    Functions for CODE_FLAG_SYNCHRONIZED.
+ *******************************************************************************/
+ inline static int code_is_synchronized(codeinfo *code)
+ {
+       return (code->flags & CODE_FLAG_SYNCHRONIZED);
+ }
+ inline static void code_flag_synchronized(codeinfo *code)
+ {
+       code->flags |= CODE_FLAG_SYNCHRONIZED;
+ }
+ inline static void code_unflag_synchronized(codeinfo *code)
+ {
+       code->flags &= ~CODE_FLAG_SYNCHRONIZED;
+ }
+ /* code_get_codeinfo_for_pv ****************************************************
+    Return the codeinfo for the given PV.
+    IN:
+        pv...............PV
+    RETURN VALUE:
+        the codeinfo *
+ *******************************************************************************/
+ inline static codeinfo *code_get_codeinfo_for_pv(void *pv)
+ {
+       codeinfo *code;
+       assert(pv != NULL);
+       code = *((codeinfo **) (((uintptr_t) pv) + CodeinfoPointer));
+       return code;
+ }
+ /* function prototypes ********************************************************/
+ void code_init(void);
+ codeinfo *code_codeinfo_new(methodinfo *m);
+ void code_codeinfo_free(codeinfo *code);
+ codeinfo *code_find_codeinfo_for_pc(void *pc);
+ codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
+ methodinfo *code_get_methodinfo_for_pv(void *pv);
+ #if defined(ENABLE_REPLACEMENT)
+ int code_get_sync_slot_count(codeinfo *code);
+ #endif /* defined(ENABLE_REPLACEMENT) */
+ void code_free_code_of_method(methodinfo *m);
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif // _CODE_HPP
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,c4a4c64f827d70b9890f1a15028949df15b074a1..1210915ea4131e15e150a53c7ebcf37b69c680d7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1075 +1,1081 @@@
+ /* src/vm/jit/codegen-common.cpp - architecture independent code generator stuff
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+    All functions assume the following code area / data area layout:
+    +-----------+
+    |           |
+    | code area | code area grows to higher addresses
+    |           |
+    +-----------+ <-- start of procedure
+    |           |
+    | data area | data area grows to lower addresses
+    |           |
+    +-----------+
+    The functions first write into a temporary code/data area allocated by
+    "codegen_init". "codegen_finish" copies the code and data area into permanent
+    memory. All functions writing values into the data area return the offset
+    relative the begin of the code area (start of procedure).  
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <string.h>
++#include "vm/jit/jitcache.hpp"
++
+ #include "vm/types.h"
+ #include "codegen.h"
+ #include "md.h"
+ #include "md-abi.h"
+ #include "mm/memory.h"
+ #include "toolbox/avl.h"
+ #include "toolbox/list.hpp"
+ #include "toolbox/logging.h"
+ #include "native/llni.h"
+ #include "native/localref.hpp"
+ #include "native/native.hpp"
+ #include "threads/thread.hpp"
+ #include "vm/jit/builtin.hpp"
+ #include "vm/exceptions.hpp"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/string.hpp"
+ # include "vm/statistics.h"
+ #include "vm/jit/abi.h"
+ #include "vm/jit/asmpart.h"
+ #include "vm/jit/code.hpp"
+ #include "vm/jit/codegen-common.hpp"
+ #if defined(ENABLE_DISASSEMBLER)
+ # include "vm/jit/disass.h"
+ #endif
+ #include "vm/jit/dseg.h"
+ #include "vm/jit/emit-common.hpp"
+ #include "vm/jit/jit.hpp"
+ #include "vm/jit/linenumbertable.hpp"
+ #include "vm/jit/methodheader.h"
+ #include "vm/jit/methodtree.h"
+ #include "vm/jit/patcher-common.hpp"
+ #include "vm/jit/replace.hpp"
+ #if defined(ENABLE_SSA)
+ # include "vm/jit/optimizing/lsra.h"
+ # include "vm/jit/optimizing/ssa.h"
+ #endif
+ #include "vm/jit/stacktrace.hpp"
+ #include "vm/jit/trace.hpp"
+ #if defined(ENABLE_INTRP)
+ #include "vm/jit/intrp/intrp.h"
+ #endif
+ #if defined(ENABLE_VMLOG)
+ #include <vmlog_cacao.h>
+ #endif
+ #include "show.hpp"
+ /* codegen_init ****************************************************************
+    TODO
+ *******************************************************************************/
+ void codegen_init(void)
+ {
+ }
+ /* codegen_setup ***************************************************************
+    Allocates and initialises code area, data area and references.
+ *******************************************************************************/
+ void codegen_setup(jitdata *jd)
+ {
+       methodinfo  *m;
+       codegendata *cd;
+       /* get required compiler data */
+       m  = jd->m;
+       cd = jd->cd;
+       /* initialize members */
+       cd->flags        = 0;
+       cd->mcodebase    = (u1*) DumpMemory::allocate(MCODEINITSIZE);
+       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
+       cd->mcodesize    = MCODEINITSIZE;
+       /* initialize mcode variables */
+       cd->mcodeptr     = cd->mcodebase;
+       cd->lastmcodeptr = cd->mcodebase;
+ #if defined(ENABLE_INTRP)
+       /* native dynamic superinstructions variables */
+       if (opt_intrp) {
+               cd->ncodebase = (u1*) DumpMemory::allocate(NCODEINITSIZE);
+               cd->ncodesize = NCODEINITSIZE;
+               /* initialize ncode variables */
+       
+               cd->ncodeptr = cd->ncodebase;
+               cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
+               cd->superstarts = NULL;
+       }
+ #endif
+       cd->dseg           = NULL;
+       cd->dseglen        = 0;
+       cd->jumpreferences = NULL;
+ #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences = NULL;
+ #endif
+       cd->brancheslabel  = new DumpList<branch_label_ref_t*>();
+       cd->linenumbers    = new DumpList<Linenumber>();
+ }
+ /* codegen_reset ***************************************************************
+    Resets the codegen data structure so we can recompile the method.
+ *******************************************************************************/
+ static void codegen_reset(jitdata *jd)
+ {
+       codeinfo    *code;
+       codegendata *cd;
+       basicblock  *bptr;
+       /* get required compiler data */
+       code = jd->code;
+       cd   = jd->cd;
+       /* reset error flag */
+       cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
+       /* reset some members, we reuse the code memory already allocated
+          as this should have almost the correct size */
+       cd->mcodeptr        = cd->mcodebase;
+       cd->lastmcodeptr    = cd->mcodebase;
+       cd->dseg            = NULL;
+       cd->dseglen         = 0;
+       cd->jumpreferences  = NULL;
+ #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences  = NULL;
+ #endif
+       cd->brancheslabel   = new DumpList<branch_label_ref_t*>();
+       cd->linenumbers     = new DumpList<Linenumber>();
+       
+       /* We need to clear the mpc and the branch references from all
+          basic blocks as they will definitely change. */
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->mpc        = -1;
+               bptr->branchrefs = NULL;
+       }
+       /* We need to clear all the patcher references from the codeinfo
+          since they all will be regenerated */
+       patcher_list_reset(code);
+ #if defined(ENABLE_REPLACEMENT)
+       code->rplpoints     = NULL;
+       code->rplpointcount = 0;
+       code->regalloc      = NULL;
+       code->regalloccount = 0;
+       code->globalcount   = 0;
+ #endif
+ }
+ /* codegen_generate ************************************************************
+    Generates the code for the currently compiled method.
+ *******************************************************************************/
+ bool codegen_generate(jitdata *jd)
+ {
+       codegendata *cd;
+       /* get required compiler data */
+       cd = jd->cd;
+       /* call the machine-dependent code generation function */
+       if (!codegen_emit(jd))
+               return false;
+       /* check for an error */
+       if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+               /* check for long-branches flag, if it is set we recompile the
+                  method */
+ #if !defined(NDEBUG)
+         if (compileverbose)
+             log_message_method("Re-generating code: ", jd->m);
+ #endif
+               /* XXX maybe we should tag long-branches-methods for recompilation */
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       /* we have to reset the codegendata structure first */
+                       codegen_reset(jd);
+                       /* and restart the compiler run */
+                       if (!codegen_emit(jd))
+                               return false;
+               }
+               else {
+                       vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
+               }
+ #if !defined(NDEBUG)
+         if (compileverbose)
+             log_message_method("Re-generating code done: ", jd->m);
+ #endif
+       }
+       /* reallocate the memory and finish the code generation */
+       codegen_finish(jd);
+       /* everything's ok */
+       return true;
+ }
+ /* codegen_close ***************************************************************
+    TODO
+ *******************************************************************************/
+ void codegen_close(void)
+ {
+       /* TODO: release avl tree on i386 and x86_64 */
+ }
+ /* codegen_increase ************************************************************
+    Doubles code area.
+ *******************************************************************************/
+ void codegen_increase(codegendata *cd)
+ {
+       u1 *oldmcodebase;
+       /* save old mcodebase pointer */
+       oldmcodebase = cd->mcodebase;
+       /* reallocate to new, doubled memory */
+       cd->mcodebase = (u1*) DumpMemory::reallocate(cd->mcodebase,
+                                                                                                cd->mcodesize,
+                                                                                                cd->mcodesize * 2);
+       cd->mcodesize *= 2;
+       cd->mcodeend   = cd->mcodebase + cd->mcodesize;
+       /* set new mcodeptr */
+       cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
+ #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
+  || defined(__SPARC_64__)
+       /* adjust the pointer to the last patcher position */
+       if (cd->lastmcodeptr != NULL)
+               cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
+ #endif
+ }
+ /* codegen_ncode_increase ******************************************************
+    Doubles code area.
+ *******************************************************************************/
+ #if defined(ENABLE_INTRP)
+ u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
+ {
+       u1 *oldncodebase;
+       /* save old ncodebase pointer */
+       oldncodebase = cd->ncodebase;
+       /* reallocate to new, doubled memory */
+       cd->ncodebase = DMREALLOC(cd->ncodebase,
+                                                         u1,
+                                                         cd->ncodesize,
+                                                         cd->ncodesize * 2);
+       cd->ncodesize *= 2;
+       /* return the new ncodeptr */
+       return (cd->ncodebase + (ncodeptr - oldncodebase));
+ }
+ #endif
+ /* codegen_add_branch_ref ******************************************************
+    Prepends an branch to the list.
+ *******************************************************************************/
+ void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+ {
+       branchref *br;
+       s4         branchmpc;
+       STATISTICS(count_branches_unresolved++);
+       /* calculate the mpc of the branch instruction */
+       branchmpc = cd->mcodeptr - cd->mcodebase;
+       br = (branchref*) DumpMemory::allocate(sizeof(branchref));
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
+       target->branchrefs = br;
+ }
+ /* codegen_resolve_branchrefs **************************************************
+    Resolves and patches the branch references of a given basic block.
+ *******************************************************************************/
+ void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
+ {
+       branchref *br;
+       u1        *mcodeptr;
+       /* Save the mcodeptr because in the branch emitting functions
+          we generate code somewhere inside already generated code,
+          but we're still in the actual code generation phase. */
+       mcodeptr = cd->mcodeptr;
+       /* just to make sure */
+       assert(bptr->mpc >= 0);
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
+       /* restore mcodeptr */
+       cd->mcodeptr = mcodeptr;
+ }
+ /* codegen_branch_label_add ****************************************************
+    Append an branch to the label-branch list.
+ *******************************************************************************/
+ void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+ {
+       // Calculate the current mpc.
+       int32_t mpc = cd->mcodeptr - cd->mcodebase;
+       branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       // Add the branch to the list.
+       cd->brancheslabel->push_back(br);
+ }
+ /* codegen_set_replacement_point_notrap ****************************************
+    Record the position of a non-trappable replacement point.
+ *******************************************************************************/
+ #if defined(ENABLE_REPLACEMENT)
+ #if !defined(NDEBUG)
+ void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
+ #else
+ void codegen_set_replacement_point_notrap(codegendata *cd)
+ #endif
+ {
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+       cd->replacementpoint++;
+ }
+ #endif /* defined(ENABLE_REPLACEMENT) */
+ /* codegen_set_replacement_point ***********************************************
+    Record the position of a trappable replacement point.
+ *******************************************************************************/
+ #if defined(ENABLE_REPLACEMENT)
+ #if !defined(NDEBUG)
+ void codegen_set_replacement_point(codegendata *cd, s4 type)
+ #else
+ void codegen_set_replacement_point(codegendata *cd)
+ #endif
+ {
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+       cd->replacementpoint++;
+ #if !defined(NDEBUG)
+       /* XXX actually we should use an own REPLACEMENT_NOPS here! */
+       if (opt_TestReplacement)
+               PATCHER_NOPS;
+ #endif
+       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+ }
+ #endif /* defined(ENABLE_REPLACEMENT) */
+ /* codegen_finish **************************************************************
+    Finishes the code generation. A new memory, large enough for both
+    data and code, is allocated and data and code are copied together
+    to their final layout, unresolved jumps are resolved, ...
+ *******************************************************************************/
+ void codegen_finish(jitdata *jd)
+ {
+       codeinfo    *code;
+       codegendata *cd;
+       s4           mcodelen;
+ #if defined(ENABLE_INTRP)
+       s4           ncodelen;
+ #endif
+       s4           alignedmcodelen;
+       jumpref     *jr;
+       u1          *epoint;
+       s4           alignedlen;
+       /* get required compiler data */
+       code = jd->code;
+       cd   = jd->cd;
+       /* prevent compiler warning */
+ #if defined(ENABLE_INTRP)
+       ncodelen = 0;
+ #endif
+       /* calculate the code length */
+       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               count_code_len += mcodelen;
+               count_data_len += cd->dseglen;
+       }
+ #endif
+       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
+ #if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               ncodelen = cd->ncodeptr - cd->ncodebase;
+       else {
+               ncodelen = 0; /* avoid compiler warning */
+       }
+ #endif
+       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
+       alignedlen = alignedmcodelen + cd->dseglen;
+ #if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+               alignedlen += ncodelen;
+       }
+ #endif
+       /* allocate new memory */
+       code->mcodelength = mcodelen + cd->dseglen;
+       code->mcode       = CNEW(u1, alignedlen);
+       /* set the entrypoint of the method */
+       
+       assert(code->entrypoint == NULL);
+       code->entrypoint = epoint = (code->mcode + cd->dseglen);
+       /* fill the data segment (code->entrypoint must already be set!) */
+       dseg_finish(jd);
+       /* copy code to the new location */
+       MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
+ #if defined(ENABLE_INTRP)
+       /* relocate native dynamic superinstruction code (if any) */
+       if (opt_intrp) {
+               cd->mcodebase = code->entrypoint;
+               if (ncodelen > 0) {
+                       u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
+                       MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
+                       /* flush the instruction and data caches */
+                       md_cacheflush(ncodebase, ncodelen);
+                       /* set some cd variables for dynamic_super_rerwite */
+                       cd->ncodebase = ncodebase;
+               } else {
+                       cd->ncodebase = NULL;
+               }
+               dynamic_super_rewrite(cd);
+       }
+ #endif
+       /* Create the exception table. */
+       exceptiontable_create(jd);
+       /* Create the linenumber table. */
+       code->linenumbertable = new LinenumberTable(jd);
+       /* jump table resolving */
+       for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
++      {
+               *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+                       (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
++              JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
++      }
++
+       /* patcher resolving */
+       patcher_resolve(jd);
+ #if defined(ENABLE_REPLACEMENT)
+       /* replacement point resolving */
+       {
+               int i;
+               rplpoint *rp;
+               rp = code->rplpoints;
+               for (i=0; i<code->rplpointcount; ++i, ++rp) {
+                       rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+               }
+       }
+ #endif /* defined(ENABLE_REPLACEMENT) */
+       /* Insert method into methodtree to find the entrypoint. */
+       methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
+ #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       /* resolve data segment references */
+       dseg_resolve_datareferences(jd);
+ #endif
+       /* flush the instruction and data caches */
+       md_cacheflush(code->mcode, code->mcodelength);
+ }
+ /* codegen_start_native_call ***************************************************
+    Prepares the stuff required for a native (JNI) function call:
+    - adds a stackframe info structure to the chain, for stacktraces
+    - prepares the local references table on the stack
+    The layout of the native stub stackframe should look like this:
+    +---------------------------+ <- java SP (of parent Java function)
+    | return address            |
+    +---------------------------+ <- data SP
+    |                           |
+    | stackframe info structure |
+    |                           |
+    +---------------------------+
+    |                           |
+    | local references table    |
+    |                           |
+    +---------------------------+
+    |                           |
+    | saved registers (if any)  |
+    |                           |
+    +---------------------------+
+    |                           |
+    | arguments (if any)        |
+    |                           |
+    +---------------------------+ <- current SP (native stub)
+ *******************************************************************************/
+ java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
+ {
+       stackframeinfo_t *sfi;
+       localref_table   *lrt;
+       methodinfo       *m;
+       int32_t           framesize;
+       uint8_t  *datasp;
+       uint8_t  *javasp;
+       uint64_t *arg_regs;
+       uint64_t *arg_stack;
+       STATISTICS(count_calls_java_to_native++);
+       /* Get the methodinfo. */
+       m = code_get_methodinfo_for_pv(pv);
+       assert(m);
+       framesize = *((int32_t *) (pv + FrameSize));
+       assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
+       /* calculate needed values */
+ #if defined(__ALPHA__) || defined(__ARM__)
+       datasp    = sp + framesize - SIZEOF_VOID_P;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) sp;
+       arg_stack = (uint64_t *) javasp;
+ #elif defined(__MIPS__)
+       /* MIPS always uses 8 bytes to store the RA */
+       datasp    = sp + framesize - 8;
+       javasp    = sp + framesize;
+ #elif defined(__S390__)
+       datasp    = sp + framesize - 8;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + 96);
+       arg_stack = (uint64_t *) javasp;
+ #elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize + SIZEOF_VOID_P;
+       arg_regs  = (uint64_t *) sp;
+       arg_stack = (uint64_t *) javasp;
+ #elif defined(__POWERPC__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
+       arg_stack = (uint64_t *) javasp;
+ #elif defined(__POWERPC64__)
+       datasp    = sp + framesize;
+       javasp    = sp + framesize;
+       arg_regs  = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
+       arg_stack = (uint64_t *) javasp;
+ #else
+       /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
+       /* XXX maybe we need to pass the RA as argument there */
+       vm_abort("codegen_start_native_call: unsupported architecture");
+ #endif
+       /* get data structures from stack */
+       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+       lrt = (localref_table *)   (datasp - sizeof(stackframeinfo_t) - 
+                                                               sizeof(localref_table));
+ #if defined(ENABLE_JNI)
+       /* add current JNI local references table to this thread */
+       localref_table_add(lrt);
+ #endif
+ #if !defined(NDEBUG)
+ # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+       /* print the call-trace if necesarry */
+       /* BEFORE: filling the local reference table */
+       if (opt_TraceJavaCalls)
+               trace_java_call_enter(m, arg_regs, arg_stack);
+ # endif
+ #endif
+ #if defined(ENABLE_HANDLES)
+       /* place all references into the local reference table */
+       /* BEFORE: creating stackframeinfo */
+       localref_native_enter(m, arg_regs, arg_stack);
+ #endif
+       /* Add a stackframeinfo for this native method.  We don't have RA
+          and XPC here.  These are determined in
+          stacktrace_stackframeinfo_add. */
+       stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
+       /* Return a wrapped classinfo for static methods. */
+       if (m->flags & ACC_STATIC)
+               return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
+       else
+               return NULL;
+ }
+ /* codegen_finish_native_call **************************************************
+    Removes the stuff required for a native (JNI) function call.
+    Additionally it checks for an exceptions and in case, get the
+    exception object and clear the pointer.
+ *******************************************************************************/
+ java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
+ {
+       stackframeinfo_t *sfi;
+       java_handle_t    *e;
+       java_object_t    *o;
+       codeinfo         *code;
+       methodinfo       *m;
+       int32_t           framesize;
+       uint8_t  *datasp;
+       uint64_t *ret_regs;
+       /* get information from method header */
+       code = code_get_codeinfo_for_pv(pv);
+       framesize = *((int32_t *) (pv + FrameSize));
+       assert(code);
+       /* get the methodinfo */
+       m = code->m;
+       assert(m);
+       /* calculate needed values */
+ #if defined(__ALPHA__) || defined(__ARM__)
+       datasp   = sp + framesize - SIZEOF_VOID_P;
+       ret_regs = (uint64_t *) sp;
+ #elif defined(__MIPS__)
+       /* MIPS always uses 8 bytes to store the RA */
+       datasp   = sp + framesize - 8;
+ #elif defined(__S390__)
+       datasp   = sp + framesize - 8;
+       ret_regs = (uint64_t *) (sp + 96);
+ #elif defined(__I386__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
+ #elif defined(__M68K__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + 2 * 8);
+ #elif defined(__X86_64__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) sp;
+ #elif defined(__POWERPC__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
+ #elif defined(__POWERPC64__)
+       datasp   = sp + framesize;
+       ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
+ #else
+       vm_abort("codegen_finish_native_call: unsupported architecture");
+ #endif
+       /* get data structures from stack */
+       sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+       /* Remove current stackframeinfo from chain. */
+       stacktrace_stackframeinfo_remove(sfi);
+ #if defined(ENABLE_HANDLES)
+       /* unwrap the return value from the local reference table */
+       /* AFTER: removing the stackframeinfo */
+       /* BEFORE: releasing the local reference table */
+       localref_native_exit(m, ret_regs);
+ #endif
+       /* get and unwrap the exception */
+       /* AFTER: removing the stackframe info */
+       /* BEFORE: releasing the local reference table */
+       e = exceptions_get_and_clear_exception();
+       o = LLNI_UNWRAP(e);
+ #if defined(ENABLE_JNI)
+       /* release JNI local references table for this thread */
+       localref_frame_pop_all();
+       localref_table_remove();
+ #endif
+ #if !defined(NDEBUG)
+ # if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+       /* print the call-trace if necesarry */
+       /* AFTER: unwrapping the return value */
+       if (opt_TraceJavaCalls)
+               trace_java_call_exit(m, ret_regs);
+ # endif
+ #endif
+       return o;
+ }
+ /* codegen_reg_of_var **********************************************************
+    This function determines a register, to which the result of an
+    operation should go, when it is ultimatively intended to store the
+    result in pseudoregister v.  If v is assigned to an actual
+    register, this register will be returned.  Otherwise (when v is
+    spilled) this function returns tempregnum.  If not already done,
+    regoff and flags are set in the stack location.
+        
+ *******************************************************************************/
+ s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
+ {
+       if (!(v->flags & INMEMORY))
+               return v->vv.regoff;
+       return tempregnum;
+ }
+ /* codegen_reg_of_dst **********************************************************
+    This function determines a register, to which the result of an
+    operation should go, when it is ultimatively intended to store the
+    result in iptr->dst.var.  If dst.var is assigned to an actual
+    register, this register will be returned.  Otherwise (when it is
+    spilled) this function returns tempregnum.  If not already done,
+    regoff and flags are set in the stack location.
+        
+ *******************************************************************************/
+ s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+ {
+       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+ }
+ /* codegen_emit_phi_moves ****************************************************
+    Emits phi moves at the end of the basicblock.
+ *******************************************************************************/
+ #if defined(ENABLE_SSA)
+ void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
+ {
+       int lt_d,lt_s,i;
+       lsradata *ls;
+       codegendata *cd;
+       varinfo *s, *d;
+       instruction tmp_i;
+       cd = jd->cd;
+       ls = jd->ls;
+       MCODECHECK(512);
+       /* Moves from phi functions with highest indices have to be */
+       /* inserted first, since this is the order as is used for   */
+       /* conflict resolution */
+       for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
+               lt_d = ls->phi_moves[bptr->nr][i][0];
+               lt_s = ls->phi_moves[bptr->nr][i][1];
+ #if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
+ #endif
+               if (lt_s == UNUSED) {
+ #if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf(" ... not processed \n");
+ #endif
+                       continue;
+               }
+                       
+               d = VAR(ls->lifetime[lt_d].v_index);
+               s = VAR(ls->lifetime[lt_s].v_index);
+               
+               if (d->type == -1) {
+ #if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+ #endif
+                       continue;
+               }
+               if (s->type == -1) {
+ #if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+ #endif
+                       continue;
+               }
+               tmp_i.opc = 0;
+               tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
+               tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
+               emit_copy(jd, &tmp_i);
+ #if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose) {
+                       if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
+                               /* mem -> mem */
+                               printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(s->flags)) {
+                               /* mem -> reg */
+                               printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(d->flags)) {
+                               /* reg -> mem */
+                               printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else {
+                               /* reg -> reg */
+                               printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       printf("\n");
+               }
+ #endif /* defined(SSA_DEBUG_VERBOSE) */
+       }
+ }
+ #endif /* defined(ENABLE_SSA) */
+ /* REMOVEME When we have exception handling in C. */
+ void *md_asm_codegen_get_pv_from_pc(void *ra)
+ {
+       return md_codegen_get_pv_from_pc(ra);
+ }
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 133b1bf61e60e826d136d0ea4e8384bbf4226f61,1252e136ac09e7e1c89e22669df606846d4db23e..b7e808cabc8f7ecaa927bb0ea5b0bb89c9e6e26a
  
  #include "vm/jit/abi.h"
  #include "vm/jit/asmpart.h"
- #include "vm/jit/codegen-common.h"
+ #include "vm/jit/codegen-common.hpp"
  #include "vm/jit/dseg.h"
- #include "vm/jit/emit-common.h"
- #include "vm/jit/jit.h"
+ #include "vm/jit/emit-common.hpp"
+ #include "vm/jit/jit.hpp"
 +#include "vm/jit/jitcache.hpp"
- #include "vm/jit/linenumbertable.h"
+ #include "vm/jit/linenumbertable.hpp"
  #include "vm/jit/parse.h"
- #include "vm/jit/patcher-common.h"
+ #include "vm/jit/patcher-common.hpp"
  #include "vm/jit/reg.h"
- #include "vm/jit/replace.h"
+ #include "vm/jit/replace.hpp"
  #include "vm/jit/stacktrace.hpp"
  #include "vm/jit/trap.h"
  
Simple merge
index 0000000000000000000000000000000000000000,b889cd59ca5d84a701e9918505f92b7631f164dd..e7dddde59906ac26f1b5a47cb9fa7c76b584d054
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1178 +1,1197 @@@
+ /* src/vm/jit/jit.cpp - Just-In-Time compiler
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <stdint.h>
+ #include "vm/types.h"
+ #include "md.h"
+ #include "mm/memory.h"
+ #include "native/native.hpp"
+ #include "toolbox/logging.h"
+ #include "threads/mutex.hpp"
+ #include "vm/class.h"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/initialize.h"
+ #include "vm/loader.hpp"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/rt-timing.h"
+ #include "vm/statistics.h"
+ #include "vm/jit/asmpart.h"
+ #include "vm/jit/cfg.h"
+ #include "vm/jit/codegen-common.hpp"
+ #include "vm/jit/disass.h"
+ #include "vm/jit/dseg.h"
+ #include "vm/jit/jit.hpp"
+ #include "vm/jit/parse.h"
+ #include "vm/jit/reg.h"
+ #include "vm/jit/show.hpp"
+ #include "vm/jit/stack.h"
+ #include "vm/jit/stubs.hpp"
++#if defined(ENABLE_JITCACHE)
++# include "vm/jit/jitcache.hpp"
++#endif
++
+ #if defined(ENABLE_OPAGENT)
+ #include "vm/jit/oprofile-agent.hpp"
+ #endif
+ #include "vm/jit/allocator/simplereg.h"
+ #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
+ # include "vm/jit/allocator/lsra.h"
+ #endif
+ #if defined(ENABLE_SSA)
+ # include "vm/jit/optimizing/lsra.h"
+ # include "vm/jit/optimizing/ssa.h"
+ #endif
+ #if defined(ENABLE_INLINING)
+ # include "vm/jit/inline/inline.h"
+ #endif
+ #include "vm/jit/ir/bytecode.h"
+ #include "vm/jit/loop/analyze.h"
+ #include "vm/jit/loop/graph.h"
+ #include "vm/jit/loop/loop.h"
+ #if defined(ENABLE_IFCONV)
+ # include "vm/jit/optimizing/ifconv.h"
+ #endif
+ #include "vm/jit/optimizing/reorder.h"
+ #if defined(ENABLE_PYTHON)
+ # include "vm/jit/python.h"
+ #endif
+ #include "vm/jit/verify/typecheck.h"
+ /* debug macros ***************************************************************/
+ #if !defined(NDEBUG)
+ #define DEBUG_JIT_COMPILEVERBOSE(x)                           \
+     do {                                                                              \
+         if (compileverbose) {                                 \
+             log_message_method(x, m);                 \
+         }                                                                             \
+     } while (0)
+ #else
+ #define DEBUG_JIT_COMPILEVERBOSE(x)    /* nothing */
+ #endif
+ #if !defined(NDEBUG)
+ # define TRACECOMPILERCALLS()                                                         \
+       do {                                                                                                    \
+               if (opt_TraceCompilerCalls) {                                           \
+                       log_start();                                                                    \
+                       log_print("[JIT compiler started: method=");    \
+                       method_print(m);                                                                \
+                       log_print("]");                                                                 \
+                       log_finish();                                                                   \
+               }                                                                                                       \
+       } while (0)
+ #else
+ # define TRACECOMPILERCALLS()
+ #endif
+ /* jit_init ********************************************************************
+    Initializes the JIT subsystem.
+ *******************************************************************************/
+ void jit_init(void)
+ {
+       TRACESUBSYSTEMINITIALIZATION("jit_init");
+ #if defined(ENABLE_JIT)
+       /* initialize stack analysis subsystem */
+       (void) stack_init();
+ #endif
+       /* initialize show subsystem */
+ #if !defined(NDEBUG)
+       (void) show_init();
+ #endif
+       /* initialize codegen subsystem */
+       codegen_init();
+       /* initialize code subsystem */
+       (void) code_init();
+       /* Machine dependent initialization. */
+ #if defined(ENABLE_JIT)
+ # if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               intrp_md_init();
+       else
+ # endif
+               md_init();
+ #else
+       intrp_md_init();
+ #endif
+ #if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::initialize();
+ #endif
+ }
+ /* jit_close *******************************************************************
+    Close the JIT subsystem.
+ *******************************************************************************/
+ void jit_close(void)
+ {
+ #if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::close();
+ #endif
+ }
+ /* dummy function, used when there is no JavaVM code available                */
+ static u1 *do_nothing_function(void)
+ {
+       return NULL;
+ }
+ /* jit_jitdata_new *************************************************************
+    Allocates and initalizes a new jitdata structure.
+ *******************************************************************************/
+ jitdata *jit_jitdata_new(methodinfo *m)
+ {
+       jitdata  *jd;
+       codeinfo *code;
+       /* allocate jitdata structure and fill it */
+       jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
+       jd->m     = m;
+       jd->cd    = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+       jd->rd    = (registerdata*) DumpMemory::allocate(sizeof(registerdata));
+ #if defined(ENABLE_LOOP)
+       jd->ld    = (loopdata*) DumpMemory::allocate(sizeof(loopdata));
+ #endif
+       /* Allocate codeinfo memory from the heap as we need to keep them. */
+       code = code_codeinfo_new(m);
+       /* Set codeinfo flags. */
+ #if defined(ENABLE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               code_flag_synchronized(code);
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               code_unflag_leafmethod(code);
+       else
+ #endif
+               code_flag_leafmethod(code);
+       /* initialize variables */
+       jd->code                 = code;
+       jd->flags                = 0;
+       jd->exceptiontable       = NULL;
+       jd->exceptiontablelength = 0;
+       jd->returncount          = 0;
+       jd->branchtoentry        = false;
+       jd->branchtoend          = false;
+       jd->returncount          = 0;
+       jd->returnblock          = NULL;
+       jd->maxlocals            = m->maxlocals;
+       return jd;
+ }
+ /* jit_compile *****************************************************************
+    Translates one method to machine code.
+ *******************************************************************************/
+ static u1 *jit_compile_intern(jitdata *jd);
+ u1 *jit_compile(methodinfo *m)
+ {
+       u1      *r;
+       jitdata *jd;
+       STATISTICS(count_jit_calls++);
+       /* Initialize the static function's class. */
+       /* ATTENTION: This MUST be done before the method lock is aquired,
+          otherwise we could run into a deadlock with <clinit>'s that
+          call static methods of it's own class. */
+       if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
+ #if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class ", m->clazz);
+ #endif
+               if (!initialize_class(m->clazz))
+                       return NULL;
+               /* check if the method has been compiled during initialization */
+               if ((m->code != NULL) && (m->code->entrypoint != NULL))
+                       return m->code->entrypoint;
+       }
+       /* enter a monitor on the method */
+       m->mutex->lock();
+       /* if method has been already compiled return immediately */
+       if (m->code != NULL) {
+               m->mutex->unlock();
+               assert(m->code->entrypoint);
+               return m->code->entrypoint;
+       }
+       TRACECOMPILERCALLS();
+       STATISTICS(count_methods++);
++#if defined (ENABLE_JITCACHE)
++
++      if (jitcache_load (m))
++      {
++              m->mutex->unlock();
++
++              return m->code->entrypoint;
++      }
++
++#endif
++
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getcompilingtime)
+               compilingtime_start();
+ #endif
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+       /* create jitdata structure */
+       jd = jit_jitdata_new(m);
+       /* set the flags for the current JIT run */
+       jd->flags = JITDATA_FLAG_PARSE;
+ #if defined(ENABLE_VERIFIER)
+       if (opt_verify)
+               jd->flags |= JITDATA_FLAG_VERIFY;
+ #endif
+ #if defined(ENABLE_PROFILING)
+       if (opt_prof)
+               jd->flags |= JITDATA_FLAG_INSTRUMENT;
+ #endif
+ #if defined(ENABLE_IFCONV)
+       if (opt_ifconv)
+               jd->flags |= JITDATA_FLAG_IFCONV;
+ #endif
+ #if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
+       if (opt_Inline && opt_InlineAll)
+               jd->flags |= JITDATA_FLAG_INLINE;
+ #endif
+       if (opt_showintermediate)
+               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+       if (opt_showdisassemble)
+               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+ #if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
+       if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
+               jd->flags |= JITDATA_FLAG_COUNTDOWN;
+       }
+ #endif
+ #if defined(ENABLE_JIT)
+ # if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+ # endif
+               /* initialize the register allocator */
+       {
+               reg_setup(jd);
+       }
+ #endif
+       /* setup the codegendata memory */
+       codegen_setup(jd);
+       /* now call internal compile function */
+       r = jit_compile_intern(jd);
+       if (r == NULL) {
+               /* We had an exception! Finish stuff here if necessary. */
+               /* release codeinfo */
+               code_codeinfo_free(jd->code);
+ #if defined(ENABLE_PROFILING)
+               /* Release memory for basic block profiling information. */
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+                       if (jd->code->bbfrequency != NULL)
+                               MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
+ #endif
+       }
+       else {
+               DEBUG_JIT_COMPILEVERBOSE("Running: ");
+       }
++#if defined (ENABLE_JITCACHE)
++      jitcache_store(m);
++#endif
++
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getcompilingtime)
+               compilingtime_stop();
+ #endif
+ #if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::newmethod(m);
+ #endif
+       /* leave the monitor */
+       m->mutex->unlock();
+       /* return pointer to the methods entry point */
+       return r;
+ }
+ /* jit_recompile ***************************************************************
+    Recompiles a Java method.
+ *******************************************************************************/
+ u1 *jit_recompile(methodinfo *m)
+ {
+       u1      *r;
+       jitdata *jd;
+       u1       optlevel;
+       /* check for max. optimization level */
+       optlevel = (m->code) ? m->code->optlevel : 0;
+ #if 0
+       if (optlevel == 1) {
+ /*            log_message_method("not recompiling: ", m); */
+               return NULL;
+       }
+ #endif
+       DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
+       STATISTICS(count_jit_calls++);
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getcompilingtime)
+               compilingtime_start();
+ #endif
+       // Create new dump memory area.
+       DumpMemoryArea dma;
+       /* create jitdata structure */
+       jd = jit_jitdata_new(m);
+       /* set the current optimization level to the previous one plus 1 */
+       jd->code->optlevel = optlevel + 1;
+       /* get the optimization flags for the current JIT run */
+ #if defined(ENABLE_VERIFIER)
+       jd->flags |= JITDATA_FLAG_VERIFY;
+ #endif
+       /* jd->flags |= JITDATA_FLAG_REORDER; */
+       if (opt_showintermediate)
+               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+       if (opt_showdisassemble)
+               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+ #if defined(ENABLE_INLINING)
+       if (opt_Inline)
+               jd->flags |= JITDATA_FLAG_INLINE;
+ #endif
+ #if defined(ENABLE_JIT)
+ # if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+ # endif
+               /* initialize the register allocator */
+               reg_setup(jd);
+ #endif
+       /* setup the codegendata memory */
+       codegen_setup(jd);
+       /* now call internal compile function */
+       r = jit_compile_intern(jd);
+       if (r == NULL) {
+               /* We had an exception! Finish stuff here if necessary. */
+               /* release codeinfo */
+               code_codeinfo_free(jd->code);
+       }
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getcompilingtime)
+               compilingtime_stop();
+ #endif
+ #if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::newmethod(m);
+ #endif
+       DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
+       /* return pointer to the methods entry point */
+       return r;
+ }
+ #if defined(ENABLE_PM_HACKS)
+ #include "vm/jit/jit_pm_1.inc"
+ #endif
+ /* jit_compile_intern **********************************************************
+    Static internal function which does the actual compilation.
+ *******************************************************************************/
+ static u1 *jit_compile_intern(jitdata *jd)
+ {
+       methodinfo  *m;
+       codegendata *cd;
+       codeinfo    *code;
+ #if defined(ENABLE_RT_TIMING)
+       struct timespec time_start,time_checks,time_parse,time_stack,
+                                       time_typecheck,time_loop,time_ifconv,time_alloc,
+                                       time_codegen;
+ #endif
+       
+       RT_TIMING_GET_TIME(time_start);
+       /* get required compiler data */
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+       jd->ls = NULL;
+ #endif
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       
+ #if defined(ENABLE_DEBUG_FILTER)
+       show_filters_apply(jd->m);
+ #endif
+       // Handle native methods and create a native stub.
+       if (m->flags & ACC_NATIVE) {
+               NativeMethods& nm = VM::get_current()->get_nativemethods();
+               void* f = nm.resolve_method(m);
+               if (f == NULL)
+                       return NULL;
+               code = NativeStub::generate(m, (functionptr) f);
+               /* Native methods are never recompiled. */
+               
+               assert(!m->code);
+               m->code = code;
+               
+               return code->entrypoint;
+       }
+       /* if there is no javacode, print error message and return empty method   */
+       if (m->jcode == NULL) {
+               DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
+               code->entrypoint = (u1 *) (ptrint) do_nothing_function;
+               m->code = code;
+               return code->entrypoint;        /* return empty method                */
+       }
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat) {
+               count_javacodesize += m->jcodelength + 18;
+               count_tryblocks    += jd->exceptiontablelength;
+               count_javaexcsize  += jd->exceptiontablelength * SIZEOF_VOID_P;
+       }
+ #endif
+       RT_TIMING_GET_TIME(time_checks);
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       /* Code for Sun's OpenJDK (see
+          hotspot/src/share/vm/classfile/verifier.cpp
+          (Verifier::is_eligible_for_verification)): Don't verify
+          dynamically-generated bytecodes. */
+ # if defined(ENABLE_VERIFIER)
+       if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
+               jd->flags &= ~JITDATA_FLAG_VERIFY;
+ # endif
+ #endif
+       /* call the compiler passes ***********************************************/
+       DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
+       /* call parse pass */
+       if (!parse(jd)) {
+               DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
+               return NULL;
+       }
+       RT_TIMING_GET_TIME(time_parse);
+       DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
+       
+ #if defined(ENABLE_JIT)
+ # if defined(ENABLE_INTRP)
+       if (!opt_intrp) {
+ # endif
+               DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
+               /* call stack analysis pass */
+               if (!stack_analyse(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
+                       return NULL;
+               }
+               RT_TIMING_GET_TIME(time_stack);
+               DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
+ #ifdef ENABLE_VERIFIER
+               if (JITDATA_HAS_FLAG_VERIFY(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
+                       /* call typecheck pass */
+                       if (!typecheck(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
+                               return NULL;
+                       }
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
+               }
+ #endif
+               RT_TIMING_GET_TIME(time_typecheck);
+ #if defined(ENABLE_LOOP)
+               if (opt_loops) {
+                       depthFirst(jd);
+                       analyseGraph(jd);
+                       optimize_loops(jd);
+                       jit_renumber_basicblocks(jd);
+               }
+ #endif
+               RT_TIMING_GET_TIME(time_loop);
+ #if defined(ENABLE_IFCONV)
+               if (JITDATA_HAS_FLAG_IFCONV(jd)) {
+                       if (!ifconv_static(jd))
+                               return NULL;
+                       jit_renumber_basicblocks(jd);
+               }
+ #endif
+               RT_TIMING_GET_TIME(time_ifconv);
+               /* inlining */
+ #if defined(ENABLE_INLINING) && (!defined(ENABLE_ESCAPE) || 1)
+               if (JITDATA_HAS_FLAG_INLINE(jd)) {
+                       if (!inline_inline(jd))
+                               return NULL;
+               }
+ #endif
+ #if defined(ENABLE_SSA)
+               if (opt_lsra) {
+                       fix_exception_handlers(jd);
+               }
+ #endif
+               /* Build the CFG.  This has to be done after stack_analyse, as
+                  there happens the JSR elimination. */
+               if (!cfg_build(jd))
+                       return NULL;
+ #if defined(ENABLE_PROFILING)
+               /* Basic block reordering.  I think this should be done after
+                  if-conversion, as we could lose the ability to do the
+                  if-conversion. */
+               if (JITDATA_HAS_FLAG_REORDER(jd)) {
+                       if (!reorder(jd))
+                               return NULL;
+                       jit_renumber_basicblocks(jd);
+               }
+ #endif
+ #if defined(ENABLE_PM_HACKS)
+ #include "vm/jit/jit_pm_2.inc"
+ #endif
+               DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
+ #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
+               /* allocate registers */
+               if (opt_lsra) {
+                       if (!lsra(jd))
+                               return NULL;
+                       STATISTICS(count_methods_allocated_by_lsra++);
+               } else
+ # endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
+ #if defined(ENABLE_SSA)
+               /* allocate registers */
+               if (
+                       (opt_lsra &&
+                       jd->code->optlevel > 0) 
+                       /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
+                       /*&& jd->exceptiontablelength == 0*/
+               ) {
+                       /*printf("=== %s ===\n", jd->m->name->text);*/
+                       jd->ls = (lsradata*) DumpMemory::allocate(sizeof(lsradata));
+                       jd->ls = NULL;
+                       ssa(jd);
+                       /*lsra(jd);*/ regalloc(jd);
+                       /*eliminate_subbasicblocks(jd);*/
+                       STATISTICS(count_methods_allocated_by_lsra++);
+               } else
+ # endif /* defined(ENABLE_SSA) */
+               {
+                       STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
+                       regalloc(jd);
+               }
+               STATISTICS(simplereg_make_statistics(jd));
+               DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
+ # if defined(ENABLE_INTRP)
+       }
+ # endif
+ #endif /* defined(ENABLE_JIT) */
+       RT_TIMING_GET_TIME(time_alloc);
+ #if defined(ENABLE_PROFILING)
+       /* Allocate memory for basic block profiling information. This
+          _must_ be done after loop optimization and register allocation,
+          since they can change the basic block count. */
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+               code->bbfrequency = MNEW(u4, jd->basicblockcount);
+ #endif
+       DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
+       /* now generate the machine code */
+ #if defined(ENABLE_JIT)
+ # if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+ #if defined(ENABLE_VERIFIER)
+               if (opt_verify) {
+                       DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
+                       if (!typecheck_stackbased(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
+                               return NULL;
+                       }
+               }
+ #endif
+               if (!intrp_codegen(jd)) {
+                       DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+                       return NULL;
+               }
+       } else
+ # endif
+               {
+                       if (!codegen_generate(jd)) {
+                               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+                               return NULL;
+                       }
+               }
+ #else
+       if (!intrp_codegen(jd)) {
+               DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+               return NULL;
+       }
+ #endif
+       RT_TIMING_GET_TIME(time_codegen);
+       DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
+ #if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
+       /* activate replacement points inside newly created code */
+       if (opt_TestReplacement)
+               replace_activate_replacement_points(code, false);
+ #endif
+ #if !defined(NDEBUG)
+ #if defined(ENABLE_DEBUG_FILTER)
+       if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+ #endif
+       {
+               /* intermediate and assembly code listings */
+               
+               if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
+                       show_method(jd, SHOW_CODE);
+               }
+               else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+ # if defined(ENABLE_DISASSEMBLER)
+                       DISASSEMBLE(code->entrypoint,
+                                               code->entrypoint + (code->mcodelength - cd->dseglen));
+ # endif
+               }
+               if (opt_showddatasegment)
+                       dseg_display(jd);
+       }
+ #endif
+       /* switch to the newly generated code */
+       assert(code);
+       assert(code->entrypoint);
+       /* add the current compile version to the methodinfo */
+       code->prev = m->code;
+       m->code = code;
+       RT_TIMING_TIME_DIFF(time_start,time_checks,RT_TIMING_JIT_CHECKS);
+       RT_TIMING_TIME_DIFF(time_checks,time_parse,RT_TIMING_JIT_PARSE);
+       RT_TIMING_TIME_DIFF(time_parse,time_stack,RT_TIMING_JIT_STACK);
+       RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
+       RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
+       RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
+       RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
+       RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
+       /* return pointer to the methods entry point */
+       return code->entrypoint;
+ } 
+ /* jit_invalidate_code *********************************************************
+    Mark the compiled code of the given method as invalid and take care that
+    it is replaced if necessary.
+    XXX Not fully implemented, yet.
+ *******************************************************************************/
+ void jit_invalidate_code(methodinfo *m)
+ {
+       codeinfo *code;
+       code = m->code;
+       if (code == NULL || code_is_invalid(code))
+               return;
+       code_flag_invalid(code);
+       /* activate mappable replacement points */
+ #if defined(ENABLE_REPLACEMENT)
+       replace_activate_replacement_points(code, true);
+ #else
+       vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
+ #endif
+ }
+ /* jit_request_optimization ****************************************************
+    Request optimization of the given method. If the code of the method is
+    unoptimized, it will be invalidated, so the next jit_get_current_code(m)
+    triggers an optimized recompilation.
+    If the method is already optimized, this function does nothing.
+    IN:
+        m................the method
+ *******************************************************************************/
+ void jit_request_optimization(methodinfo *m)
+ {
+       codeinfo *code;
+       code = m->code;
+       if (code && code->optlevel == 0)
+               jit_invalidate_code(m);
+ }
+ /* jit_get_current_code ********************************************************
+    Get the currently valid code for the given method. If there is no valid
+    code, (re)compile the method.
+    IN:
+        m................the method
+    RETURN VALUE:
+        the codeinfo* for the current code, or
+          NULL if an exception has been thrown during recompilation.
+ *******************************************************************************/
+ codeinfo *jit_get_current_code(methodinfo *m)
+ {
+       assert(m);
+       /* if we have valid code, return it */
+       if (m->code && !code_is_invalid(m->code))
+               return m->code;
+       /* otherwise: recompile */
+       if (!jit_recompile(m))
+               return NULL;
+       assert(m->code);
+       return m->code;
+ }
+ /* jit_asm_compile *************************************************************
+    This method is called from asm_vm_call_method and does:
+      - create stackframe info for exceptions
+      - compile the method
+      - patch the entrypoint of the method into the calculated address in
+        the JIT code
+      - flushes the instruction cache.
+ *******************************************************************************/
+ #if defined(ENABLE_JIT)
+ #if !defined(JIT_COMPILER_VIA_SIGNAL)
+ extern "C" {
+ void* jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra)
+ {
+       stackframeinfo_t  sfi;
+       void             *entrypoint;
+       void             *pa;
+       uintptr_t        *p;
+       /* create the stackframeinfo (subtract 1 from RA as it points to the */
+       /* instruction after the call)                                       */
+       stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ((uint8_t*) ra) - 1);
+       /* actually compile the method */
+       entrypoint = jit_compile(m);
+       /* remove the stackframeinfo */
+       stacktrace_stackframeinfo_remove(&sfi);
+       /* there was a problem during compilation */
+       if (entrypoint == NULL)
+               return NULL;
+       /* get the method patch address */
+       pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
+       /* patch the method entry point */
+       p = (uintptr_t*) pa;
+       *p = (uintptr_t) entrypoint;
+       /* flush the instruction cache */
+       md_icacheflush(pa, SIZEOF_VOID_P);
+       return entrypoint;
+ }
+ }
+ #endif
+ /* jit_compile_handle **********************************************************
+    This method is called from the appropriate signal handler which
+    handles compiler-traps and does the following:
+      - compile the method
+      - patch the entrypoint of the method into the calculated address in
+        the JIT code
+      - flush the instruction cache
+ *******************************************************************************/
+ void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
+ {
+       void      *newpv;                               /* new compiled method PV */
+       void      *pa;                                           /* patch address */
+       uintptr_t *p;                                      /* convenience pointer */
+       /* Compile the method. */
+       newpv = jit_compile(m);
+       /* There was a problem during compilation. */
+       if (newpv == NULL)
+               return NULL;
+       /* Get the method patch address. */
+       pa = md_jit_method_patch_address(pv, ra, mptr);
+       /* Patch the method entry point. */
+       p = (uintptr_t *) pa;
+       *p = (uintptr_t) newpv;
+       /* Flush both caches. */
+       md_cacheflush(pa, SIZEOF_VOID_P);
+       return newpv;
+ }
+ #endif /* defined(ENABLE_JIT) */
+ /* jit_complement_condition ****************************************************
+    Returns the complement of the passed conditional instruction.
+    We use the order of the different conditions, e.g.:
+    ICMD_IFEQ         153
+    ICMD_IFNE         154
+    If the passed opcode is odd, we simply add 1 to get the complement.
+    If the opcode is even, we subtract 1.
+    Exception:
+    ICMD_IFNULL       198
+    ICMD_IFNONNULL    199
+ *******************************************************************************/
+ s4 jit_complement_condition(s4 opcode)
+ {
+       switch (opcode) {
+       case ICMD_IFNULL:
+               return ICMD_IFNONNULL;
+       case ICMD_IFNONNULL:
+               return ICMD_IFNULL;
+       default:
+               /* check if opcode is odd */
+               if (opcode & 0x1)
+                       return opcode + 1;
+               else
+                       return opcode - 1;
+       }
+ }
+ /* jit_renumber_basicblocks ****************************************************
+    Set the ->nr of all blocks so it increases when traversing ->next.
+    IN:
+        jitdata..........the current jitdata
+ *******************************************************************************/
+ void jit_renumber_basicblocks(jitdata *jd)
+ {
+       s4          nr;
+       basicblock *bptr;
+       nr = 0;
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->nr = nr++;
+       }
+       /* we have one block more than jd->basicblockcount (the end marker) */
+       assert(nr == jd->basicblockcount + 1);
+ }
+ /* jit_check_basicblock_numbers ************************************************
+    Assert that the ->nr of the first block is zero and increases by 1 each
+    time ->next is traversed.
+    This function should be called before any analysis that relies on
+    the basicblock numbers.
+    IN:
+        jitdata..........the current jitdata
+    NOTE: Aborts with an assertion if the condition is not met!
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void jit_check_basicblock_numbers(jitdata *jd)
+ {
+       s4          nr;
+       basicblock *bptr;
+       nr = 0;
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               assert(bptr->nr == nr);
+               nr++;
+       }
+       /* we have one block more than jd->basicblockcount (the end marker) */
+       assert(nr == jd->basicblockcount + 1);
+ }
+ #endif /* !defined(NDEBUG) */
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index baf6634b4a49308690141da5b1eeae8b5d0f4e07,0000000000000000000000000000000000000000..2cd93a282e8d701f7dbd554a4331cd481c0f62f0
mode 100644,000000..100644
--- /dev/null
@@@ -1,2414 -1,0 +1,2393 @@@
- /* for mkdir() */
 +/* src/vm/jit/jitcache.c - JIT caching stuff
 +
 +   Copyright (C) 2008
 +   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 +
 +   This file is part of CACAO.
 +
 +   This program is free software; you can redistribute it and/or
 +   modify it under the terms of the GNU General Public License as
 +   published by the Free Software Foundation; either version 2, or (at
 +   your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful, but
 +   WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program; if not, write to the Free Software
 +   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 +   02110-1301, USA.
 +
 +*/
 +
 +#include "config.h"
 +
 +#if defined(ENABLE_JITCACHE)
 +
- #include "toolbox/list.h"
++#include "threads/thread.hpp"
++
++#include "toolbox/list.hpp"
++
++#include "vm/field.hpp"
++
++#include "vm/jit/builtin.hpp"
++#include "vm/jit/code.hpp"
++#include "vm/jit/codegen-common.hpp"
++#include "vm/jit/jit.hpp"
++#include "vm/jit/jitcache.hpp"
++#include "vm/jit/linenumbertable.hpp"
++#include "vm/jit/patcher-common.hpp"
++
++#include "vm/os.hpp"
++#include "vm/string.hpp"
 +
 +extern "C" {
 +
++/* for mkdir() */
 +#include <sys/stat.h>
 +
 +#include <assert.h>
 +#include <stdint.h>
 +
 +#include "md.h"
 +
- #include "vm/builtin.h"
 +#include "toolbox/logging.h"
 +
 +#include "mm/memory.h"
 +#include "mm/codememory.h"
 +
- #include "vm/jit/jit.h"
- #include "vm/jit/code.h"
- #include "vm/jit/patcher-common.h"
- #include "vm/jit/codegen-common.h"
- #include "vm/jit/linenumbertable.h"
 +#include "vm/method.h"
 +#include "vm/options.h"
 +#include "vm/resolve.h"
 +#include "vm/types.h"
 +
 +#include "vm/jit/asmpart.h"
- #include "vm/field.h"
 +#include "vm/jit/exceptiontable.h"
 +#include "vm/jit/methodtree.h"
 +
 +#include "vm/references.h"
- #include "vm/string.hpp"
- #include "vm/os.hpp"
- #include "vm/jit/jitcache.hpp"
- #include "threads/thread.hpp"
 +#include "vm/utf8.h"
 +
 +}
 +
-       code->cachedrefs = list_create(OFFSET(cachedref_t, linkage));
 +
 +/* TODO: Wrap this in vm/system.h" */
 +#include "unistd.h"
 +
 +#define CACHEROOT "/tmp/cacao-jitcache/"
 +
 +/* small grained helper functions */
 +char *get_dest_dir(methodinfo *);
 +char *get_dest_file(methodinfo *);
 +
 +int mkdir_hier(char *, mode_t);
 +int open_to_read(char *);
 +int open_to_write(char *);
 +
 +void *to_abs(void *, void *);
 +void *to_offset(void *, void *);
 +
 +void store_utf(int, utf *);
 +void store_classinfo(int, classinfo *);
 +void store_builtin(int, builtintable_entry *);
 +void store_string(int, java_object_t *);
 +void store_methodinfo(int, methodinfo *);
 +void store_fieldinfo(int, fieldinfo *);
 +void store_cachedref(int, cachedref_t *);
 +
 +void load_utf(utf **, int);
 +void load_classinfo(classinfo **, int, methodinfo *);
 +void load_builtin(builtintable_entry **, int);
 +void load_string(java_object_t **, int);
 +void load_methodinfo(methodinfo **, int, methodinfo *);
 +void load_fieldinfo(fieldinfo **, int, methodinfo *);
 +void load_cachedref(cachedref_t **, int, codeinfo *);
 +
 +/* medium grained helper functions */
 +void load_from_file_patchers(codeinfo *, int);
 +void load_from_file_cachedrefs(codeinfo *, int);
 +void load_from_file_exceptiontable(codeinfo *, int);
 +void load_from_file_linenumbertable(codeinfo *, int);
 +
 +void store_to_file_patchers(int, codeinfo *);
 +void store_to_file_cachedrefs(int, codeinfo *);
 +void store_to_file_linenumbertable(int, codeinfo *);
 +void store_to_file_exceptiontable(int, codeinfo *);
 +
 +/* file handling functions */
 +void update_method_table(methodinfo *, int);
 +int seek_method_table(methodinfo *, int);
 +int get_cache_file_readable(methodinfo *);
 +int get_cache_file_writable(methodinfo *);
 +
 +/* serializer forward declarations */
 +void s_dummy(int, patchref_t *, methodinfo *);
 +void s_unresolved_class(int, patchref_t *, methodinfo *);
 +void s_unresolved_field(int, patchref_t *, methodinfo *);
 +void s_unresolved_method(int, patchref_t *, methodinfo *);
 +void s_constant_classref(int, patchref_t *, methodinfo *);
 +void s_classinfo(int, patchref_t *, methodinfo *);
 +void s_methodinfo(int, patchref_t *, methodinfo *);
 +void s_fieldinfo(int, patchref_t *, methodinfo *);
 +void s_string(int, patchref_t *, methodinfo *);
 +
 +/* deserializer forward declarations */
 +void d_dummy(patchref_t *, int, methodinfo *);
 +void d_unresolved_class(patchref_t *, int, methodinfo *);
 +void d_unresolved_field(patchref_t *, int, methodinfo *);
 +void d_unresolved_method(patchref_t *, int, methodinfo *);
 +void d_constant_classref(patchref_t *, int, methodinfo *);
 +void d_classinfo(patchref_t *, int, methodinfo *);
 +void d_methodinfo(patchref_t *, int, methodinfo *);
 +void d_fieldinfo(patchref_t *, int, methodinfo *);
 +void d_string(patchref_t *, int, methodinfo *);
 +
 +/* The order of entries follows the order of
 + * declarations in patcher-common.h
 + */
 +
 +static jitcache_patcher_function_list_t patcher_functions[] = {
 +              { PATCHER_resolve_class, s_unresolved_class, d_unresolved_class },
 +              { PATCHER_initialize_class, s_classinfo, d_classinfo },
 +              { PATCHER_resolve_classref_to_classinfo, s_constant_classref, d_constant_classref },
 +              { PATCHER_resolve_classref_to_vftbl, s_constant_classref, d_constant_classref },
 +              { PATCHER_resolve_classref_to_index, s_constant_classref, d_constant_classref },
 +              { PATCHER_resolve_classref_to_flags, s_constant_classref, d_constant_classref },
 +              { PATCHER_resolve_native_function, s_methodinfo, d_methodinfo },
 +
 +              /* old patcher functions */
 +              { PATCHER_get_putstatic, s_unresolved_field, d_unresolved_field },
 +
 +#if defined(__I386__)
 +              { PATCHER_getfield, s_unresolved_field, d_unresolved_field },
 +              { PATCHER_putfield, s_unresolved_field, d_unresolved_field },
 +#else
 +              { PATCHER_get_putfield, s_unresolved_field, d_unresolved_field },
 +#endif
 +
 +#if defined(__I386__) || defined(__X86_64__)
 +              { PATCHER_putfieldconst, s_unresolved_field, d_unresolved_field }, /* 10 */
 +#endif
 +
 +              { PATCHER_invokestatic_special, s_unresolved_method, d_unresolved_method },
 +              { PATCHER_invokevirtual, s_unresolved_method, d_unresolved_method },
 +              { PATCHER_invokeinterface, s_unresolved_method, d_unresolved_method },
 +
 +#if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
 +              { PATCHER_checkcast_interface, s_constant_classref, d_constant_classref },
 +              { PATCHER_instanceof_interface, s_constant_classref, d_constant_classref },
 +#endif
 +
 +#if defined(__S390__)
 +              { PATCHER_checkcast_instanceof_interface, s_dummy, d_dummy },
 +#endif
 +
 +#if defined(__I386__)
 +              { PATCHER_aconst, s_constant_classref, d_constant_classref }, /* 16 */
 +              { PATCHER_builtin_multianewarray, s_constant_classref, d_constant_classref },
 +              { PATCHER_builtin_arraycheckcast, s_constant_classref, d_constant_classref },
 +              { PATCHER_checkcast_instanceof_flags, s_constant_classref, d_constant_classref },
 +              { PATCHER_checkcast_class, s_constant_classref, d_constant_classref },
 +              { PATCHER_instanceof_class, s_constant_classref, d_constant_classref },
 +#endif
 +
 +              { NULL, s_dummy, d_dummy }
 +};
 +
 +#define JC_MRU_SIZE 100
 +static classinfo *jc_mru_list[JC_MRU_SIZE];
 +int mru_last_free = 0;
 +int mru_start = 0;
 +
 +/* jitcache_mru_add ************************************************************
 +
 +   Adds a classinfo to the most recently used (MRU) list. The MRU uses a simple
 +   strategy: it will store entries until it is full, further candidates replace
 +   the 
 +
 +*******************************************************************************/
 +
 +void jitcache_mru_add(classinfo *c, int fd)
 +{
 +      classinfo *old_c;
 +      assert(!c->cache_file_fd);
 +
 +      c->cache_file_fd = fd;
 +
 +      if (mru_last_free < JC_MRU_SIZE) {
 +              jc_mru_list[mru_last_free] = c;
 +
 +              mru_last_free++;
 +
 +              return;
 +      }
 +      else {
 +              mru_start--;
 +              if (mru_start < 0)
 +                      mru_start = JC_MRU_SIZE - 1;
 +
 +              old_c = jc_mru_list[mru_start];
 +
 +              assert (old_c);
 +              assert (old_c->cache_file_fd);
 +              os::close(old_c->cache_file_fd);
 +              old_c->cache_file_fd = 0;
 +
 +              jc_mru_list[mru_start] = c;
 +      }
 +      
 +}
 +
 +void jitcache_mru_remove(classinfo *c)
 +{
 +      int i, j;
 +
 +      for (i = 0; i < JC_MRU_SIZE; i++)
 +              if (jc_mru_list[i] == c) {
 +                      jc_mru_list[j] = NULL;
 +
 +                      for (j = i; i < mru_last_free - 1; j++)
 +                              jc_mru_list[j] = jc_mru_list[j+1];
 +
 +                      mru_last_free--;
 +              }
 +
 +      assert (0);
 +}
 +
 +/* jitcache_list_create ********************************************************
 +
 +   Creates an empty cached reference list for the given codeinfo.
 +
 +*******************************************************************************/
 +
 +void jitcache_list_create(codeinfo *code)
 +{
-       cachedref_t *pr;
-       /* free all elements of the list */
-       while((pr = (cachedref_t *) list_first(code->cachedrefs)) != NULL) {
-               list_remove(code->cachedrefs, pr);
-               FREE(pr, cachedref_t);
- #if defined(ENABLE_STATISTICS)
-               if (opt_stat)
-                       size_cachedref -= sizeof(cachedref_t);
- #endif
-       }
++      code->cachedrefs = new List<cachedref_t>();
 +}
 +
 +
 +/* jitcache_list_reset **********************************************************
 +
 +   Resets the cached reference list inside a codeinfo.
 +
 +*******************************************************************************/
 +
 +void jitcache_list_reset(codeinfo *code)
 +{
-       FREE(code->cachedrefs, list_t);
++      code->cachedrefs->clear();
 +}
 +
 +
 +/* jitcache_list_free ***********************************************************
 +
 +   Frees the cached reference list and all its entries for the given codeinfo.
 +
 +*******************************************************************************/
 +
 +void jitcache_list_free(codeinfo *code)
 +{
 +      /* free all elements of the list */
 +
 +      jitcache_list_reset(code);
 +
 +      /* free the list itself */
 +
-       cachedref_t *cr;
++      delete code->cachedrefs;
++      code->cachedrefs = 0;
 +}
 +
 +
 +/* jitcache_list_find ***********************************************************
 +
 +   Find an entry inside the cached reference list for the given codeinfo
 +   by specifying the displacement in the code/data segment.
 +
 +   NOTE: Caller should hold the patcher list lock or maintain
 +   exclusive access otherwise.
 +
 +*******************************************************************************/
 +
 +static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
 +{
-       cr = (cachedref_t *) list_first(code->cachedrefs);
-       while (cr) {
-               if (cr->disp == disp)
-                       return cr;
 +      /* walk through all cached references for the given codeinfo */
 +
-               cr = (cachedref_t *) list_next(code->cachedrefs, cr);
++      for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
++                      it != code->cachedrefs->end(); it++)
++      {
 +
- cachedref_t *jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
++              if (it->disp == disp)
++                      return &(*it);
 +      }
 +
 +      return NULL;
 +}
 +
 +
 +/* jitcache_new_cachedref ******************************************************
 +
 +   Creates and initializes a new cachedref
 +
 +*******************************************************************************/
 +
-       cachedref_t *cr;
-       /* allocate cachedref on heap (at least freed together with codeinfo) */
-       cr = NEW(cachedref_t);
- #if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               size_cachedref += sizeof(cachedref_t);
- #endif
++cachedref_t jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
 +{
-       cr->type    = type;
-       cr->md_patch= md_patch;
-       cr->disp    = disp;
-       cr->ref     = ref;
++      cachedref_t cr;
 +
 +      /* set reference information */
 +
- /* jitcache_add_cachedref_jd ***************************************************
++      cr.type    = type;
++      cr.md_patch= md_patch;
++      cr.disp    = disp;
++      cr.ref     = ref;
 +
 +      return cr;
 +}
-    Creates a new cached ref appends it to the list in the codeinfo structure
-    *or* attaches it to the *last* patchref_t if it overlaps with the address
-    of the cached reference.
++/* jitcache_add_cachedref_intern ***********************************************
 +
- void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
++   Creates a new cached ref appends it to the list in the codeinfo structure.
 +
 +*******************************************************************************/
 +
-       cachedref_t *list_cr;
-       list_cr = (cachedref_t *) list_first(code->cachedrefs);
++void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t cachedref)
 +{
-       while (list_cr)
++      List<cachedref_t>::iterator it = code->cachedrefs->begin();
 +
-               if (list_cr->disp == cachedref->disp)
++      while (it != code->cachedrefs->end())
 +      {
-                       assert(list_cr->type == cachedref->type);
-                       assert(list_cr->ref == cachedref->ref);
++              if (it->disp == cachedref.disp)
 +              {
-               list_cr = (cachedref_t *) list_next(code->cachedrefs, list_cr);
++                      assert(it->type == cachedref.type);
++                      assert(it->ref == cachedref.ref);
 +
 +                      /* Cachedref for already existing object found. No need to store
 +                       * it.
 +             */
 +                      return;
 +              }
 +
-       list_add_first(code->cachedrefs, cachedref);
++              it++;
 +      }
 +
-       patchref_t       *patchref;
++      code->cachedrefs->push_front(cachedref);
 +}
 +
 +/* jitcache_add_cachedref_jd ***************************************************
 +
 +   Creates a new cached ref appends it to the list in the codeinfo structure
 +   *or* attaches it to the *last* patchref_t if it overlaps with the address
 +   of the cached reference.
 +
 +*******************************************************************************/
 +
 +void jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, void* ref)
 +{
 +      jitcache_add_cached_ref_md_jd(jd, type, 0, ref);
 +}
 +
 +
 +/* jitcache_add_cachedref_md_jd ************************************************
 +
 +   Creates a new cached ref appends it to the list in the codeinfo structure
 +   *or* attaches it to the *last* patchref_t if it overlaps with the address
 +   of the cached reference.
 +
 +*******************************************************************************/
 +
 +void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, void* ref)
 +{
-       cachedref_t *cachedref;
++      patchref_t       patchref;
 +      codegendata      *cd;
 +      ptrint                   disp;
-       patchref = (patchref_t *) list_first(jd->code->patchers);
++      cachedref_t  cachedref;
 +
 +      if (type >= CRT_OBJECT_HEADER && !ref)
 +              return;
 +
 +      cd = jd->cd;
 +
 +      disp = (ptrint) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
 +      cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
 +
-       if (patchref
-               && (patchref->mpc) <= disp
-               && (patchref->mpc + sizeof(patchref->mcode)) >= disp)
++      patchref = jd->code->patchers->front();
 +
-          */
++      if ((patchref.mpc) <= disp
++                && (patchref.mpc + sizeof(patchref.mcode)) >= disp)
 +      {
 +              /* patchers and cachedref overlap: cached ref must
 +               * be handled after the patcher.
-          * If the need arises to handle more cached refs a list can
-          * be used.
-          */
-               assert(!patchref->attached_ref);
++     */
 +
 +              if (opt_DebugJitCache)
 +              {
 +                      log_message_method("cached ref overlaps with patchref: ", jd->m);
 +              }
 +
 +              /* There can be only one cached ref per patcher currently.
-               patchref->attached_ref = cachedref;
++     * If the need arises to handle more cached refs a list can
++     * be used.
++     */
++              assert(!patchref.attached_ref);
 +
-       cachedref_t *cr;
++              patchref.attached_ref = &cachedref;
 +      }
 +      else
 +              jitcache_add_cached_ref_intern(jd->code, cachedref);
 +}
 +
 +
 +/* jitcache_add_cachedref ******************************************************
 +
 +   Creates a new cached references and appends it to the list.
 +
 +*******************************************************************************/
 +
 +void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, void* ref, s4 disp)
 +{
-       return mkdir(path, mode);
++      cachedref_t cr;
 +
 +      /* allocate cachedref on heap (at least freed together with codeinfo) */
 +      cr = jitcache_new_cached_ref(type, 0, ref,disp);
 +
 +      jitcache_add_cached_ref_intern(code, cr);
 +}
 +
 +
 +
 +/* jitcache_handle_cached_ref **************************************************
 +
 +   Creates a new cached references and appends it to the list.
 +
 +*******************************************************************************/
 +
 +void jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code)
 +{
 +      u1 **location;
 +
 +      location = (u1 **) (code->entrypoint + cr->disp);
 +
 +      /* Write the restored reference into the code. */
++#if defined (__ARM__)
 +      if (cr->md_patch)
 +              patch_md(cr->md_patch, (ptrint) location, cr->ref);
 +      else
++#endif
 +              *location = (u1 *) cr->ref;
 +
 +      md_cacheflush(location, SIZEOF_VOID_P);
 +
 +      FREE(cr, cachedref_t);
 +}
 +
 +#include <stdlib.h>
 +#include <stdio.h>
 +
 +bool filter(utf *classname)
 +{
 +      static bool printed = false;
 +      char *buf = NULL;
 +      int i = 0;
 +      int max_index = 30000;
 +      const char *classes[] = {
 +              "Test$FooBar",
 +              "Test",
 +              "FieldTest",
 +              "UnresolvedClass",
 +              "java/lang/ThreadGroup",
 +              "java/lang/Object",
 +              "java/util/Vector",
 +              "java/util/Vector$1",
 +              "java/util/AbstractList", 
 +              "java/util/AbstractCollection",
 +              "java/lang/Thread",
 +              "java/lang/String",
 +              "java/lang/ClassLoader",
 +              "java/lang/VMClassLoader",
 +              "java/util/HashMap",
 +              "java/util/HashSet",
 +              "java/util/AbstractSet",
 +              "gnu/classpath/SystemProperties",
 +              "java/util/Properties",
 +              "java/util/Hashtable",
 +              "java/util/Dictionary",
 +              "java/util/Hashtable$HashEntry",
 +              "java/util/AbstractMap$SimpleEntry",
 +              "java/lang/StringBuilder",
 +              "java/lang/AbstractStringBuffer",
 +              "java/util/Collections$SynchronizedSet",
 +              "java/util/Collections$SynchronizedCollection",
 +              "java/util/Hashtable$3",
 +              "java/util/Hashtable$EntryIterator",
 +              "java/util/Collections$SynchronizedIterator",
 +              "java/lang/Boolean",
 +              "java/util/Collections",
 +              "java/util/Collections$EmptySet",
 +              "java/util/Collections$EmptyList",
 +              "java/util/Collections$EmptyMap",
 +              "java/util/Collections$ReverseComparator",
 +              "java/util/Collections$UnmodifiableMap",
 +              "java/io/File",
 +              "java/util/StringTokenizer",
 +              "java/util/ArrayList",
 +              "java/io/VMFile",
 +              "java/lang/System",
 +              "java/lang/VMSystem",
 +              "java/io/FileDescriptor",
 +              "gnu/java/io/FileChannelImpl",
 +              "java/lang/Runtime",
 +              "gnu/classpath/VMStackWalker",
 +              "gnu/java/io/VMChannel",
 +              "gnu/java/io/VMChannel$State",
 +              "gnu/java/io/VMChannel$Kind",
 +              "java/nio/channels/FileChannelImpl",
 +              "java/nio/channels/spi/AbstractInterruptibleChannel",
 +              "java/lang/Number",
 +              "java/io/FileInputStream",
 +              "java/io/InputStream",
 +              "java/io/BufferedInputStream",
 +              "java/io/FilterInputStream",
 +              "java/io/PrintStream",
 +              "java/io/OutputStream",
 +              "java/io/BufferedOutputStream",
 +              "java/io/FilterOutputStream",
 +              "java/net/URL",
 +              "java/util/Locale",
 +              "java/lang/Math",
 +              "gnu/java/lang/CharData",
 +              "java/lang/Character",
 +              "java/net/URL$1",
 +              "java/security/VMAccessController",
 +              "java/lang/ThreadLocal",
 +              "java/security/CodeSource",
 +              "**placeholder**",
 +              "java/security/PermissionCollection",
 +              "Test$1",
 +              "java/security/ProtectionDomain",
 +              "java/security/AccessControlContext",
 +              "gnu/java/util/WeakIdentityHashMap",
 +              "gnu/java/util/WeakIdentityHashMap$WeakEntrySet",
 +              "java/lang/ref/ReferenceQueue",
 +              "java/util/LinkedList",
 +              "java/util/AbstractSequentialList",
 +              "gnu/java/util/WeakIdentityHashMap$WeakBucket$WeakEntry",
 +              "java/util/LinkedList$Entry",
 +              "java/lang/Class",
 +              "java/lang/reflect/VMConstructor",
 +              "java/lang/reflect/Constructor",
 +              "java/lang/reflect/Modifier",
 +              "gnu/java/net/protocol/file/Handler",
 +              "java/net/URLStreamHandler",
 +              "java/util/ArrayList",
 +              "java/security/SecureClassLoader",
 +              "java/lang/Exception",
 +              "java/lang/Throwable",
 +              "java/lang/VMThrowable",
 +              "gnu/java/net/loader/FileURLLoader",
 +              "gnu/java/net/loader/URLLoader",
 +              "java/security/Policy",
 +              "gnu/java/security/provider/DefaultPolicy",
 +              "gnu/java/net/loader/Resource",
 +              "gnu/java/net/loader/FileResource", 
 +              "java/io/FileInputStream", 
 +              "gnu/java/nio/FileChannelImpl",
 +              "java/nio/ByteBuffer",
 +              "java/nio/Buffer",
 +              "java/nio/ByteOrder",
 +              "java/security/Permissions$PermissionsHash",
 +              "java/nio/charset/Charset",
 +              "gnu/java/nio/charset/Provider",
 +              "gnu/java/nio/charset/Provider$1",
 +              "gnu/java/nio/charset/US_ASCII",
 +              "java/util/Collections$UnmodifiableSet/",
 +              "java/util/Collections$UnmodifiableCollection",
 +              "java/util/Collections$UnmodifiableIterator",
 +              "gnu/java/nio/charset/ISO_8859_1",
 +              "gnu/java/nio/charset/UTF_8",
 +              "gnu/java/nio/charset/UTF_16BE",
 +              "gnu/java/nio/charset/UTF_16LE",
 +              "gnu/java/nio/charset/UTF_16",
 +              "gnu/java/nio/charset/UnicodeLittle",
 +              "gnu/java/nio/charset/Windows1250",
 +              "gnu/java/nio/charset/Windows1250",
 +              "gnu/java/nio/charset/ByteCharset",
 +              "gnu/java/nio/charset/Windows1251",
 +              "gnu/java/nio/charset/Windows1252",
 +              "gnu/java/nio/charset/Windows1253",
 +              "gnu/java/nio/charset/Windows1254",
 +              "gnu/java/nio/charset/Windows1257",
 +              "gnu/java/nio/charset/ISO_8859_2",
 +              "gnu/java/nio/charset/ISO_8859_4",
 +              "gnu/java/nio/charset/ISO_8859_5",
 +              "gnu/java/nio/charset/ISO_8859_7",
 +              "gnu/java/nio/charset/ISO_8859_9",
 +              "gnu/java/nio/charset/ISO_8859_13",
 +              "gnu/java/nio/charset/ISO_8859_15",
 +              "gnu/java/nio/charset/KOI_8",
 +              "gnu/java/nio/charset/ISO_8859_1$Encoder",
 +              "java/nio/charset/CharsetEncoder",
 +              "gnu/java/nio/charset/ByteEncodeLoopHelper",
 +              "java/nio/charset/CodingErrorAction",
 +              "java/nio/CharBuffer",
 +              "java/nio/CharBufferImpl",
 +              "gnu/java/nio/charset/ByteEncodeLoopHelper",
 +              "java/nio/charset/CoderResult",
 +              "java/nio/charset/CoderResult$1",
 +              "java/nio/charset/CoderResult$2",
 +              "java/nio/charset/CoderResult$Cache",
 +              "java/awt/Toolkit",
 +              "gnu/java/awt/peer/gtk/GtkToolkit",
 +              "gnu/java/awt/peer/gtk/GtkGenericPeer",
 +              "java/util/WeakHashMap",
 +              "java/util/WeakHashMap$1", 
 +              "java/util/WeakHashMap$WeakEntrySet",
 +              "gnu/java/awt/peer/gtk/GtkWindowPeer",
 +              "gnu/java/awt/peer/gtk/GtkCheckboxPeer",
 +              "gnu/java/awt/peer/gtk/GtkFileDialogPeer",
 +              "gnu/java/awt/peer/gtk/GtkMainThread",
 +              "java/security/AccessController",
 +              "java/security/Permission",
 +              "java/lang/ClassLoader$StaticData",
 +              "java/lang/VMString",
 +              "gnu/java/lang/CPStringBuilder",
 +              "gnu/java/lang/VMCPStringBuilder",
 +              "java/io/FileOutputStream",
 +              "gnu/java/nio/VMChannel",
 +              "gnu/java/nio/VMChannel$State",
 +              "gnu/java/nio/VMChannel$Kind",
 +              "java/nio/channels/FileChannel",
 +              "gnu/classpath/VMSystemProperties",
 +              "java/lang/StringBuffer",
 +              "java/lang/VMRuntime",
 +              "java/lang/VMObject",
 +              "java/lang/VMThread",
 +              "java/lang/VMClass",
 +              "java/lang/InheritableThreadLocal",
 +              "java/lang/ClassNotFoundException",
 +              "java/net/URLClassLoader",
 +              "java/lang/ClassLoader$1",
 +              "java/nio/ByteBufferImpl",
 +              "java/io/FilePermission",
 +              "gnu/java/nio/charset/ISO_8859_1$Encoder$1",
 +              "java/nio/charset/spi/CharsetProvider",
 +              "gnu/java/net/loader/URLStreamHandlerCache",
 +              "java/util/HashMap$HashIterator",
 +              "java/util/HashMap$HashEntry",
 +              "java/util/AbstractMap",
 +              "java/util/AbstractMap$1",
 +              "java/lang/RuntimeException",
 +              "java/util/Collections$UnmodifiableSet",
 +              "java/lang/ref/Reference",
 +              "java/lang/ref/WeakReference",
 +              "gnu/java/util/WeakIdentityHashMap$WeakBucket",
 +              "gnu/java/util/WeakIdentityHashMap$WeakEntrySet$1",
 +              "java/lang/String$CaseInsensitiveComparator",
 +              "java/lang/Throwable$StaticData",
 +              "java/lang/StackTraceElement",
 +              "java/lang/VMMath",
 +              "java/lang/Double",
 +              "java/lang/VMDouble",
 +              "java/lang/Long",
 +              "java/lang/Float",
 +              "java/lang/VMFloat",
 +              "java/security/Permissions", /* 200 */
 +              "java/security/AllPermission", 
 +              "java/security/AllPermission$AllPermissionCollection",
 +              "java/util/AbstractMap$1$1", /* 203 */
 +              "java/lang/Integer",
 +              
 +              NULL };
 +
 +      if (getenv("FILTER_VERBOSE") && !printed)
 +      {
 +              i = 0;
 +              while (classes[i])
 +              {
 +                      log_println("[%d] - %s", i, classes[i]);
 +                      i++;
 +              }
 +
 +              printed = true;
 +      }
 +
 +      buf = getenv("INDEX");
 +      if (buf)
 +              sscanf(buf, "%d", &max_index);
 +
 +      i = 0;
 +      while (classes[i] && i <= max_index)
 +      {
 +
 +              if (!strcmp(classes[i], classname->text))
 +                      return true;
 +
 +              i++;
 +      }
 +
 +      if ((buf = getenv("FILTER_VERBOSE")))
 +      {
 +              log_println("filtered: %s", classname->text);
 +      }
 +
 +      return false;
 +}
 +
 +void filter_match()
 +{
 +      /* Wohoo! */
 +}
 +
 +/**
 + * Causes filter_match() on which one can set a breakpoint in the debugger
 + * in the following conditions:
 + *
 + * If the environment variable NO_FILTER is set, then filter_match() is not
 + * called at all. This disables filter capabilities.
 + *
 + * If environment variable TEST_CLASS is set and the method belong to this
 + * class and there is no variable TEST_METHOD then filter_match() is called.
 + *
 + * If TEST_CLASS and TEST_METHOD match the methodinfo and TEST_DESCRIPTOR is
 + * not set.
 + *
 + * If TEST_CLASS, TEST_METHOD and TEST_DESCRIPTOR match the methodinfo's values.
 + */
 +void filter_single(methodinfo *m)
 +{
 +      char *buf = NULL;
 +
 +      buf = getenv("NO_FILTER");
 +      if (buf)
 +              return;
 +
 +      buf = getenv("TEST_CLASS");
 +      if (!buf || strcmp(m->clazz->name->text, buf))
 +              return;
 +
 +      buf = getenv("TEST_METHOD");
 +      if (!buf)
 +      {
 +              filter_match();
 +              return;
 +      }
 +      else if (strcmp(m->name->text, buf))
 +              return;
 +
 +      buf = getenv("TEST_DESCRIPTOR");
 +      if (!buf)
 +      {
 +              filter_match();
 +              return;
 +      }
 +      else if (strcmp(m->descriptor->text, buf))
 +              return;
 +
 +      filter_match();
 +}
 +
 +Mutex *jitcache_lock;
 +
 +/* jitcache_store **************************************************************
 +
 +   Saves the generated machine code to disk.
 +
 +*******************************************************************************/
 +void jitcache_store (methodinfo *m)
 +{
 +      static int init_lock = true;
 +      void *temp;
 +      int fd;
 +
 +      if (init_lock)
 +      {
 +              jitcache_lock = new Mutex();
 +              init_lock = false;
 +      }
 +
 +/*
 +      filter_single(m);
 +
 +      if (!filter(m->clazz->name))
 +              return;
 +*/
 +
 +      /* Never try to store native method stubs because those include a reference
 +       * a dynamically resolved function.
 +     *
 +     * TODO: Handle those, too.
 +       */
 +      if (m->flags & ACC_NATIVE)
 +              return;
 +
 +      fd = get_cache_file_writable(m);
 +      if (!fd)
 +      {
 +              if (opt_DebugJitCache)
 +            log_message_method("[jitcache] store: got no file descriptor for ", m);
 +
 +      return;
 +      }
 +
 +      /* Write (and some read) file operations beyond this point.
 +       * Acquire lock first because another thread may try to load a different
 +     * method from this class.
 +     */
 +/*    Mutex_lock(&m->clazz->cache_file_lock);*/
 +      jitcache_lock->lock();
 +
 +      if (opt_DebugJitCache)
 +      log_message_method("[jitcache] store: ", m);
 +
 +      update_method_table(m, fd);
 +
 +      /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
 +    */
 +      system_write(fd, (const void *) &m->code->flags, sizeof(m->code->flags));
 +
 +      system_write(fd, (const void *) &m->code->optlevel, sizeof(m->code->optlevel));
 +      system_write(fd, (const void *) &m->code->basicblockcount, sizeof(m->code->basicblockcount));
 +
 +      system_write(fd, (const void *)  &m->code->synchronizedoffset, sizeof(m->code->synchronizedoffset));
 +
 +      system_write(fd, (const void *)  &m->code->stackframesize, sizeof(m->code->stackframesize));
 +
 +      temp = to_offset(m->code->mcode, m->code->entrypoint);
 +      system_write(fd, (const void *) &temp, sizeof(temp));
 +
 +      system_write(fd, (const void *) &m->code->mcodelength, sizeof(m->code->mcodelength));
 +
 +      system_write(fd, (const void *) m->code->mcode, m->code->mcodelength);
 +
 +      store_to_file_exceptiontable(fd, m->code);
 +
 +      store_to_file_linenumbertable(fd, m->code);
 +
 +      store_to_file_patchers(fd, m->code);
 +
 +      store_to_file_cachedrefs(fd, m->code);
 +
 +/*    Mutex_unlock(&m->clazz->cache_file_lock);*/
 +      jitcache_lock->unlock();
 +
 +}
 +
 +/* jitcache_load ***************************************************************
 +
 +   Try to load previously generated machine code from disk.
 +
 +   Returns non-zero if successfull.
 +
 +*******************************************************************************/
 +
 +u1 jitcache_load (methodinfo *m)
 +{
 +      codeinfo *code;
 +      u1 *endpc;
 +      int fd;
 +
 +/*
 +      if (!filter(m->clazz->name))
 +              return false;
 +*/
 +
 +      /* Never try to store native method stubs because those include a reference
 +       * a dynamically resolved function.
 +       */
 +      if (m->flags & ACC_NATIVE)
 +              return false;
 +
 +      fd = get_cache_file_readable(m);
 +      if (fd <= 0)
 +      {
 +              if (opt_DebugJitCache)
 +            log_message_method("[jitcache] load: got no file descriptor for ", m);
 +
 +      return false;
 +      }
 +
 +      if(!seek_method_table(m, fd))
 +      {
 +              os::close(fd);
 +
 +              return false;
 +      }
 +
 +      if (opt_DebugJitCache)
 +              log_message_method("[jitcache] load: ", m);
 +
 +      code = code_codeinfo_new(m);
 +      m->code = code;
 +
 +      /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
 +    */
 +      system_read(fd, (void *) &code->flags, sizeof(code->flags));
 +
 +      system_read(fd, (void *) &code->optlevel, sizeof(code->optlevel));
 +      system_read(fd, (void *) &code->basicblockcount, sizeof(code->basicblockcount));
 +
 +      system_read(fd, (void *) &code->synchronizedoffset, sizeof(code->synchronizedoffset));
 +
 +      system_read(fd, (void *) &code->stackframesize, sizeof(code->stackframesize));
 +
 +      system_read(fd, (void *) &code->entrypoint, sizeof(code->entrypoint));
 +
 +      system_read(fd, (void *) &code->mcodelength, sizeof(code->mcodelength));
 +
 +      code->mcode = CNEW(u1, code->mcodelength);
 +      system_read(fd, (void *) code->mcode, code->mcodelength);
 +      code->entrypoint = (u1 *) to_abs(code->mcode, code->entrypoint);
 +
 +      load_from_file_exceptiontable(code, fd);
 +
 +      load_from_file_linenumbertable(code, fd);
 +
 +      load_from_file_patchers(code, fd);
 +
 +      load_from_file_cachedrefs(code, fd);
 +
 +      os::close(fd);
 +
 +      endpc = (u1 *) ((ptrint) code->mcode) + code->mcodelength;
 +
 +      /* Insert method into methodtree to find the entrypoint. */
 +
 +      methodtree_insert(code->entrypoint, endpc);
 +
 +      /* flush the instruction and data caches */
 +
 +      md_cacheflush(code->mcode, code->mcodelength);
 +
 +      if (opt_DebugJitCache)
 +      {
 +              log_println("[jitcache] load - registered method: %x -> %x", code->entrypoint, endpc);
 +      }
 +
 +      return true;
 +}
 +
 +void jitcache_quit()
 +{
 +      int i;
 +
 +      for (i = 0; i < mru_last_free; i++)
 +      {
 +              os::close(jc_mru_list[i]->cache_file_fd);
 +              jc_mru_list[i]->cache_file_fd = 0;
 +              jc_mru_list[i] = 0;
 +      }
 +
 +      mru_last_free = 0;
 +
 +      /* Closes all open file descriptors. */
 +}
 +
 +void jitcache_freeclass(classinfo *c)
 +{
 +      if (c->cache_file_fd)
 +              jitcache_mru_remove(c);
 +}
 +
 +/* Helper functions */
 +void update_method_table(methodinfo *m, int fd)
 +{
 +      int state = 0, i, temp, offset = 0;
 +
 +      system_lseek(fd, 0, SEEK_SET);
 +
 +      system_read(fd, (void *) &state, sizeof(state));
 +
 +      /* table does not exist yet and needs to be created first */
 +      if (state != 1)
 +      {
 +              system_lseek(fd, 0, SEEK_SET);
 +              state = 1;
 +              system_write(fd, &state, sizeof(state));
 +
 +              temp = -1;
 +              for (i = 0; i < m->clazz->methodscount; i++)
 +                      system_write(fd, &temp, sizeof(temp));
 +      }
 +
 +      /* get last offset in file */
 +      offset = system_lseek(fd, 0, SEEK_END);
 +
 +      /* find out the index in the methods array */
 +      temp = -1;
 +      for (i = 0; i < m->clazz->methodscount; i++)
 +              if (&m->clazz->methods[i] == m)
 +              {
 +                      temp = i;
 +                      break;
 +              }
 +      assert(temp != -1);
 +
 +      /* seek to the method's entry in the table */
 +      system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
 +
 +      /* enter the location */
 +      system_write(fd, &offset, sizeof(offset));
 +
 +      system_lseek(fd, offset, SEEK_SET);
 +}
 +
 +int seek_method_table(methodinfo *m, int fd)
 +{
 +      int state = 0, i, temp, offset;
 +
 +      system_lseek(fd, 0, SEEK_SET);
 +
 +      system_read(fd, (void *) &state, sizeof(state));
 +
 +      /* if table does not exist, we cannot load any machine code from this file */
 +      if (state != 1)
 +              return 0;
 +
 +      /* find out the index in the methods array */
 +      temp = -1;
 +      for (i = 0; i < m->clazz->methodscount; i++)
 +              if (&m->clazz->methods[i] == m)
 +              {
 +                      temp = i;
 +                      break;
 +              }
 +      assert(temp != -1);
 +
 +      /* seek to the method's entry in the table */
 +      system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
 +
 +      /* get the location */
 +      system_read(fd, &offset, sizeof(offset));
 +
 +      if (offset > 0)
 +      {
 +              system_lseek(fd, offset, SEEK_SET);
 +              return offset;
 +      }
 +
 +      return 0;
 +}
 +
 +int get_cache_file_readable(methodinfo *m)
 +{
 +      char *dest_file;
 +      int fd;
 +
 +      if (m->clazz->cache_file_fd)
 +              return dup(m->clazz->cache_file_fd);
 +
 +
 +      /* load from filesystem */
 +      dest_file = get_dest_file(m);
 +
 +      if (os::access(dest_file, F_OK) != 0)
 +      {
 +              if (opt_DebugJitCache)
 +                      log_message_method("[jitcache] no cache file found for ", m);
 +
++              perror("get_cache_file_writable: ");
++
 +              os::free(dest_file);
 +
 +              return 0;
 +      }
 +
 +/*
 +      filter_single(m);
 +*/
 +
 +      fd = open_to_read(dest_file);
 +
 +      os::free(dest_file);
 +
 +/*
 +      if (fd > 0)
 +              jitcache_mru_add(m->clazz, fd);
 +*/
 +      return fd;
 +}
 +
 +int get_cache_file_writable(methodinfo *m)
 +{
 +      char *dest_file, *dest_dir;
 +      int fd;
 +
 +      if (m->clazz->cache_file_fd)
 +              return m->clazz->cache_file_fd;
 +
 +      /* try to get the file first */
 +      dest_file = get_dest_file(m);
 +      fd = open_to_write(dest_file);
 +
 +      /* file does not exist. We need to create it and possibly
 +       * the directory hierarchy as well.
 +       */
 +      if (fd <= 0) {
 +              dest_dir = get_dest_dir(m);
 +
 +              if (os::access(dest_dir, F_OK) != 0)
 +              {
 +                      if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
 +                      {
++                              perror("get_cache_file_writable: ");
++
 +                              if (opt_DebugJitCache)
 +                                      log_println("[jitcache] unable to create cache directory: %s", dest_dir);
 +
 +                              os::free(dest_dir);
 +                              os::free(dest_file);
 +
 +                              return 0;
 +                      }
 +              }
 +
 +              os::free(dest_dir);
 +
 +              /* try to open the file again. */
 +              fd = open_to_write(dest_file);
 +              os::free(dest_file);
 +
 +              if (fd <= 0)
++              {
++                      perror("get_cache_file_writable2: ");
 +                      return 0;
++              }
 +      }
 +
 +      os::free(dest_file);
 +
 +      jitcache_mru_add(m->clazz, fd);
 +
 +      return fd;
 +}
 +
 +/* mkdir_hier ******************************************************************
 +
 +   Creates a directory hierarchy on the filesystem.
 +
 +*******************************************************************************/
 +int mkdir_hier(char *path, mode_t mode)
 +{
 +      int index;
 +      int length = os::strlen(path);
 +
 +      for (index = 0; index < length; index++)
 +      {
 +              if (path[index] == '/')
 +              {
 +                      path[index] = 0;
 +                      mkdir(path, mode);
 +
 +                      path[index] = '/';
 +              }
 +      }
 +
-       patchref_t *pr;
++      if (!mkdir(path, mode) || errno == EEXIST)
++              return 0;
 +}
 +
 +/* get_dest_file ****************************************************************
 +
 +   Returns a string denoting the file in which the method's machine code
 +   (along with the other data) is stored.
 +
 +*******************************************************************************/
 +
 +char *get_dest_file(methodinfo *m)
 +{
 +      int len_cacheroot = os::strlen(CACHEROOT);
 +      int len_classname = utf_bytes(m->clazz->name);
 +
 +      char *dest_file = (char *) os::calloc(sizeof(u1),
 +                                                                 len_cacheroot
 +                                     + len_classname
 +                                     + 2);
 +
 +      strcat(dest_file, CACHEROOT);
 +      utf_cat(dest_file, m->clazz->name);
 +
 +      return dest_file;
 +}
 +
 +/* get_dest_dir ****************************************************************
 +
 +   Returns a string denoting the directory in which the method's machine code
 +   (along with the other data) is stored.
 +
 +*******************************************************************************/
 +
 +char *get_dest_dir(methodinfo *m)
 +{
 +      int len_cacheroot = os::strlen(CACHEROOT);
 +      int len_packagename = utf_bytes(m->clazz->packagename);
 +
 +      char *dest_dir = (char *) os::calloc(sizeof(u1),
 +                                                                 len_cacheroot
 +                                     + len_packagename + 2);
 +
 +      strcat(dest_dir, CACHEROOT);
 +      utf_cat(dest_dir, m->clazz->packagename);
 +
 +      /* Make trailing slash from package name to 0 */
 +      dest_dir[len_cacheroot + len_packagename + 2 - 1] = 0;
 +
 +      return dest_dir;
 +}
 +
 +/* to_abs **********************************************************************
 +
 +   Generates an absolute pointer from an offset. You need this after loading
 +   a value from the disk which is absolute at runtime.
 +
 +*******************************************************************************/
 +
 +void *to_abs(void *base, void *offset)
 +{
 +      return (void *) ((ptrint) base + (ptrint) offset);
 +}
 +
 +/* to_offset *******************************************************************
 +
 +   Generates an offset from an absolute pointer. This has to be done to each
 +   absolute pointer before storing it to disk.
 +
 +*******************************************************************************/
 +
 +void *to_offset(void *base, void *abs)
 +{
 +      return (void *) ((ptrint) abs - (ptrint) base);
 +}
 +
 +/* open_to_read ****************************************************************
 +
 +   Open a file for reading.
 +
 +*******************************************************************************/
 +
 +int open_to_read(char *dest_file)
 +{
 +      int fd;
 +/*
 +      fd = system_open(dest_file, O_RDONLY, 0);
 +*/
 +      fd = system_open(dest_file,
 +                                       O_RDWR,
 +                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 +
 +      return fd;
 +}
 +
 +/* open_to_write ***************************************************************
 +
 +   Open a file for writing.
 +
 +*******************************************************************************/
 +
 +int open_to_write(char *dest_file)
 +{
 +      int fd;
 +
 +/*    fd = system_open(filename,
 +                                       O_CREAT | O_WRONLY,
 +                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 +*/
 +      fd = system_open(dest_file,
 +                                       O_CREAT | O_RDWR,
 +                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 +
 +      return fd;
 +}
 +
 +/* store_utf *******************************************************************
 +
 +   Writes a utf object to disk (via filedescriptor).
 +
 +*******************************************************************************/
 +void store_utf(int fd, utf *s)
 +{
 +      int len;
 +
 +      if (!s)
 +      {
 +              len = -1;
 +              system_write(fd, (const void *) &len, sizeof(len));
 +      }
 +      else
 +      {
 +              len = utf_bytes(s);
 +              system_write(fd, (const void *) &len, sizeof(len));
 +              system_write(fd, s->text, len);
 +      }
 +}
 +
 +/* load_utf ********************************************************************
 +
 +   Loads a UTF8 constant from the given filedescriptor and initializes
 +   the given pointer with it.
 +   In case the stored constant's length is -1 the returned string is NULL.
 +
 +*******************************************************************************/
 +void load_utf(utf **s, int fd)
 +{
 +      int len = 0;
 +      char *tmp;
 +
 +      system_read(fd, (void *) &len, sizeof(len));
 +
 +      if (len == -1)
 +              *s = NULL;
 +      else
 +      {
 +              tmp = (char *) os::calloc(sizeof(char), len);
 +
 +              system_read(fd, tmp, len);
 +
 +              *s = utf_new(tmp, len);
 +
 +/*            os::free(tmp);*/
 +      }
 +}
 +
 +
 +/* store_to_file_patchers ******************************************************
 +
 +   Writes the patchers structure of a codeinfo to disk.
 +
 +*******************************************************************************/
 +void store_to_file_patchers(int fd, codeinfo *code)
 +{
 +      int temp = 0;
 +      void *temp_ptr;
-       list_t *patchers = code->patchers;
 +      int j;
 +
-       system_write(fd, (const void *) &patchers->size, sizeof(patchers->size));
++      int size = code->patchers->size();
 +
 +      /* serialize patchers list */
-               log_println("store_to_file_patchers - patchers size %d", patchers->size);
++      system_write(fd, (const void *) &size, sizeof(size));
 +      if (opt_DebugJitCache)
-       for (pr = (patchref_t *) list_first(patchers); pr != NULL; pr = (patchref_t *) list_next(patchers, pr))
++              log_println("store_to_file_patchers - patchers size %d", size);
 +
-               temp_ptr = to_offset(code->mcode, (u1 *) pr->mpc);
++      for (List<patchref_t>::iterator it = code->patchers->begin();
++                      it != code->patchers->end(); it++)
 +      {
-               temp_ptr = to_offset(code->mcode, (u1 *) pr->datap);
++              temp_ptr = to_offset(code->mcode, (u1 *) it->mpc);
 +              system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 +
-               system_write(fd, (const void *) &pr->disp, sizeof(pr->disp));
++              temp_ptr = to_offset(code->mcode, (u1 *) it->datap);
 +              system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 +
-                       if (patcher_functions[j].patcher == pr->patcher)
++              system_write(fd, (const void *) &it->disp, sizeof(it->disp));
 +
 +              temp = -1;
 +              j = 0;
 +              while (patcher_functions[j].patcher)
 +              {
-                               (*patcher_functions[j].serializer)(fd, pr, code->m);
++                      if (patcher_functions[j].patcher == it->patcher)
 +                      {
 +                              temp = j;
 +                              system_write(fd, (const void *) &j, sizeof(j));
 +
-               system_write(fd, (const void *) &pr->attached_ref, sizeof(pr->attached_ref));
++                              (*patcher_functions[j].serializer)(fd, &(*it), code->m);
 +
 +                              if (patcher_functions[j].serializer == s_dummy)
 +                                      log_println("store_to_file_patchers: unhandled patcher function for %d", j);
 +                              break;
 +                      }
 +                      j++;
 +              }
 +              
 +              if (temp == -1)
 +              {
 +                      log_println("warning! unknown patcher function stored!");
 +                      system_write(fd, (const void *) &temp, sizeof(temp));
 +              }
 +
-               if (pr->attached_ref)
++              if (it->attached_ref)
++                      temp = 1;
++              
++              system_write(fd, (const void *) &temp, sizeof(temp));
 +
-                       store_cachedref(fd, pr->attached_ref);
++              if (it->attached_ref)
 +              {
-                       FREE(pr->attached_ref, cachedref_t);
-                       pr->attached_ref = NULL;
++                      store_cachedref(fd, it->attached_ref);
 +
 +                      /* Release the cached reference now because it should not be used
 +                       * in the current Cacao process.
 +                       */
-               system_write(fd, (const void *) &pr->mcode, sizeof(pr->mcode));
++                      FREE(it->attached_ref, cachedref_t);
++                      it->attached_ref = NULL;
 +              }
 +
-       cachedref_t *cr;
-       list_t *cachedrefs = code->cachedrefs;
++              system_write(fd, (const void *) &it->mcode, sizeof(it->mcode));
 +      }
 +}
 +
 +
 +/* store_to_file_cachedrefs *****************************************************
 +
 +   Writes the cachedrefs structure of a codeinfo to disk.
 +
 +*******************************************************************************/
 +void store_to_file_cachedrefs(int fd, codeinfo *code)
 +{
-               log_println("store_to_file_cachedrefs - cachedrefs size %d", cachedrefs->size);
++      int size = code->cachedrefs->size();
 +      if (opt_DebugJitCache)
-       system_write(fd, (const void *) &cachedrefs->size, sizeof(cachedrefs->size));
++              log_println("store_to_file_cachedrefs - cachedrefs size %d", size);
 +
 +      /* serialize cachedrefs list */
-       for (cr = (cachedref_t *) list_first(cachedrefs);
-                cr != NULL;
-                cr = (cachedref_t *) list_next(cachedrefs, cr))
-               store_cachedref(fd, cr);
++      system_write(fd, (const void *) &size, sizeof(size));
 +
-       linenumbertable_entry_t *lte;
++      for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
++                      it != code->cachedrefs->end(); it++)
++              store_cachedref(fd, &(*it));
 +}
 +
 +/* store_cachedref *************************************************************
 +
 +   Stores a single cachedref_t instance to disk.
 +
 +*******************************************************************************/
 +
 +void store_cachedref(int fd, cachedref_t *cr)
 +{
 +      system_write(fd, (const void *) &cr->type, sizeof(cr->type));
 +      system_write(fd, (const void *) &cr->md_patch, sizeof(cr->md_patch));
 +      system_write(fd, (const void *) &cr->disp, sizeof(cr->disp));
 +
 +      switch (cr->type) {
 +              case CRT_CODEINFO:
 +              case CRT_ENTRYPOINT:
 +              case CRT_CODEGEN_FINISH_NATIVE_CALL:
 +              case CRT_ASM_HANDLE_EXCEPTION:
 +              case CRT_ASM_HANDLE_NAT_EXCEPTION:
 +                      /* Nothing to store. */
 +                      break;
 +              case CRT_NUM:
 +                      system_write(fd, (const void *) &cr->ref, sizeof(s4));
 +                      break;
 +              case CRT_OBJECT_HEADER:
 +              case CRT_CLASSINFO:
 +              case CRT_CLASSINFO_INDEX:
 +              case CRT_CLASSINFO_INTERFACETABLE:
 +              case CRT_CLASSINFO_VFTBL:
 +                      /* Store classinfo */
 +                      store_classinfo(fd, (classinfo *) cr->ref);
 +                      break;
 +              case CRT_BUILTIN:
 +              case CRT_BUILTIN_FP:
 +                      store_builtin(fd, (builtintable_entry *) cr->ref);
 +                      break;
 +              case CRT_STRING:
 +                      store_string(fd, (java_object_t *) cr->ref);
 +                      break;
 +              case CRT_METHODINFO_STUBROUTINE:
 +              case CRT_METHODINFO_TABLE:
 +              case CRT_METHODINFO_INTERFACETABLE:
 +              case CRT_METHODINFO_METHODOFFSET:
 +                      store_methodinfo(fd, (methodinfo *) cr->ref);
 +                      break;
 +              case CRT_FIELDINFO_VALUE:
 +              case CRT_FIELDINFO_OFFSET:
 +              case CRT_FIELDINFO_OFFSET_HIGH:
 +                      store_fieldinfo(fd, (fieldinfo *) cr->ref);
 +                      break;
 +              case CRT_JUMPREFERENCE:
 +                      system_write(fd, (const void *) &cr->ref, sizeof(cr->ref));
 +                      
 +                      break;
 +              default:
 +                      log_println("store_cachedref: Invalid cachedref type: %d", cr->type);
 +                      assert(0);
 +      }
 +}
 +
 +
 +/* store_to_file_exceptiontable ************************************************
 +
 +   Writes the exceptiontable structure of a codeinfo to disk.
 +
 +*******************************************************************************/
 +void store_to_file_exceptiontable(int fd, codeinfo *code)
 +{
 +      int count = 0;
 +      void *temp_ptr;
 +      int i;
 +      utf *name;
 +
 +      /* serialize exceptiontable */
 +
 +      /* temp will contain the amount of exceptiontable entries or zero
 +       * if none exists.
 +     */
 +      if (code->exceptiontable)
 +              count = code->exceptiontable->length;
 +
 +      system_write(fd, (const void *) &count, sizeof(count));
 +      if (opt_DebugJitCache)
 +              log_println("store_exceptiontable - exceptiontable size %d", count);
 +
 +      for (i = 0; i < count; i++)
 +      {
 +              exceptiontable_entry_t *entry = &code->exceptiontable->entries[i];
 +
 +              temp_ptr = to_offset(code->mcode, entry->endpc);
 +              system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 +
 +              temp_ptr = to_offset(code->mcode, entry->startpc);
 +              system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 +
 +              temp_ptr = to_offset(code->mcode, entry->handlerpc);
 +              system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
 +
 +              /* store class name of entry->catchtype */
 +              if (entry->catchtype.any)
 +              {
 +                      name = CLASSREF_OR_CLASSINFO_NAME(entry->catchtype);
 +                      store_utf(fd, name);
 +              }
 +              else
 +                      store_utf(fd, NULL);
 +
 +      }
 +
 +}
 +
 +
 +/* store_to_file_linenumbertable ***********************************************
 +
 +   Writes the linenumbertable structure of a codeinfo to disk.
 +
 +*******************************************************************************/
 +void store_to_file_linenumbertable(int fd, codeinfo *code)
 +{
 +      void *temp_ptr;
-       int i;
-       linenumbertable_t *linenumbertable;
-       linenumbertable = code->linenumbertable;
 +      int count = 0;
-               count = code->linenumbertable->length;
 +
 +      if (code->linenumbertable)
-               lte = linenumbertable->entries;
-               for (i = 0; i < count; i++)
++              count = code->linenumbertable->_linenumbers.size();
 +
 +      /* serialize patchers list */
 +      system_write(fd, (const void *) &count, sizeof(count));
 +
 +      if (opt_DebugJitCache)
 +              log_println("store_to_file_linenumbertable - linenumbertable size %d", count);
 +
 +      if (count)
 +      {
-                       system_write(fd, (const void *) &lte->linenumber, sizeof(lte->linenumber));
++              for (std::vector<Linenumber>::iterator it = code->linenumbertable->_linenumbers.begin();
++                      it != code->linenumbertable->_linenumbers.end(); it++)
 +              {
-                       temp_ptr = to_offset(code->entrypoint, lte->pc);
++                      int temp = it->get_linenumber();
++                      system_write(fd, (const void *) &temp, sizeof(temp));
 +      
-                       lte++;
++                      temp_ptr = to_offset(code->entrypoint, it->get_pc());
 +                      system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
-               patchref_t *pr = NEW(patchref_t);
 +              }
 +      }
 +
 +}
 +
 +
 +/* load_from_file_patchers *****************************************************
 +
 +   Loads the patchers structure of codeinfo from a file.
 +
 +*******************************************************************************/
 +void load_from_file_patchers(codeinfo *code, int fd)
 +{
 +      int temp = 0;
 +      u1 *temp_ptr;
 +      int count = 0;
 +      int i;
 +
 +      /* serialize patchers list */
 +      system_read(fd, (void *) &count, sizeof(count));
 +
 +      if (opt_DebugJitCache   /* Insert method into methodtree to find the entrypoint. */
 +)
 +              log_println("load_from_file_patchers - patcher size %d", count);
 +
 +      patcher_list_create(code);
 +
 +      for (i = 0;i < count; i++)
 +      {
-               pr->mpc = (ptrint) to_abs(code->mcode, temp_ptr);
++              patchref_t pr;
 +
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               pr->datap = (ptrint) to_abs(code->mcode, temp_ptr);
++              pr.mpc = (ptrint) to_abs(code->mcode, temp_ptr);
 +
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               system_read(fd, (void *) &pr->disp, sizeof(pr->disp));
++              pr.datap = (ptrint) to_abs(code->mcode, temp_ptr);
 +
-               pr->patcher = patcher_functions[temp].patcher;
++              system_read(fd, (void *) &pr.disp, sizeof(pr.disp));
 +
 +              system_read(fd, (void *) &temp, sizeof(temp));
 +              if (temp == -1)
 +              {
 +                      vm_abort("Invalid patcher function index loaded!");
 +                      temp = 0;
 +              }
-               (*patcher_functions[temp].deserializer)(pr, fd, code->m);
++              pr.patcher = patcher_functions[temp].patcher;
 +
-               system_read(fd, (void *) &pr->attached_ref, sizeof(pr->attached_ref));
++              (*patcher_functions[temp].deserializer)(&pr, fd, code->m);
 +
 +              /* Load the pointer value to decide whether a cached reference must
 +         * be loaded or not. */
-               if (pr->attached_ref)
++              system_read(fd, (void *) &temp, sizeof(temp));
 +
-                       pr->attached_ref = NULL;
-                       load_cachedref(&pr->attached_ref, fd, code);
++              if (temp)
 +              {
-               system_read(fd, (void *) &pr->mcode, sizeof(pr->mcode));
++                      pr.attached_ref = 0;
++                      load_cachedref(&pr.attached_ref, fd, code);
 +              }
 +
-               pr->done = false;
++              system_read(fd, (void *) &pr.mcode, sizeof(pr.mcode));
 +
-               list_add_first(code->patchers, pr);
++              pr.done = false;
 +
-       linenumbertable_entry_t *lte;
++              code->patchers->push_front(pr);
 +      }
 +}
 +
 +/* load_from_file_cachedrefs ***************************************************
 +
 +   Loads the cachedrefs structure of codeinfo from a file.
 +
 +   Note: code->entrypoint *must* be valid at this point!
 +
 +   Binary format:
 +   int - number of cachedref_t instances in the file
 +   cachedref_t - see load_cachedref
 +
 +*******************************************************************************/
 +void load_from_file_cachedrefs(codeinfo *code, int fd)
 +{
 +      cachedref_t *cr;
 +      int count = 0;
 +      int i;
 +
 +      /* serialize cachedrefs list */
 +      system_read(fd, (void *) &count, sizeof(count));
 +
 +      if (opt_DebugJitCache)
 +              log_println("load_from_file_cachedrefs - cachedrefs size %d", count);
 +
 +      jitcache_list_reset(code);
 +
 +      cr = NEW(cachedref_t);
 +
 +      for (i = 0;i < count; i++)
 +      {
 +              load_cachedref(&cr, fd, code);
 +
 +              /* Write the restored reference into the code. */
++#if defined (__ARM__)
 +              if (cr->md_patch)
 +                      patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
 +              else
++#endif
 +              {
 +                *((u1 **) (code->entrypoint + cr->disp)) = (u1 *) cr->ref;
 +              }
 +
 +      }
 +
 +      FREE(cr, cachedref_t);
 +}
 +
 +
 +/* load_cachedref **************************************************************
 +
 +      Loads a cached reference from disk and 
 +
 +      Binary format:
 +     s4 - disp value
 +     cachedreftype - type value
 +     * - cached ref specific (depends on type)
 +
 +*******************************************************************************/
 +
 +void load_cachedref(cachedref_t **result_cr, int fd, codeinfo *code)
 +{
 +      cachedref_t                     *cr;
 +      classinfo                       *ci;
 +      methodinfo                      *mi;
 +      fieldinfo                       *fi;
 +      builtintable_entry  *bte;
 +      java_object_t           *h;
 +
 +      if (*result_cr)
 +              cr = *result_cr;
 +      else
 +              *result_cr = cr = NEW(cachedref_t);
 +
 +      system_read(fd, (void *) &cr->type, sizeof(cr->type));
 +      system_read(fd, (void *) &cr->md_patch, sizeof(cr->md_patch));
 +      system_read(fd, (void *) &cr->disp, sizeof(cr->disp));
 +
 +      switch (cr->type) {
 +              case CRT_CODEINFO:
 +                      /* Just set the current codeinfo. */
 +                      cr->ref = (void*) code;
 +                      break;
 +              case CRT_NUM:
 +                      system_read(fd, (void *) &cr->ref, sizeof(s4));
 +                      break;
 +              case CRT_ENTRYPOINT:
 +                      /* Just set the current entrypoint. */
 +                      cr->ref = (void*) code->entrypoint;
 +                      break;
 +              case CRT_CODEGEN_FINISH_NATIVE_CALL:
 +                      /* Just set the pointer to codegen_finish_native_call. */
 +                      cr->ref = (void*) (ptrint) codegen_finish_native_call;
 +                      break;
 +              case CRT_ASM_HANDLE_EXCEPTION:
 +                      /* Just set the pointer to asm_handle_exception. */
 +                      cr->ref = (void*) (ptrint) asm_handle_exception;
 +                      break;
 +              case CRT_ASM_HANDLE_NAT_EXCEPTION:
 +                      /* Just put the pointer to asm_handle_nat_exception. */
 +                      cr->ref = (void*) (ptrint) asm_handle_nat_exception;
 +                      break;
 +              case CRT_OBJECT_HEADER:
 +                      /* Load classinfo */
 +                      load_classinfo(&ci, fd, code->m);
 +                      cr->ref = &ci->object.header;
 +                      break;
 +              case CRT_BUILTIN:
 +                      load_builtin(&bte, fd);
 +                      /* TODO: For the time being prefer the stub if it exists, otherwise
 +                       * use the function pointer directlty.
 +                       * This should go away with a moving garbage collector.
 +             */
 +                      cr->ref = (void*) (bte->stub == NULL ? (ptrint) bte->fp : (ptrint) bte->stub);
 +
 +                      break;
 +              case CRT_BUILTIN_FP:
 +                      load_builtin(&bte, fd);
 +                      cr->ref = (void*) (ptrint) bte->fp;
 +
 +                      break;
 +              case CRT_STRING:
 +                      load_string(&h, fd);
 +                      cr->ref = (void*) h;
 +                      break;
 +              case CRT_CLASSINFO:
 +                      /* Load classinfo */
 +                      load_classinfo(&ci, fd, code->m);
 +                      cr->ref = (void*) ci;
 +
 +                      break;
 +              case CRT_CLASSINFO_INDEX:
 +                      /* Load classinfo */
 +                      load_classinfo(&ci, fd, code->m);
 +                      cr->ref = (void*) ci->index;
 +                      break;
 +              case CRT_CLASSINFO_INTERFACETABLE:
 +                      /* Load classinfo */
 +                      load_classinfo(&ci, fd, code->m);
 +                      cr->ref = (void*) (OFFSET(vftbl_t, interfacetable[0]) -
 +                                              ci->index * sizeof(methodptr*));
 +                      break;
 +              case CRT_CLASSINFO_VFTBL:
 +                      /* Load classinfo */
 +                      load_classinfo(&ci, fd, code->m);
 +                      cr->ref = (void*) ci->vftbl;
 +                      break;
 +              case CRT_METHODINFO_STUBROUTINE:
 +                      load_methodinfo(&mi, fd, code->m);
 +                      cr->ref = (void*) mi->stubroutine;
 +                      break;
 +              case CRT_METHODINFO_TABLE:
 +                      load_methodinfo(&mi, fd, code->m);
 +                      cr->ref = (void*) ((OFFSET(vftbl_t, table[0]) +
 +                                                         sizeof(methodptr) * mi->vftblindex));
 +                      break;
 +              case CRT_METHODINFO_INTERFACETABLE:
 +                      load_methodinfo(&mi, fd, code->m);
 +                      cr->ref = (void*) (OFFSET(vftbl_t, interfacetable[0]) -
 +                                      sizeof(methodptr) * mi->clazz->index);
 +                      break;
 +              case CRT_METHODINFO_METHODOFFSET:
 +                      load_methodinfo(&mi, fd, code->m);
 +                      cr->ref = (void*) ((sizeof(methodptr) * (mi - mi->clazz->methods)));
 +                      break;
 +              case CRT_FIELDINFO_VALUE:
 +                      load_fieldinfo(&fi, fd, code->m);
 +
 +                      cr->ref = (void*) fi->value;
 +                      break;
 +              case CRT_FIELDINFO_OFFSET:
 +                      load_fieldinfo(&fi, fd, code->m);
 +
 +                      cr->ref = (void*) fi->offset;
 +                      break;
 +              case CRT_FIELDINFO_OFFSET_HIGH:
 +                      /* Should be used on 32 bit archs only. */
 +                      load_fieldinfo(&fi, fd, code->m);
 +
 +                      cr->ref = (void*) (fi->offset + 4);
 +                      break;
 +              case CRT_JUMPREFERENCE:
 +                      system_read(fd, (void *) &cr->ref, sizeof(cr->ref));
 +
 +                      cr->ref = (void*) ((ptrint) cr->ref + (ptrint) code->entrypoint);
 +                      break;
 +              default:
 +                      log_println("Invalid (or unhandled) cachedreference type: %d", cr->type);
 +                      assert(0);
 +                      break;
 +      }
 +
 +
 +      if (opt_DebugJitCache)
 +      {
 +              if (cr->md_patch)
 +                      log_println("[%X, %d]: replace (md) %X with %X", code->entrypoint + cr->disp, cr->type, 0xFFF & (u4) (*(u1 **) (code->entrypoint + cr->disp)), cr->ref);
 +              else
 +              {
 +              log_println("[%X, %d]: replace %X with %X", code->entrypoint + cr->disp, cr->type, *((u1 **) (code->entrypoint + cr->disp)), cr->ref);
 +              if ((cr->type == CRT_BUILTIN || cr->type == CRT_BUILTIN_FP) && (void*) (*((u1 **) (code->entrypoint + cr->disp))) != cr->ref)
 +                      log_println("[!!!] differing builtin function pointer: %s", bte->cname);
 +              }
 +      }
 +
 +
 +}
 +
 +/* load_from_file_exceptiontable ***********************************************
 +
 +   Loads the exceptiontable structure of codeinfo from a file.
 +
 +*******************************************************************************/
 +void load_from_file_exceptiontable(codeinfo *code, int fd)
 +{
 +      int i;
 +      u1 *temp_ptr;
 +      utf *classname;
 +      constant_classref *classref;
 +      exceptiontable_entry_t *ete;
 +
 +      code->exceptiontable = NEW(exceptiontable_t);
 +
 +      system_read(fd, (void *) &code->exceptiontable->length, sizeof(code->exceptiontable->length));
 +
 +      if (opt_DebugJitCache)
 +              log_println("load_exceptiontable - exceptiontable size %d", code->exceptiontable->length);
 +
 +
 +      ete = MNEW(exceptiontable_entry_t, code->exceptiontable->length);
 +      code->exceptiontable->entries = ete;
 +
 +      for (i = 0; i < code->exceptiontable->length; i++)
 +      {
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
 +              ete->endpc = to_abs(code->mcode, temp_ptr);
 +
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
 +              ete->startpc = to_abs(code->mcode, temp_ptr);
 +
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
 +              ete->handlerpc = to_abs(code->mcode, temp_ptr);
 +
 +              /* load class name of entry->catchtype */
 +              load_utf(&classname, fd);
 +
 +              if (classname)
 +              {
 +                      classref = NEW(constant_classref);
 +                      CLASSREF_INIT(*classref, code->m->clazz, classname);
 +
 +                      ete->catchtype = CLASSREF_OR_CLASSINFO(classref);
 +              }
 +              else
 +                      ete->catchtype.any = NULL;
 +
 +              ete++;
 +      }
 +
 +}
 +
 +
 +/* load_from_file_linenumbertable **********************************************
 +
 +   Loads the linenumbertable structure of codeinfo from a file.
 +
 +*******************************************************************************/
 +void load_from_file_linenumbertable(codeinfo *code, int fd)
 +{
-       code->linenumbertable = NEW(linenumbertable_t);
 +      void *temp_ptr;
 +      int i;
 +
-       system_read(fd, (void *) &code->linenumbertable->length, sizeof(code->linenumbertable->length));
++      code->linenumbertable = new LinenumberTable();
 +
-               log_println("load_linenumbertable - linenumbertable size %d", code->linenumbertable->length);
-       lte = MNEW(linenumbertable_entry_t, code->linenumbertable->length);
-       code->linenumbertable->entries = lte;
++      int size;
++      system_read(fd, (void *) &size, sizeof(size));
 +
 +      if (opt_DebugJitCache)
-       for (i = 0;i < code->linenumbertable->length; i++)
++              log_println("load_linenumbertable - linenumbertable size %d", size);
 +
-               system_read(fd, (void *) &lte->linenumber, sizeof(lte->linenumber));
++      for (i = 0;i < size; i++)
 +      {
-               lte->pc = to_abs(code->entrypoint, temp_ptr);
++              int linenumber;
++              system_read(fd, (void *) &linenumber, sizeof(linenumber));
 +
 +              system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
-               lte++;
 +
++              code->linenumbertable->_linenumbers.push_back(
++                      Linenumber(linenumber, to_abs(code->entrypoint, temp_ptr)));
 +      }
 +}
 +
 +
 +/* s_dummy *********************************************************************
 +
 +   Patcher serialization function which does nothing and can therefore be used
 +   as a placeholder for not yet written serializers.
 +
 +*******************************************************************************/
 +void s_dummy(int fd, patchref_t *pr, methodinfo *m)
 +{
 +  /* Intentionally does nothing. */
 +}
 +
 +/* s_unresolved_class **********************************************************
 +
 +   Serializes a unresolved_class reference.
 +
 +   Binary format:
 +   - utf string - classname
 +
 +*******************************************************************************/
 +void s_unresolved_class(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      unresolved_class *uc;
 +
 +      uc = (unresolved_class *) pr->ref;
 +
 +      /* Store the class name ... */
 +      store_utf(fd, uc->classref->name);
 +
 +/*
 +      log_println("s_unresolved_class:");
 +      log_message_utf("class:", uc->classref->name);
 +*/
 +}
 +
 +/* s_unresolved_field **********************************************************
 +
 +      Serializes a unresolved_field reference.
 +
 +      Binary format:
 +      s4  - unresolved_field.flags
 +      int - index into class' cpinfo that denotes the unresolved_field's
 +                constant_FMIref
 +
 +*******************************************************************************/
 +void s_unresolved_field(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      int i;
 +
 +      unresolved_field *ref = (unresolved_field *) pr->ref;
 +
 +/*
 +      log_println("s_unresolved_field:");
 +      log_message_utf("field name: ", ref->fieldref->name);
 +      log_message_utf("field desc: ", ref->fieldref->descriptor);
 +      log_message_utf("field's class: ", FIELDREF_CLASSNAME(ref->fieldref));
 +*/
 +      system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
 +
 +      for (i = 0; i < m->clazz->cpcount; i++)
 +      {
 +              if (m->clazz->cpinfos[i] == (void*) ref->fieldref)
 +              {
 +                      system_write(fd, (const void *) &i, sizeof(i));
 +
 +                      return;
 +              }
 +      }
 +      /* We should be out at this point. */
 +
 +      vm_abort("fieldref not found");
 +}
 +
 +/* s_unresolved_method **********************************************************
 +
 +   Serializes a unresolved_method reference.
 +
 +   Binary format:
 +   undecided
 +
 +*******************************************************************************/
 +void s_unresolved_method(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      int i;
 +
 +      unresolved_method *ref = (unresolved_method *) pr->ref;
 +
 +      system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
 +
 +      for (i = 0; i < m->clazz->cpcount; i++)
 +      {
 +              if (m->clazz->cpinfos[i] == (void*) ref->methodref)
 +              {
 +                      system_write(fd, (const void *) &i, sizeof(i));
 +
 +                      return;
 +              }
 +      }
 +      /* We should be out at this point. */
 +
 +      vm_abort("methodref not found");
 +}
 +
 +/* s_classinfo *****************************************************************
 +
 +   Serializes a classinfo reference.
 +
 +*******************************************************************************/
 +void s_classinfo(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      classinfo *ci;
 +
 +      ci = (classinfo *) pr->ref;
 +
 +      store_classinfo(fd, ci);
 +}
 +
 +/* s_methodinfo ****************************************************************
 +
 +      Serializes a methodinfo reference.
 +
 +*******************************************************************************/
 +void s_methodinfo(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      methodinfo *mi;
 +
 +      mi = (methodinfo *) pr->ref;
 +
 +      store_methodinfo(fd, mi);
 +}
 +
 +/* store_methodinfo ************************************************************
 +
 +      Serializes a methodinfo reference.
 +
 +      Binary format:
 +      utf - method name
 +      utf - method descriptor
 +      utf - class to which method belongs
 +
 +*******************************************************************************/
 +void store_methodinfo(int fd, methodinfo *mi)
 +{
 +      store_utf(fd, mi->name);
 +      store_utf(fd, mi->descriptor);
 +      store_utf(fd, mi->clazz->name);
 +}
 +
 +/* s_fieldinfo ****************************************************************
 +
 +      Serializes a fieldinfo reference.
 +
 +      Binary format:
 +      utf - field name
 +      utf - field descriptor
 +      utf - class to which field belongs
 +
 +*******************************************************************************/
 +void s_fieldinfo(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      fieldinfo *fi;
 +
 +      fi = (fieldinfo *) pr->ref;
 +
 +      store_fieldinfo(fd, fi);
 +}
 +
 +void store_fieldinfo(int fd, fieldinfo *fi)
 +{
 +      store_utf(fd, fi->name);
 +      store_utf(fd, fi->descriptor);
 +      store_utf(fd, fi->clazz->name);
 +}
 +
 +/* s_constant_classref *********************************************************
 +
 +   Serializes a constant_classref reference.
 +
 +   Binary format:
 +   - utf string - constant_classref's classname
 +
 +*******************************************************************************/
 +void s_constant_classref(int fd, patchref_t *pr, methodinfo *m)
 +{
 +      constant_classref *cr = (constant_classref *) pr->ref;
 +
 +      store_utf(fd, cr->name);
 +}
 +
 +
 +/* store_builtin *******************************************************************
 +
 +   Serializes a constant_classref reference.
 +
 +   Binary format:
 +   - s4 - key from builtintable_get_key()
 +
 +*******************************************************************************/
 +void store_builtin(int fd, builtintable_entry *bte)
 +{
 +      s4                                      key;
 +
 +      key = builtintable_get_key(bte);
 +
 +      system_write(fd, (const void *) &key, sizeof(key));
 +}
 +
 +/* store_string ****************************************************************
 +
 +   Serializes a java_object_t reference which denotes a string.
 +
 +   Binary format:
 +   - utf - utf bytes of the string instance
 +
 +*******************************************************************************/
 +void store_string(int fd, java_object_t *h)
 +{
 +      utf                             *string;
 +
 +      string = javastring_toutf((java_handle_t *) h, false);
 +
 +      store_utf(fd, string);
 +}
 +
 +
 +/* d_dummy *********************************************************************
 +
 +   Patcher deserialization function which does nothing and can therefore be used
 +   as a placeholder for not yet written deserializers.
 +
 +*******************************************************************************/
 +void d_dummy(patchref_t *pr, int fd, methodinfo *m)
 +{
 +  /* Intentionally do nothing. */
 +}
 +
 +/*
 + * Loads UTF8 classname and creates an unresolved_class for it
 + * using the class to which the patchref_t belongs as the referer.
 + */
 +void d_unresolved_class(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      utf *classname;
 +      constant_classref *classref;
 +      unresolved_class *uc;
 +
 +      classref = NEW(constant_classref);
 +
 +      load_utf(&classname, fd);
 +
 +      CLASSREF_INIT(*classref, m->clazz, classname);
 +
 +      uc = create_unresolved_class(m, classref, NULL);
 +
 +      pr->ref = (void*) uc;
 +
 +/*    FREE(classref, constant_classref);*/
 +
 +/*    os::free(classname); */
 +}
 +
 +void d_unresolved_field(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      int i;
 +
 +      unresolved_field *ref = NEW(unresolved_field);
 +
 +      system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
 +
 +      system_read(fd, (void *) &i, sizeof(i));
 +      ref->fieldref = (constant_FMIref *) m->clazz->cpinfos[i];
 +
 +      ref->referermethod = m;
 +
 +      UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
 +
 +      pr->ref = (void*) ref;
 +}
 +
 +void d_unresolved_method(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      int i;
 +
 +      unresolved_method *ref = NEW(unresolved_method);
 +
 +      system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
 +
 +      system_read(fd, (void *) &i, sizeof(i));
 +      ref->methodref = (constant_FMIref *) m->clazz->cpinfos[i];
 +
 +      ref->referermethod = m;
 +      ref->paramconstraints = NULL;
 +      UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
 +
 +      pr->ref = (void*) ref;
 +}
 +
 +void d_classinfo(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      classinfo *ci;
 +
 +      load_classinfo(&ci, fd, m);
 +
 +      pr->ref = (void*) ci;
 +}
 +
 +void d_methodinfo(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      methodinfo *lm;
 +
 +      load_methodinfo(&lm, fd, m);
 +
 +      pr->ref = (void*) lm;
 +}
 +
 +void load_methodinfo(methodinfo **lm, int fd, methodinfo *m)
 +{
 +      utf *m_name;
 +      utf *m_desc;
 +      utf *classname;
 +      classinfo *clazz;
 +      constant_classref ref;
 +
 +      load_utf(&m_name, fd);
 +      load_utf(&m_desc, fd);
 +      load_utf(&classname, fd);
 +
 +      CLASSREF_INIT(ref, m->clazz, classname);
 +
 +      clazz = resolve_classref_eager(&ref);
 +
 +      *lm = class_findmethod(clazz, m_name, m_desc);
 +}
 +
 +void d_fieldinfo(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      fieldinfo *fi;
 +
 +      load_fieldinfo(&fi, fd, m);
 +      
 +      pr->ref = (void*) fi;
 +}
 +
 +void load_fieldinfo(fieldinfo **fi, int fd, methodinfo *m)
 +{
 +      utf *f_name;
 +      utf *f_desc;
 +      utf *classname;
 +      classinfo *clazz;
 +      constant_classref ref;
 +
 +      load_utf(&f_name, fd);
 +      load_utf(&f_desc, fd);
 +      load_utf(&classname, fd);
 +
 +      CLASSREF_INIT(ref, m->clazz, classname);
 +
 +      clazz = resolve_classref_eager(&ref);
 +/*
 +      if (!(clazz->state & CLASS_INITIALIZED))
 +              if (!initialize_class(clazz))
 +*/
 +      *fi = class_findfield(clazz, f_name, f_desc);
 +}
 +
 +/*
 + * Loads UTF8 classname and initializes a constant_classref for it
 + * using the class to which the patchref_t belongs as the referer.
 + */
 +void d_constant_classref(patchref_t *pr, int fd, methodinfo *m)
 +{
 +      utf *classname;
 +      constant_classref *cr = NEW(constant_classref);
 +
 +      load_utf(&classname, fd);
 +
 +      CLASSREF_INIT(*cr, m->clazz, classname);
 +
 +      pr->ref = (void*) cr;
 +
 +/*    os::free(classname);*/
 +}
 +
 +void load_builtin(builtintable_entry **bte, int fd)
 +{
 +      s4                                      key;
 +
 +      system_read(fd, (void *) &key, sizeof(key));
 +
 +      *bte = builtintable_get_by_key(key);
 +}
 +
 +void load_string(java_object_t **h, int fd)
 +{
 +      utf *string;
 +
 +      load_utf(&string, fd);
 +
 +/*    *h = javastring_new(string);*/
 +      *h = literalstring_new(string);
 +}
 +
 +/* store_classinfo *************************************************************
 +
 +   Serializes a classinfo reference.
 +
 +   Binary format:
 +   - utf string - classinfo's classname
 +
 +*******************************************************************************/
 +void store_classinfo(int fd, classinfo *ci)
 +{
 +      /* Store the class name ... */
 +      store_utf(fd, ci->name);
 +}
 +
 +/* load_classinfo *************************************************************
 +
 +   Deserializes a classinfo reference.
 +
 +   Binary format: see store_classinfo
 +
 +*******************************************************************************/
 +void load_classinfo(classinfo **ci, int fd, methodinfo *m)
 +{
 +      utf *classname;
 +      constant_classref *classref;
 +
 +      classref = NEW(constant_classref);
 +
 +      load_utf(&classname, fd);
 +
 +      CLASSREF_INIT(*classref, m->clazz, classname);
 +
 +      *ci = resolve_classref_eager(classref);
 +}
 +
 +#endif
 +
 +/*
 + * These are local overrides for various environment variables in Emacs.
 + * Please do not remove this and leave it at the end of the file, where
 + * Emacs will automagically detect them.
 + * ---------------------------------------------------------------------
 + * Local variables:
 + * mode: c++
 + * indent-tabs-mode: t
 + * c-basic-offset: 4
 + * tab-width: 4
 + * End:
 + * vim:noexpandtab:sw=4:ts=4:
 + */
index 8bb1c58c713d34454d32048799ba20c3515500fe,0000000000000000000000000000000000000000..250b046fc710e5b1e5cb09ce15296cf03283fe28
mode 100644,000000..100644
--- /dev/null
@@@ -1,183 -1,0 +1,182 @@@
- #include "vm/jit/patcher-common.h"
 +/* src/vm/jit/jitcache.h - jit compiler output caching
 +
 +   Copyright (C) 2008
 +   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 +
 +   This file is part of CACAO.
 +
 +   This program is free software; you can redistribute it and/or
 +   modify it under the terms of the GNU General Public License as
 +   published by the Free Software Foundation; either version 2, or (at
 +   your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful, but
 +   WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program; if not, write to the Free Software
 +   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 +   02110-1301, USA.
 +
 +*/
 +
 +#ifndef _JITCACHE_H
 +#define _JITCACHE_H
 +
++#include "vm/jit/patcher-common.hpp"
++
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +#if defined(ENABLE_JITCACHE)
 +
 +#include "config.h"
 +
 +#include <stdint.h>
 +
- typedef struct cachedref_t {
 +#include "vm/class.h"
 +#include "vm/method.h"
 +
 +typedef enum cachedreftype {
 +      CRT_CODEINFO,
 +      CRT_NUM,
 +      CRT_ENTRYPOINT,
 +      CRT_CODEGEN_FINISH_NATIVE_CALL,
 +      CRT_ASM_HANDLE_EXCEPTION, /* 4 */
 +      CRT_ASM_HANDLE_NAT_EXCEPTION,
 +      CRT_OBJECT_HEADER,
 +      CRT_BUILTIN, /* 7 */
 +      CRT_BUILTIN_FP,
 +      CRT_STRING,
 +      CRT_CLASSINFO, /* 10 */
 +      CRT_CLASSINFO_INDEX,
 +      CRT_CLASSINFO_INTERFACETABLE,
 +      CRT_CLASSINFO_VFTBL,
 +      CRT_METHODINFO_STUBROUTINE, /* 14 */
 +      CRT_METHODINFO_TABLE,
 +      CRT_METHODINFO_INTERFACETABLE,
 +      CRT_METHODINFO_METHODOFFSET,
 +      CRT_FIELDINFO_VALUE, /* 18 */
 +      CRT_FIELDINFO_OFFSET,
 +      CRT_FIELDINFO_OFFSET_HIGH,
 +      CRT_JUMPREFERENCE /* 21 */
 +} cachedreftype;
 +
 +/* cachedref_t *****************************************************************
 +
 +   A cached reference contains information about a code or data position
 +   which needs patching after restoring the it from disk.
 +
 +*******************************************************************************/
 +
-       listnode_t    linkage;
- } cachedref_t;
++struct cachedref_t {
 +      cachedreftype type;                     /* type of the cached reference */
 +      s4                        md_patch;             /* machine dependent back patching */
 +      s4                disp;         /* displacement of ref in the data segment    */
 +      void*       ref;          /* reference passed                           */
- typedef struct jitcache_patcher_function_list_t {
++};
 +
 +/*
 +typedef struct mru_entry_t {
 +      classinfo *clazz;
 +      mutex_t  lock;
 +}
 +*/
 +
 +/* typedefs *******************************************************************/
 +
 +typedef void (*serializerfptr) (int, patchref_t *, methodinfo *);
 +typedef void (*deserializerfptr) (patchref_t *, int, methodinfo *);
 +
 +/* jitcache_patcher_function_list_t typedef ***********************************/
 +
- } jitcache_patcher_function_list_t;
++struct jitcache_patcher_function_list_t {
 +      functionptr patcher;
 +      serializerfptr serializer;
 +      deserializerfptr deserializer;
++};
 +
 +/* function prototypes ********************************************************/
 +
 +void  jitcache_list_create(codeinfo *code);
 +
 +void  jitcache_list_reset(codeinfo *code);
 +
 +void  jitcache_list_free(codeinfo *code);
 +
 +void  jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, void* ref);
 +
 +void  jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, void* ref);
 +
 +void  jitcache_add_cached_ref(codeinfo *code, cachedreftype type, void* ref, s4 disp);
 +
 +void    jitcache_store(methodinfo *m);
 +
 +u1      jitcache_load(methodinfo *m);
 +
 +void  jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code);
 +
 +void  jitcache_quit();
 +
 +void  jitcache_freeclass(classinfo *);
 +
 +#define JITCACHE_ADD_CACHED_REF_JD(jd, type, ref) \
 +      (jitcache_add_cached_ref_jd(jd, type, (void*) ref))
 +
 +#define JITCACHE_ADD_CACHED_REF_JD_COND(jd, type, ref, COND) \
 +      if (COND) \
 +      (jitcache_add_cached_ref_jd(jd, type, (void*) ref))
 +
 +#define JITCACHE_ADD_CACHED_REF_MD_JD(jd, type, md_patch, ref) \
 +      (jitcache_add_cached_ref_md_jd(jd, type, md_patch, (void*) ref))
 +
 +#define JITCACHE_ADD_CACHED_REF(code, type, ref, disp) \
 +      (jitcache_add_cached_ref(code, type, (void*) ref, disp))
 +
 +#define JITCACHE_ADD_CACHED_REF_COND(code, type, ref, disp, COND) \
 +      if (COND) \
 +              jitcache_add_cached_ref(code, type, (void*) ref, disp)
 +
 +#else
 +
 +#define JITCACHE_ADD_CACHED_REF_JD(jd, type, ref) \
 +      while (0) { }
 +
 +#define JITCACHE_ADD_CACHED_REF_JD_COND(jd, type, ref, COND) \
 +      while (0) { }
 +
 +#define JITCACHE_ADD_CACHED_REF_MD_JD(jd, type, md_patch, ref) \
 +      while (0) { }
 +
 +#define JITCACHE_ADD_CACHED_REF(code, type, ref, disp) \
 +      while (0) { }
 +
 +#define JITCACHE_ADD_CACHED_REF_COND(code, type, ref, disp, COND) \
 +      while (0) { }
 +
 +#endif /* ENABLE_JITCACHE */
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +
 +#endif /* _JITCACHE_HPP */
 +
 +
 +/*
 + * These are local overrides for various environment variables in Emacs.
 + * Please do not remove this and leave it at the end of the file, where
 + * Emacs will automagically detect them.
 + * ---------------------------------------------------------------------
 + * Local variables:
 + * mode: c++
 + * indent-tabs-mode: t
 + * c-basic-offset: 4
 + * tab-width: 4
 + * End:
 + * vim:noexpandtab:sw=4:ts=4:
 + */
index 0000000000000000000000000000000000000000,620cc1a3112b0cb1e3d9661d85c3d52262343d5b..0d6143e171f21f36ab484a76a66004ba2d5d90ce
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,145 +1,147 @@@
 -private:
+ /* src/vm/jit/linenumbertable.hpp - linenumber table
+    Copyright (C) 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #ifndef _LINENUMBERTABLE_HPP
+ #define _LINENUMBERTABLE_HPP
+ #include "config.h"
+ #include <stdint.h>
+ #ifdef __cplusplus
+ #include <functional>
+ #include <vector>
+ #endif
+ #include "toolbox/list.hpp"
+ #include "vm/method.h"
+ #include "vm/jit/jit.hpp"
+ #include "vm/jit/code.hpp"
+ #include "vm/jit/ir/instruction.hpp"
+ #ifdef __cplusplus
+ /**
+  * Represents a Java line number.
+  */
+ class Linenumber {
+ private:
+       // TODO Add constants.
+       /* -1......start of inlined body              */
+       /* -2......end of inlined body                */
+       /* <= -3...special entry with methodinfo *    */
+       /* (see doc/inlining_stacktrace.txt)          */
+       int32_t _linenumber;
+       void*   _pc;
+ public:
+       Linenumber(int32_t linenumber, void* pc) : _linenumber(linenumber), _pc(pc) {}
+       inline int32_t get_linenumber() const { return _linenumber; }
+       inline void*   get_pc        () const { return _pc; }
+       void resolve(const codeinfo* code);
+ };
+ /**
+  * Unary function to resolve Linenumber objects.
+  */
+ class LinenumberResolver : public std::binary_function<Linenumber, codeinfo*, void> {
+ public:
+       // Unary resolve function.
+       void operator() (Linenumber& ln, const codeinfo* code) const
+       {
+               ln.resolve(code);
+       }
+ };
+ /**
+  * Linenumber table of a Java method.
+  */
+ class LinenumberTable {
++public:
+       std::vector<Linenumber> _linenumbers;
++private:
+       // Comparator class.
+       class comparator : public std::binary_function<Linenumber, void*, bool> {
+       public:
+               bool operator() (const Linenumber& ln, const void* pc) const
+               {
+                       return (pc >= ln.get_pc());
+               }
+       };
+ public:
+       LinenumberTable(jitdata* jd);
++      LinenumberTable() { }
+       ~LinenumberTable();
+       int32_t find(methodinfo **pm, void* pc);
+ };
+ #else
+ typedef struct LinenumberTable LinenumberTable;
+ #endif
+ #include "vm/jit/codegen-common.hpp"
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ void    linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber);
+ void    linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr);
+ void    linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr);
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+ #endif // _LINENUMBERTABLE_HPP
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,134ea9057361668756228310d715ba443c731c0d..0a903eca985c3f26b5f18fbce418a6a483e691a5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,521 +1,556 @@@
+ /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
+    Copyright (C) 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    Copyright (C) 2008 Theobroma Systems Ltd.
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <stdint.h>
+ #include <algorithm>
+ #include <functional>
+ #include "codegen.h"                   /* for PATCHER_NOPS */
+ #include "md.h"
+ #include "mm/memory.h"
+ #include "native/native.hpp"
+ #include "toolbox/list.hpp"
+ #include "toolbox/logging.h"           /* XXX remove me! */
+ #include "vm/exceptions.hpp"
+ #include "vm/initialize.h"
+ #include "vm/options.h"
+ #include "vm/resolve.h"
+ #include "vm/vm.hpp"                     /* for vm_abort */
+ #include "vm/jit/code.hpp"
+ #include "vm/jit/disass.h"
+ #include "vm/jit/jit.hpp"
+ #include "vm/jit/patcher-common.hpp"
+ /* patcher_function_list *******************************************************
+    This is a list which maps patcher function pointers to the according
+    names of the patcher functions. It is only usefull for debugging
+    purposes.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ typedef struct patcher_function_list_t {
+       functionptr patcher;
+       const char* name;
+ } patcher_function_list_t;
+ static patcher_function_list_t patcher_function_list[] = {
+       { PATCHER_initialize_class,              "initialize_class" },
+       { PATCHER_resolve_class,                 "resolve_class" },
+       { PATCHER_resolve_native_function,       "resolve_native_function" },
+       { PATCHER_invokestatic_special,          "invokestatic_special" },
+       { PATCHER_invokevirtual,                 "invokevirtual" },
+       { PATCHER_invokeinterface,               "invokeinterface" },
+       { NULL,                                  "-UNKNOWN PATCHER FUNCTION-" }
+ };
+ #endif
+ /* patcher_list_create *********************************************************
+    Creates an empty patcher list for the given codeinfo.
+ *******************************************************************************/
+ void patcher_list_create(codeinfo *code)
+ {
+       code->patchers = new List<patchref_t>();
+ }
+ /* patcher_list_reset **********************************************************
+    Resets the patcher list inside a codeinfo. This is usefull when
+    resetting a codeinfo for recompiling.
+ *******************************************************************************/
+ void patcher_list_reset(codeinfo *code)
+ {
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_patchref -= sizeof(patchref_t) * code->patchers->size();
+ #endif
+       // Free all elements of the list.
+       code->patchers->clear();
+ }
+ /* patcher_list_free ***********************************************************
+    Frees the patcher list and all its entries for the given codeinfo.
+ *******************************************************************************/
+ void patcher_list_free(codeinfo *code)
+ {
+       // Free all elements of the list.
+       patcher_list_reset(code);
+       // Free the list itself.
+       delete code->patchers;
+ }
+ /**
+  * Find an entry inside the patcher list for the given codeinfo by
+  * specifying the program counter of the patcher position.
+  *
+  * NOTE: Caller should hold the patcher list lock or maintain
+  * exclusive access otherwise.
+  *
+  * @param pc Program counter to find.
+  *
+  * @return Pointer to patcher.
+  */
+ struct foo : public std::binary_function<patchref_t, void*, bool> {
+       bool operator() (const patchref_t& pr, const void* pc) const
+       {
+               return (pr.mpc == (uintptr_t) pc);
+       }
+ };
+ static patchref_t* patcher_list_find(codeinfo* code, void* pc)
+ {
+       // Search for a patcher with the given PC.
+       List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
+       if (it == code->patchers->end())
+               return NULL;
+       return &(*it);
+ }
+ /* patcher_add_patch_ref *******************************************************
+    Appends a new patcher reference to the list of patching positions.
+ *******************************************************************************/
+ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
+ {
+       codegendata *cd;
+       codeinfo    *code;
+       s4           patchmpc;
+       cd       = jd->cd;
+       code     = jd->code;
+       patchmpc = cd->mcodeptr - cd->mcodebase;
+ #if !defined(NDEBUG)
+       if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
+               vm_abort("patcher_add_patch_ref: different patchers at same position.");
+ #endif
+       // Set patcher information (mpc is resolved later).
+       patchref_t pr;
+       pr.mpc     = patchmpc;
+       pr.datap   = 0;
+       pr.disp    = disp;
+       pr.patcher = patcher;
+       pr.ref     = ref;
+       pr.mcode   = 0;
+       pr.done    = false;
++#if defined(ENABLE_JITCACHE)
++      pr.attached_ref = NULL;
++#endif
++
+       // Store patcher in the list (NOTE: structure is copied).
+       code->patchers->push_back(pr);
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_patchref += sizeof(patchref_t);
+ #endif
+ #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
+       /* XXX We can remove that when we don't use UD2 anymore on i386
+          and x86_64. */
+       /* On some architectures the patcher stub call instruction might
+          be longer than the actual instruction generated.  On this
+          architectures we store the last patcher call position and after
+          the basic block code generation is completed, we check the
+          range and maybe generate some nop's. */
+       /* The nops are generated in codegen_emit in each codegen */
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+ #endif
+ }
+ /**
+  * Resolve all patchers in the current JIT run.
+  *
+  * @param jd JIT data-structure
+  */
+ void patcher_resolve(jitdata* jd)
+ {
+       // Get required compiler data.
+       codeinfo* code = jd->code;
+       for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+               patchref_t& pr = *it;
+               pr.mpc   += (intptr_t) code->entrypoint;
+               pr.datap  = (intptr_t) (pr.disp + code->entrypoint);
+       }
+ }
+ /**
+  * Check if the patcher is already patched.  This is done by comparing
+  * the machine instruction.
+  *
+  * @param pr Patcher structure.
+  *
+  * @return true if patched, false otherwise.
+  */
+ bool patcher_is_patched(patchref_t* pr)
+ {
+       // Validate the instruction at the patching position is the same
+       // instruction as the patcher structure contains.
+       uint32_t mcode = *((uint32_t*) pr->mpc);
+       if (mcode != pr->mcode) {
+               // The code differs.
+               return false;
+       }
+       return true;
+ }
+ /**
+  *
+  */
+ bool patcher_is_patched_at(void* pc)
+ {
+       codeinfo* code = code_find_codeinfo_for_pc(pc);
+       // Get the patcher for the given PC.
+       patchref_t* pr = patcher_list_find(code, pc);
+       if (pr == NULL) {
+               // The given PC is not a patcher position.
+               return false;
+       }
+       // Validate the instruction.
+       return patcher_is_patched(pr);
+ }
+ /* patcher_handler *************************************************************
+    Handles the request to patch JIT code at the given patching
+    position. This function is normally called by the signal
+    handler.
+    NOTE: The patcher list lock is used to maintain exclusive
+    access of the patched position (in fact of the whole code).
+    After patching has suceeded, the patcher reference should be
+    removed from the patcher list to avoid double patching.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ /* XXX this indent is not thread safe! */
+ /* XXX if you want it thread safe, place patcher_depth in threadobject! */
+ static int patcher_depth = 0;
+ #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
+ #endif /* !defined(NDEBUG) */
+ java_handle_t *patcher_handler(u1 *pc)
+ {
+       codeinfo      *code;
+       patchref_t    *pr;
+       bool           result;
+       java_handle_t *e;
+ #if !defined(NDEBUG)
+       patcher_function_list_t *l;
+       int                      i;
+ #endif
+       /* define the patcher function */
+       bool (*patcher_function)(patchref_t *);
+       /* search the codeinfo for the given PC */
+       code = code_find_codeinfo_for_pc(pc);
+       assert(code);
+       // Enter a mutex on the patcher list.
+       code->patchers->lock();
+       /* search the patcher information for the given PC */
+       pr = patcher_list_find(code, pc);
+       if (pr == NULL)
+               vm_abort("patcher_handler: Unable to find patcher reference.");
+       if (pr->done) {
+ #if !defined(NDEBUG)
+               if (opt_DebugPatcher) {
+                       log_println("patcher_handler: double-patching detected!");
+               }
+ #endif
+               code->patchers->unlock();
+               return NULL;
+       }
+ #if !defined(NDEBUG)
+       if (opt_DebugPatcher) {
+               for (l = patcher_function_list; l->patcher != NULL; l++)
+                       if (l->patcher == pr->patcher)
+                               break;
+               TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
+               TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
+               TRACE_PATCHER_INDENT;
+               printf("\tmachine code before = ");
+ # if defined(ENABLE_DISASSEMBLER)
+               disassinstr((u1*) (void*) pr->mpc);
+ # else
+               printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+ # endif
+               patcher_depth++;
+               assert(patcher_depth > 0);
+       }
+ #endif
+       /* cast the passed function to a patcher function */
+       patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
+       /* call the proper patcher function */
+       result = (patcher_function)(pr);
+ #if !defined(NDEBUG)
+       if (opt_DebugPatcher) {
+               assert(patcher_depth > 0);
+               patcher_depth--;
+               TRACE_PATCHER_INDENT;
+               printf("\tmachine code after  = ");
+ # if defined(ENABLE_DISASSEMBLER)
+               disassinstr((u1*) (void*) pr->mpc);
+ # else
+               printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+ # endif
+               if (result == false) {
+                       TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
+               }
+       }
+ #endif
++#if defined(ENABLE_JITCACHE)
++      /* Put cached reference into the code and remove it from the patcher */
++      if (pr->attached_ref)
++      {
++              jitcache_handle_cached_ref(pr->attached_ref, code);
++              pr->attached_ref = NULL;
++      }
++#endif
++
+       /* check for return value and exit accordingly */
+       if (result == false) {
+               e = exceptions_get_and_clear_exception();
+               code->patchers->unlock();
+               return e;
+       }
+       pr->done = true; /* XXX this is only preliminary to prevent double-patching */
+       code->patchers->unlock();
+       return NULL;
+ }
+ /* patcher_initialize_class ****************************************************
+    Initalizes a given classinfo pointer.
+    This function does not patch any data.
+ *******************************************************************************/
+ bool patcher_initialize_class(patchref_t *pr)
+ {
+       classinfo *c;
+       /* get stuff from the patcher reference */
+       c = (classinfo *) pr->ref;
+       /* check if the class is initialized */
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+       /* patch back original code */
+       patcher_patch_code(pr);
+       return true;
+ }
+ /* patcher_resolve_class *******************************************************
+    Resolves a given unresolved class reference.
+    This function does not patch any data.
+ *******************************************************************************/
+ #ifdef ENABLE_VERIFIER
+ bool patcher_resolve_class(patchref_t *pr)
+ {
+       unresolved_class *uc;
+       /* get stuff from the patcher reference */
+       uc = (unresolved_class *) pr->ref;
+       /* resolve the class and check subtype constraints */
+       if (!resolve_class_eager_no_access_check(uc))
+               return false;
+       /* patch back original code */
+       patcher_patch_code(pr);
+       return true;
+ }
+ #endif /* ENABLE_VERIFIER */
+ /* patcher_resolve_native_function *********************************************
+    Resolves the native function for a given methodinfo.
+    This function patches one data segment word.
+ *******************************************************************************/
+ bool patcher_resolve_native_function(patchref_t *pr)
+ {
+       methodinfo  *m;
+       uint8_t     *datap;
+       /* get stuff from the patcher reference */
+       m     = (methodinfo *) pr->ref;
+       datap = (uint8_t *)    pr->datap;
+       /* resolve native function */
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       void* f = nm.resolve_method(m);
+       if (f == NULL)
+               return false;
+       /* patch native function pointer */
+       *((intptr_t*) datap) = (intptr_t) f;
+       /* synchronize data cache */
+       md_dcacheflush(datap, SIZEOF_VOID_P);
+       /* patch back original code */
+       patcher_patch_code(pr);
+       return true;
+ }
++/** Placeholder functions to calm down linker */
++#if defined(__I386__)
++bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
++{
++      return true;
++}
++
++bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
++{
++      return true;
++}
++
++bool patcher_resolve_classref_to_index(patchref_t *pr)
++{
++      return true;
++}
++
++bool patcher_resolve_classref_to_flags(patchref_t *pr)
++{
++      return true;
++}
++#endif
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,72ed1ec0bf5a9948d0af08ef9de861bd9f633492..7a10d4d22cf278dadb0fb84425ab15672169308f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,211 +1,224 @@@
+ /* src/vm/jit/patcher-common.hpp - architecture independent code patching stuff
+    Copyright (C) 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #ifndef _PATCHER_COMMON_HPP
+ #define _PATCHER_COMMON_HPP
+ /* forward typedefs ***********************************************************/
++typedef struct cachedref_t cachedref_t;
+ typedef struct patchref_t patchref_t;
+ #include "config.h"
+ #include "vm/types.h"
+ #include "toolbox/list.hpp"
+ #include "vm/global.h"
+ #include "vm/jit/jit.hpp"
++#if defined (ENABLE_JITCACHE)
++struct cached_ref_t;
++#endif
+ /* patchref_t ******************************************************************
+    A patcher reference contains information about a code position
+    which needs additional code patching during runtime.
+ *******************************************************************************/
+ struct patchref_t {
+       ptrint       mpc;           /* absolute position in code segment          */
+       ptrint       datap;         /* absolute position in data segment          */
+       s4           disp;          /* displacement of ref in the data segment    */
+       functionptr  patcher;       /* patcher function to call                   */
+       void*        ref;           /* reference passed                           */
+       uint32_t     mcode;         /* machine code to be patched back in         */
+       bool         done;          /* XXX preliminary: patch already applied?    */
++#if defined (ENABLE_JITCACHE)
++      cachedref_t  *attached_ref;
++                                                              /* cached reference which must be resolved    *
++                                                               * patcher has been run.                      */
++#endif
+ };
+ /* macros *********************************************************************/
+ /* function prototypes ********************************************************/
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ void patcher_list_create(codeinfo *code);
+ void patcher_list_reset(codeinfo *code);
+ void patcher_list_free(codeinfo *code);
+ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
+ void patcher_resolve(jitdata* jd);
+ bool patcher_is_patched(patchref_t* pr);
+ bool patcher_is_patched_at(void* pc);
+ // MD function.
+ bool patcher_is_valid_trap_instruction_at(void* pc);
+ java_handle_t *patcher_handler(u1 *pc);
+ /* empty patcher (just patches back original mcode) ***************************/
+ void patcher_patch_code(patchref_t *pr);
+ /* patcher prototypes and macros **********************************************/
+ /* new patcher functions */
+ bool patcher_resolve_class(patchref_t *pr);
+ #define PATCHER_resolve_class (functionptr) patcher_resolve_class
+ bool patcher_initialize_class(patchref_t *pr);
+ #define PATCHER_initialize_class (functionptr) patcher_initialize_class
+ bool patcher_resolve_classref_to_classinfo(patchref_t *pr);
+ #define PATCHER_resolve_classref_to_classinfo (functionptr) patcher_resolve_classref_to_classinfo
+ bool patcher_resolve_classref_to_vftbl(patchref_t *pr);
+ #define PATCHER_resolve_classref_to_vftbl (functionptr) patcher_resolve_classref_to_vftbl
+ bool patcher_resolve_classref_to_index(patchref_t *pr);
+ #define PATCHER_resolve_classref_to_index (functionptr) patcher_resolve_classref_to_index
+ bool patcher_resolve_classref_to_flags(patchref_t *pr);
+ #define PATCHER_resolve_classref_to_flags (functionptr) patcher_resolve_classref_to_flags
+ bool patcher_resolve_native_function(patchref_t *pr);
+ #define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
+ /* old patcher functions */
+ bool patcher_get_putstatic(patchref_t *pr);
+ #define PATCHER_get_putstatic (functionptr) patcher_get_putstatic
+ #if defined(__I386__)
+ bool patcher_getfield(patchref_t *pr);
+ #define PATCHER_getfield (functionptr) patcher_getfield
+ bool patcher_putfield(patchref_t *pr);
+ #define PATCHER_putfield (functionptr) patcher_putfield
+ #else
+ bool patcher_get_putfield(patchref_t *pr);
+ #define PATCHER_get_putfield (functionptr) patcher_get_putfield
+ #endif /* defined(__I386__) */
+ #if defined(__I386__) || defined(__X86_64__)
+ bool patcher_putfieldconst(patchref_t *pr);
+ #define PATCHER_putfieldconst (functionptr) patcher_putfieldconst
+ #endif /* defined(__I386__) || defined(__X86_64__) */
+ bool patcher_invokestatic_special(patchref_t *pr);
+ #define PATCHER_invokestatic_special (functionptr) patcher_invokestatic_special
+ bool patcher_invokevirtual(patchref_t *pr);
+ #define PATCHER_invokevirtual (functionptr) patcher_invokevirtual
+ bool patcher_invokeinterface(patchref_t *pr);
+ #define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
+ #if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+ bool patcher_checkcast_interface(patchref_t *pr);
+ #define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
+ bool patcher_instanceof_interface(patchref_t *pr);
+ #define PATCHER_instanceof_interface (functionptr) patcher_instanceof_interface
+ #endif /* defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) */
+ #if defined(__S390__)
+ bool patcher_checkcast_instanceof_interface(patchref_t *pr);
+ #define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
+ #endif /* defined(__S390__) */
+ #if defined(__I386__)
+ bool patcher_aconst(patchref_t *pr);
+ #define PATCHER_aconst (functionptr) patcher_aconst
+ bool patcher_builtin_multianewarray(patchref_t *pr);
+ #define PATCHER_builtin_multianewarray (functionptr) patcher_builtin_multianewarray
+ bool patcher_builtin_arraycheckcast(patchref_t *pr);
+ #define PATCHER_builtin_arraycheckcast (functionptr) patcher_builtin_arraycheckcast
+ bool patcher_checkcast_instanceof_flags(patchref_t *pr);
+ #define PATCHER_checkcast_instanceof_flags (functionptr) patcher_checkcast_instanceof_flags
+ bool patcher_checkcast_class(patchref_t *pr);
+ #define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
+ bool patcher_instanceof_class(patchref_t *pr);
+ #define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
+ #endif /* defined(__I386__) */
++#if defined (__ARM__)
++void patch_md(s4 md_patch, ptrint dest, void* ref);
++#endif /* defined(__ARM__) */
++
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+ #endif // _PATCHER_COMMON_HPP
+ /*
+  * These are local overrides for various environment variables in Emacs.
+  * Please do not remove this and leave it at the end of the file, where
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c++
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
Simple merge
Simple merge
diff --cc src/vm/os.hpp
Simple merge
Simple merge
Simple merge
index 37d19460707d5b98c0cc460a00d44d014a394c92,878e8b822de83089a51416a584ed2d265e36a3a7..46aa681f7e8bec6aee5d0e9853273aaa239cc87f
  
  #include "toolbox/logging.h"
  
++#include "threads/thread.hpp"
++
  #include "vm/class.h"
- #include "vm/field.h"
+ #include "vm/field.hpp"
  #include "vm/global.h"
  #include "vm/method.h"
  #include "vm/options.h"
@@@ -304,12 -302,12 +306,25 @@@ s8 getcputime(void
  
  *******************************************************************************/
  
++Mutex *loadingtime_lock = Mutex_new();
++
  void loadingtime_start(void)
  {
++      Mutex_lock(loadingtime_lock);
++
        loadingtime_recursion++;
  
        if (loadingtime_recursion == 1)
                loadingstarttime = getcputime();
++      else {
++              int end = getcputime();
++              loadingtime += (end - loadingstarttime);
++
++              loadingstarttime = loadingstoptime = end;
++      }
++      
++
++      Mutex_unlock(loadingtime_lock);
  }
  
  
  
  void loadingtime_stop(void)
  {
--      if (loadingtime_recursion == 1) {
--              loadingstoptime = getcputime();
--              loadingtime += (loadingstoptime - loadingstarttime);
++      Mutex_lock(loadingtime_lock);
++
++      loadingstoptime = getcputime();
++      loadingtime += (loadingstoptime - loadingstarttime);
++
++      if (loadingtime_recursion > 1) {
++              loadingstarttime = loadingstoptime;
        }
  
        loadingtime_recursion--;
++
++      Mutex_unlock(loadingtime_lock);
  }
  
  
Simple merge
diff --cc src/vm/vm.cpp
index dc956a961f2bb16749a86fbf9edc4fc07d2493f9,4721b8549ad6526ed0fa5663ea49ddfac99d04a0..b713e82098ae05e3767d707449c1fcf3209a3c82
@@@ -89,8 -88,7 +88,7 @@@
  # include "vm/jit/disass.h"
  #endif
  
- #include "vm/jit/jit.h"
 -#include "vm/jit/jit.hpp"
 +#include "vm/jit/jitcache.hpp"
  #include "vm/jit/methodtree.h"
  
  #if defined(ENABLE_PROFILING)