* src/vm/jit/parse.cpp,
[cacao.git] / src / vm / jit / powerpc / codegen.c
index 2c5f69bb400904e4948e290f5b6e2a1c5cd03be1..dcfc0482e276bfe38417c7cbebd7ecc8ca58ab41 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -22,8 +20,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 8297 2007-08-12 00:02:48Z michi $
-
 */
 
 
 
 #include "mm/memory.h"
 
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.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/md.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/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.h"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
 #endif
 
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
 
 /* codegen *********************************************************************
 
@@ -89,11 +84,9 @@ bool codegen_emit(jitdata *jd)
        codegendata        *cd;
        registerdata       *rd;
        s4                  len, s1, s2, s3, d, disp;
-       ptrint              a;
        varinfo            *var;
        basicblock         *bptr;
        instruction        *iptr;
-       exception_entry    *ex;
        u2                  currentline;
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
        unresolved_method  *um;
@@ -102,7 +95,8 @@ bool codegen_emit(jitdata *jd)
        fieldinfo          *fi;
        unresolved_field   *uf;
        s4                  fieldtype;
-       s4                 varindex;
+       s4                  varindex;
+       int                 i;
 
        /* get required compiler data */
 
@@ -139,7 +133,7 @@ bool codegen_emit(jitdata *jd)
           not be shared with place to save the return register on PPC,
           since both values reside in R3. */
 
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+       if (checksync && code_is_synchronized(code))
                cd->stackframesize += 2;
 #endif
 
@@ -147,44 +141,26 @@ bool codegen_emit(jitdata *jd)
 
        /* align stack to 16-bytes */
 
-       if (!jd->isleafmethod || JITDATA_HAS_FLAG_VERBOSECALL(jd))
+       if (!code_is_leafmethod(code) || JITDATA_HAS_FLAG_VERBOSECALL(jd))
                ALIGN_2(cd->stackframesize);
 
-       else if (jd->isleafmethod && (cd->stackframesize == LA_SIZE_IN_POINTERS))
+       else if (code_is_leafmethod(code) && (cd->stackframesize == LA_SIZE_IN_POINTERS))
                cd->stackframesize = 0;
 
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
        (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
 
-#if defined(ENABLE_THREADS)
-       /* IsSync contains the offset relative to the stack pointer for the
-          argument of monitor_exit used in the exception handler. Since the
-          offset could be zero and give a wrong meaning of the flag it is
-          offset by one.
-       */
-
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8);/* IsSync         */
-       else
-#endif
-               (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
-                                              
-       (void) dseg_add_unique_s4(cd, jd->isleafmethod);       /* IsLeaf          */
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+       code->synchronizedoffset = rd->memuse * 8;
 
-       dseg_addlinenumbertablesize(cd);
+       /* REMOVEME: We still need it for exception handling in assembler. */
 
-       (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
-
-       /* create exception table */
+       if (code_is_leafmethod(code))
+               (void) dseg_add_unique_s4(cd, 1);
+       else
+               (void) dseg_add_unique_s4(cd, 0);
 
-       for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
-               dseg_add_target(cd, ex->start);
-               dseg_add_target(cd, ex->end);
-               dseg_add_target(cd, ex->handler);
-               (void) dseg_add_unique_address(cd, ex->catchtype.any);
-       }
+       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
 
 #if defined(ENABLE_PROFILING)
        /* generate method profiling code */
@@ -203,7 +179,7 @@ bool codegen_emit(jitdata *jd)
 
        /* create stack frame (if necessary) */
 
-       if (!jd->isleafmethod) {
+       if (!code_is_leafmethod(code)) {
                M_MFLR(REG_ZERO);
                M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
        }
@@ -302,7 +278,7 @@ bool codegen_emit(jitdata *jd)
 #if defined(ENABLE_THREADS)
        /* call monitorenter function */
 
-       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+       if (checksync && code_is_synchronized(code)) {
                /* stack offset for monitor argument */
 
                s1 = rd->memuse;
@@ -328,13 +304,13 @@ bool codegen_emit(jitdata *jd)
                /* get or test the lock object */
 
                if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->class->object.header);
+                       disp = dseg_add_address(cd, &m->clazz->object.header);
                        M_ALD(REG_A0, REG_PV, disp);
                }
                else {
                        M_TST(REG_A0);
                        M_BNE(1);
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 8);
@@ -444,7 +420,7 @@ bool codegen_emit(jitdata *jd)
 
                for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
                        if (iptr->line != currentline) {
-                               dseg_addlinenumber(cd, iptr->line);
+                               linenumbertable_list_entry_add(cd, iptr->line);
                                currentline = iptr->line;
                        }
 
@@ -464,14 +440,14 @@ bool codegen_emit(jitdata *jd)
                case ICMD_INLINE_BODY:
 
                        REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
-                       dseg_addlinenumber_inline_start(cd, iptr);
-                       dseg_addlinenumber(cd, iptr->line);
+                       linenumbertable_list_entry_add_inline_start(cd, iptr);
+                       linenumbertable_list_entry_add(cd, iptr->line);
                        break;
 
                case ICMD_INLINE_END:
 
-                       dseg_addlinenumber_inline_end(cd, iptr);
-                       dseg_addlinenumber(cd, iptr->line);
+                       linenumbertable_list_entry_add_inline_end(cd, iptr);
+                       linenumbertable_list_entry_add(cd, iptr->line);
                        break;
 
                case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
@@ -499,16 +475,16 @@ bool codegen_emit(jitdata *jd)
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       a = dseg_add_float(cd, iptr->sx.val.f);
-                       M_FLD(d, REG_PV, a);
+                       disp = dseg_add_float(cd, iptr->sx.val.f);
+                       M_FLD(d, REG_PV, disp);
                        emit_store_dst(jd, iptr, d);
                        break;
                        
                case ICMD_DCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       a = dseg_add_double(cd, iptr->sx.val.d);
-                       M_DLD(d, REG_PV, a);
+                       disp = dseg_add_double(cd, iptr->sx.val.d);
+                       M_DLD(d, REG_PV, disp);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -793,7 +769,7 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
 
                        /* XXX TODO: only do this if arithmetic check is really done! */
-                       M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
+                       M_IOR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
                        /* XXX could be optimized */
                        emit_arithmetic_check(cd, iptr, REG_ITMP3);
 
@@ -849,7 +825,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_AND_IMM(s2, 0x1f, REG_ITMP3);
+                       M_IAND_IMM(s2, 0x1f, REG_ITMP3);
                        M_SLL(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -868,7 +844,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_AND_IMM(s2, 0x1f, REG_ITMP3);
+                       M_IAND_IMM(s2, 0x1f, REG_ITMP3);
                        M_SRA(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -887,7 +863,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_AND_IMM(s2, 0x1f, REG_ITMP2);
+                       M_IAND_IMM(s2, 0x1f, REG_ITMP2);
                        M_SRL(s1, REG_ITMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -910,7 +886,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_AND(s1, s2, d);
+                       M_IAND(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -920,7 +896,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
-                               M_AND_IMM(s1, iptr->sx.val.i, d);
+                               M_IAND_IMM(s1, iptr->sx.val.i, d);
                        /*
                        else if (iptr->sx.val.i == 0xffffff) {
                                M_RLWINM(s1, 0, 8, 31, d);
@@ -928,7 +904,7 @@ bool codegen_emit(jitdata *jd)
                        */
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.i);
-                               M_AND(s1, REG_ITMP3, d);
+                               M_IAND(s1, REG_ITMP3, d);
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -938,10 +914,10 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       M_AND(s1, s2, GET_LOW_REG(d));
+                       M_IAND(s1, s2, GET_LOW_REG(d));
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/
-                       M_AND(s1, s2, GET_HIGH_REG(d));
+                       M_IAND(s1, s2, GET_HIGH_REG(d));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -952,18 +928,18 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        if ((s3 >= 0) && (s3 <= 65535))
-                               M_AND_IMM(s1, s3, GET_LOW_REG(d));
+                               M_IAND_IMM(s1, s3, GET_LOW_REG(d));
                        else {
                                ICONST(REG_ITMP3, s3);
-                               M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
+                               M_IAND(s1, REG_ITMP3, GET_LOW_REG(d));
                        }
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s3 = iptr->sx.val.l >> 32;
                        if ((s3 >= 0) && (s3 <= 65535))
-                               M_AND_IMM(s1, s3, GET_HIGH_REG(d));
+                               M_IAND_IMM(s1, s3, GET_HIGH_REG(d));
                        else {
                                ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
-                               M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
+                               M_IAND(s1, REG_ITMP3, GET_HIGH_REG(d));
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -978,7 +954,7 @@ bool codegen_emit(jitdata *jd)
                        M_BGE(1 + 2*(iptr->sx.val.i >= 32768));
                        if (iptr->sx.val.i >= 32768) {
                                M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2);
-                               M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
+                               M_IOR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
                                M_IADD(s1, REG_ITMP2, REG_ITMP2);
                        }
                        else {
@@ -999,7 +975,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_OR(s1, s2, d);
+                       M_IOR(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1009,10 +985,10 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
-                               M_OR_IMM(s1, iptr->sx.val.i, d);
+                               M_IOR_IMM(s1, iptr->sx.val.i, d);
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.i);
-                               M_OR(s1, REG_ITMP3, d);
+                               M_IOR(s1, REG_ITMP3, d);
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1022,10 +998,10 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       M_OR(s1, s2, GET_LOW_REG(d));
+                       M_IOR(s1, s2, GET_LOW_REG(d));
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/
-                       M_OR(s1, s2, GET_HIGH_REG(d));
+                       M_IOR(s1, s2, GET_HIGH_REG(d));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1036,18 +1012,18 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        if ((s3 >= 0) && (s3 <= 65535))
-                               M_OR_IMM(s1, s3, GET_LOW_REG(d));
+                               M_IOR_IMM(s1, s3, GET_LOW_REG(d));
                        else {
                                ICONST(REG_ITMP3, s3);
-                               M_OR(s1, REG_ITMP3, GET_LOW_REG(d));
+                               M_IOR(s1, REG_ITMP3, GET_LOW_REG(d));
                        }
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s3 = iptr->sx.val.l >> 32;
                        if ((s3 >= 0) && (s3 <= 65535))
-                               M_OR_IMM(s1, s3, GET_HIGH_REG(d));
+                               M_IOR_IMM(s1, s3, GET_HIGH_REG(d));
                        else {
                                ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
-                               M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
+                               M_IOR(s1, REG_ITMP3, GET_HIGH_REG(d));
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1247,7 +1223,6 @@ bool codegen_emit(jitdata *jd)
                case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
                case ICMD_DCMPL:      /* == => 0, < => 1, > => -1                     */
 
-
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -1277,107 +1252,6 @@ bool codegen_emit(jitdata *jd)
                        emit_store_dst(jd, iptr, d);
                        break;
                        
-               case ICMD_IF_FCMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPEQ:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       M_BNAN(1);
-                       emit_beq(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPNE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       emit_bnan(cd, iptr->dst.block);
-                       emit_bne(cd, iptr->dst.block);
-                       break;
-
-
-               case ICMD_IF_FCMPL_LT:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPL_LT:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       emit_bnan(cd, iptr->dst.block);
-                       emit_blt(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPL_GT:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPL_GT:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       M_BNAN(1);
-                       emit_bgt(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPL_LE:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPL_LE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       emit_bnan(cd, iptr->dst.block);
-                       emit_ble(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPL_GE:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPL_GE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       M_BNAN(1);
-                       emit_bge(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPG_LT:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPG_LT:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       M_BNAN(1);
-                       emit_blt(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPG_GT:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPG_GT:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       emit_bnan(cd, iptr->dst.block);
-                       emit_bgt(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPG_LE:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPG_LE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       M_BNAN(1);
-                       emit_ble(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_FCMPG_GE:  /* ..., value, value ==> ...                  */
-               case ICMD_IF_DCMPG_GE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-                       M_FCMPU(s1, s2);
-                       emit_bnan(cd, iptr->dst.block);
-                       emit_bge(cd, iptr->dst.block);
-                       break;
-
 
                /* memory operations **************************************************/
 
@@ -1386,7 +1260,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        /* implicit null-pointer check */
-                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       M_ILD(d, s1, OFFSET(java_array_t, size));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1396,7 +1270,7 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
-                       M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LBZX(d, s1, REG_ITMP2);
                        M_BSEXT(d, d);
@@ -1410,7 +1284,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LHZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1423,7 +1297,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LHAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1436,7 +1310,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LWZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1451,7 +1325,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD(s1, REG_ITMP2, REG_ITMP2);
-                       M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
+                       M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1462,7 +1336,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LFSX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1475,7 +1349,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LFDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1488,7 +1362,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_LWZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
@@ -1501,7 +1375,7 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STBX(s3, s1, REG_ITMP2);
                        break;
@@ -1513,7 +1387,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
@@ -1525,7 +1399,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
@@ -1537,7 +1411,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
@@ -1549,7 +1423,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
@@ -1564,7 +1438,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STFSX(s3, s1, REG_ITMP2);
                        break;
@@ -1576,7 +1450,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STFDX(s3, s1, REG_ITMP2);
                        break;
@@ -1589,7 +1463,7 @@ bool codegen_emit(jitdata *jd)
                        s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        /* XXX what if array is NULL */
-                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+                       disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_MTCTR(REG_ITMP3);
 
@@ -1597,13 +1471,13 @@ bool codegen_emit(jitdata *jd)
                        M_INTMOVE(s3, REG_A1);
 
                        M_JSR;
-                       emit_exception_check(cd, iptr);
+                       emit_arraystore_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
-                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
                        /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
@@ -1623,9 +1497,9 @@ bool codegen_emit(jitdata *jd)
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, fi->value);
 
-                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                               fi->class, disp);
+                                                                               fi->clazz, disp);
                        }
 
                        M_ALD(REG_ITMP1, REG_PV, disp);
@@ -1669,9 +1543,9 @@ bool codegen_emit(jitdata *jd)
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, fi->value);
 
-                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                               fi->class, disp);
+                                                                               fi->clazz, disp);
                        }
 
                        M_ALD(REG_ITMP1, REG_PV, disp);
@@ -1818,13 +1692,13 @@ bool codegen_emit(jitdata *jd)
                        M_ALD(REG_ITMP2, REG_PV, disp);
                        M_MTCTR(REG_ITMP2);
 
-                       if (jd->isleafmethod)
+                       if (code_is_leafmethod(code))
                                M_MFLR(REG_ITMP3);                          /* save LR        */
 
                        M_BL(0);                                        /* get current PC */
                        M_MFLR(REG_ITMP2_XPC);
 
-                       if (jd->isleafmethod)
+                       if (code_is_leafmethod(code))
                                M_MTLR(REG_ITMP3);                          /* restore LR     */
 
                        M_RTS;                                          /* jump to CTR    */
@@ -1875,19 +1749,19 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
                        if (iptr->sx.val.l == 0) {
-                               M_OR_TST(s1, s2, REG_ITMP3);
+                               M_IOR_TST(s1, s2, REG_ITMP3);
                        }
                        else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_XOR_IMM(s2, 0, REG_ITMP2);
                                M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1);
-                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                               M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP1);
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_XOR(s2, REG_ITMP3, REG_ITMP2);
-                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                               M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
                        emit_beq(cd, iptr->dst.block);
                        break;
@@ -1926,7 +1800,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
 /*                     if (iptr->sx.val.l == 0) { */
-/*                             M_OR(s1, s2, REG_ITMP3); */
+/*                             M_IOR(s1, s2, REG_ITMP3); */
 /*                             M_CMPI(REG_ITMP3, 0); */
 
 /*                     } else  */
@@ -1953,19 +1827,19 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
                        if (iptr->sx.val.l == 0) {
-                               M_OR_TST(s1, s2, REG_ITMP3);
+                               M_IOR_TST(s1, s2, REG_ITMP3);
                        }
                        else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_XOR_IMM(s2, 0, REG_ITMP2);
                                M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1);
-                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                               M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP1);
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_XOR(s2, REG_ITMP3, REG_ITMP2);
-                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                               M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
                        emit_bne(cd, iptr->dst.block);
                        break;
@@ -1975,7 +1849,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
 /*                     if (iptr->sx.val.l == 0) { */
-/*                             M_OR(s1, s2, REG_ITMP3); */
+/*                             M_IOR(s1, s2, REG_ITMP3); */
 /*                             M_CMPI(REG_ITMP3, 0); */
 
 /*                     } else  */
@@ -2181,7 +2055,7 @@ nowperformreturn:
                        emit_verbosecall_exit(jd);
 
 #if defined(ENABLE_THREADS)
-                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                       if (checksync && code_is_synchronized(code)) {
                                disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
                                M_ALD(REG_ITMP3, REG_PV, disp);
                                M_MTCTR(REG_ITMP3);
@@ -2225,7 +2099,7 @@ nowperformreturn:
 
                        /* restore return address                                         */
 
-                       if (!jd->isleafmethod) {
+                       if (!code_is_leafmethod(code)) {
                                /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
                                   may have a displacement overflow. */
 
@@ -2334,6 +2208,8 @@ nowperformreturn:
 
                case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
 
+                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
+
                        bte = iptr->sx.s23.s3.bte;
                        md  = bte->md;
                        goto gen_method;
@@ -2358,57 +2234,68 @@ nowperformreturn:
                        }
 
 gen_method:
-                       s3 = md->paramcount;
+                       i = md->paramcount;
 
-                       MCODECHECK((s3 << 1) + 64);
+                       MCODECHECK((i << 1) + 64);
 
-                       /* copy arguments to registers or stack location */
+                       /* Copy arguments to registers or stack location. */
 
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
+                       for (i = i - 1; i >= 0; i--) {
+                               var = VAR(iptr->sx.s23.s2.args[i]);
+                               d   = md->params[i].regoff;
+
+                               /* Already pre-allocated? */
 
-                               /* Already Preallocated? */
                                if (var->flags & PREALLOC)
                                        continue;
 
-                               if (IS_INT_LNG_TYPE(var->type)) {
-                                       if (!md->params[s3].inmemory) {
-                                               if (IS_2_WORD_TYPE(var->type)) {
-                                                       s1 = emit_load(jd, iptr, var, d);
-                                                       M_LNGMOVE(s1, d);
-                                               }
-                                               else {
-                                                       s1 = emit_load(jd, iptr, var, d);
-                                                       M_INTMOVE(s1, d);
-                                               }
-                                       }
-                                       else {
-                                               if (IS_2_WORD_TYPE(var->type)) {
-                                                       s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                                       M_LST(s1, REG_SP, d);
-                                               }
-                                               else {
-                                                       s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                                       M_IST(s1, REG_SP, d);
-                                               }
+                               if (!md->params[i].inmemory) {
+                                       s1 = emit_load(jd, iptr, var, d);
+
+                                       switch (var->type) {
+                                       case TYPE_INT:
+                                       case TYPE_ADR:
+                                               M_INTMOVE(s1, d);
+                                               break;
+
+                                       case TYPE_LNG:
+                                               M_LNGMOVE(s1, d);
+                                               break;
+
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
+                                               M_FLTMOVE(s1, d);
+                                               break;
                                        }
                                }
                                else {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               M_FLTMOVE(s1, d);
-                                       }
-                                       else {
+                                       switch (var->type) {
+                                       case TYPE_INT:
+                                       case TYPE_ADR:
+                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
+                                               M_IST(s1, REG_SP, d);
+                                               break;
+
+                                       case TYPE_LNG:
+                                               s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
+                                               M_LST(s1, REG_SP, d);
+                                               break;
+
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
                                                s1 = emit_load(jd, iptr, var, REG_FTMP1);
                                                M_DST(s1, REG_SP, d);
+                                               break;
                                        }
                                }
                        }
 
                        switch (iptr->opc) {
                        case ICMD_BUILTIN:
-                               disp = dseg_add_functionptr(cd, bte->fp);
+                               if (bte->stub == NULL)
+                                       disp = dseg_add_functionptr(cd, bte->fp);
+                               else
+                                       disp = dseg_add_functionptr(cd, bte->stub);
 
                                M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
 
@@ -2417,11 +2304,10 @@ gen_method:
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
-
-                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
@@ -2484,9 +2370,9 @@ gen_method:
                                }
                                else {
                                        s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->class->index;
+                                               sizeof(methodptr*) * lm->clazz->index;
 
-                                       s2 = sizeof(methodptr) * (lm - lm->class->methods);
+                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                                }
 
                                /* implicit null-pointer check */
@@ -2505,26 +2391,31 @@ gen_method:
                                break;
                        }
 
-                       /* store return value */
+                       /* Store return value. */
 
-                       d = md->returntype.type;
+                       switch (md->returntype.type) {
+                       case TYPE_INT:
+                       case TYPE_ADR:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                               M_INTMOVE(REG_RESULT, s1);
+                               emit_store_dst(jd, iptr, s1);
+                               break;
 
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-                                       if (IS_2_WORD_TYPE(d)) {
-                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
-                                               M_LNGMOVE(REG_RESULT_PACKED, s1);
-                                       }
-                                       else {
-                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                               M_INTMOVE(REG_RESULT, s1);
-                                       }
-                               }
-                               else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                                       M_FLTMOVE(REG_FRESULT, s1);
-                               }
+                       case TYPE_LNG:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+                               M_LNGMOVE(REG_RESULT_PACKED, s1);
                                emit_store_dst(jd, iptr, s1);
+                               break;
+
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                               M_FLTMOVE(REG_FRESULT, s1);
+                               emit_store_dst(jd, iptr, s1);
+                               break;
+
+                       case TYPE_VOID:
+                               break;
                        }
                        break;
 
@@ -2546,9 +2437,6 @@ gen_method:
                                        superindex = super->index;
                                }
 
-                               if ((super == NULL) || !(super->flags & ACC_INTERFACE))
-                                       CODEGEN_CRITICAL_SECTION_NEW;
-
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
                                /* if class is not resolved, check which code to call */
@@ -2565,7 +2453,7 @@ gen_method:
                                                                                disp);
 
                                        M_ILD(REG_ITMP2, REG_PV, disp);
-                                       M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
+                                       M_IAND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
                                        emit_label_beq(cd, BRANCH_LABEL_2);
                                }
 
@@ -2621,16 +2509,12 @@ gen_method:
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
 
-                                       CODEGEN_CRITICAL_SECTION_START;
-
                                        M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                        M_ALD(REG_ITMP2, REG_PV, disp);
                                        if (s1 != REG_ITMP1) {
                                                M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                                M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
 
-                                               CODEGEN_CRITICAL_SECTION_END;
-
                                                M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
                                        }
                                        else {
@@ -2638,8 +2522,6 @@ gen_method:
                                                M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
                                                M_ALD(REG_ITMP2, REG_PV, disp);
                                                M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-
-                                               CODEGEN_CRITICAL_SECTION_END;
                                        }
                                        M_CMPU(REG_ITMP3, REG_ITMP2);
                                        emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
@@ -2701,9 +2583,6 @@ gen_method:
                                superindex = super->index;
                        }
                        
-                       if ((super == NULL) || !(super->flags & ACC_INTERFACE))
-                               CODEGEN_CRITICAL_SECTION_NEW;
-
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -2726,7 +2605,7 @@ gen_method:
                                                                        iptr->sx.s23.s3.c.ref, disp);
 
                                M_ILD(REG_ITMP3, REG_PV, disp);
-                               M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
+                               M_IAND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
                                emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
@@ -2782,14 +2661,10 @@ gen_method:
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_ALD(REG_ITMP2, REG_PV, disp);
 
-                               CODEGEN_CRITICAL_SECTION_START;
-
                                M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
                                M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
 
-                               CODEGEN_CRITICAL_SECTION_END;
-
                                M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMPU(REG_ITMP1, REG_ITMP2);
                                M_CLR(d);
@@ -2883,8 +2758,6 @@ gen_method:
        } /* if (bptr -> flags >= BBREACHED) */
        } /* for basic block */
 
-       dseg_createlinenumbertable(cd);
-
        /* generate traps */
 
        emit_patcher_traps(jd);
@@ -2895,50 +2768,28 @@ gen_method:
 }
 
 
-/* codegen_emit_stub_compiler **************************************************
-
-   Emits a stub routine which calls the compiler.
-       
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
-       methodinfo  *m;
-       codegendata *cd;
-
-       /* get required compiler data */
-
-       m  = jd->m;
-       cd = jd->cd;
-
-       /* code for the stub */
-
-       M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P);
-       M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P);
-       M_MTCTR(REG_PV);
-       M_RTS;
-}
-
-
 /* codegen_emit_stub_native ****************************************************
 
    Emits a stub routine which calls a native method.
 
 *******************************************************************************/
 
-void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
 {
        methodinfo  *m;
        codeinfo    *code;
        codegendata *cd;
        methoddesc  *md;
-       s4           nativeparams;
        s4           i, j;                 /* count variables                    */
        s4           t;
-       s4           s1, s2, disp;
-       s4           funcdisp;
+       s4           s1, s2;
+       int          disp;
 
-       /* get required compiler data */
+       /* Sanity check. */
+
+       assert(f != NULL);
+
+       /* Get required compiler data. */
 
        m    = jd->m;
        code = jd->code;
@@ -2947,20 +2798,19 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        /* set some variables */
 
        md = m->parseddesc;
-       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
 
        /* calculate stackframe size */
 
        cd->stackframesize =
-               sizeof(stackframeinfo) / SIZEOF_VOID_P +
+               sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
                sizeof(localref_table) / SIZEOF_VOID_P +
-               4 +                             /* 4 stackframeinfo arguments (darwin)*/
-               nmd->paramcount * 2 +           /* assume all arguments are doubles   */
+               4 +                            /* 4 stackframeinfo arguments (darwin) */
+               nmd->paramcount +
                nmd->memuse;
 
        /* keep stack 16-byte aligned */
 
-       cd->stackframesize = (cd->stackframesize + 3) & ~3;
+       ALIGN_2(cd->stackframesize);
 
        /* create method header */
 
@@ -2970,8 +2820,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
        (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
        (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
-       (void) dseg_addlinenumbertablesize(cd);
-       (void) dseg_add_unique_s4(cd, 0);                      /* ExTableSize     */
 
        /* generate code */
 
@@ -2979,19 +2827,17 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
        M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8));
 
-       /* get function address (this must happen before the stackframeinfo) */
+#if defined(ENABLE_GC_CACAO)
+       /* Save callee saved integer registers in stackframeinfo (GC may
+          need to recover them during a collection). */
 
-       funcdisp = dseg_add_functionptr(cd, f);
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
+               OFFSET(stackframeinfo_t, intregs);
 
-#if !defined(WITH_STATIC_CLASSPATH)
-       if (f == NULL)
-               patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
 #endif
 
-       /* emit trace code */
-
-       emit_verbosecall_enter(jd);
-
        /* save integer and float argument registers */
 
        for (i = 0; i < md->paramcount; i++) {
@@ -3016,15 +2862,18 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* create native stack info */
 
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       M_MOV(REG_SP, REG_A0);
        M_MOV(REG_PV, REG_A1);
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2);
-       M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
        disp = dseg_add_functionptr(cd, codegen_start_native_call);
        M_ALD(REG_ITMP1, REG_PV, disp);
        M_MTCTR(REG_ITMP1);
        M_JSR;
 
+       /* remember class argument */
+
+       if (m->flags & ACC_STATIC)
+               M_MOV(REG_RESULT, REG_ITMP3);
+
        /* restore integer and float argument registers */
 
        for (i = 0; i < md->paramcount; i++) {
@@ -3049,93 +2898,99 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* copy or spill arguments to new locations */
 
-       for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+       for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
                t = md->paramtypes[i].type;
 
-               if (IS_INT_LNG_TYPE(t)) {
-                       if (!md->params[i].inmemory) {
-                               s1 = md->params[i].regoff;
-                               s2 = nmd->params[j].regoff;
+               if (!md->params[i].inmemory) {
+                       s1 = md->params[i].regoff;
+                       s2 = nmd->params[j].regoff;
 
-                               if (!nmd->params[j].inmemory) {
-                                       if (IS_2_WORD_TYPE(t))
-                                               M_LNGMOVE(s1, s2);
-                                       else
-                                               M_INTMOVE(s1, s2);
-                               }
-                               else {
-                                       if (IS_2_WORD_TYPE(t))
-                                               M_LST(s1, REG_SP, s2);
-                                       else
-                                               M_IST(s1, REG_SP, s2);
-                               }
-                       }
-                       else {
-                               s1 = md->params[i].regoff + cd->stackframesize * 8;
-                               s2 = nmd->params[j].regoff;
+                       switch (t) {
+                       case TYPE_INT:
+                       case TYPE_ADR:
+                               if (!nmd->params[j].inmemory)
+                                       M_INTMOVE(s1, s2);
+                               else
+                                       M_IST(s1, REG_SP, s2);
+                               break;
 
-                               M_ILD(REG_ITMP1, REG_SP, s1);
-                               if (IS_2_WORD_TYPE(t))
-                                       M_ILD(REG_ITMP2, REG_SP, s1 + 4);
+                       case TYPE_LNG:
+                               if (!nmd->params[j].inmemory)
+                                       M_LNGMOVE(s1, s2);
+                               else
+                                       M_LST(s1, REG_SP, s2);
+                               break;
 
-                               M_IST(REG_ITMP1, REG_SP, s2);
-                               if (IS_2_WORD_TYPE(t))
-                                       M_IST(REG_ITMP2, REG_SP, s2 + 4);
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               /* We only copy spilled float arguments, as the float
+                                  argument registers keep unchanged. */
+                               break;
                        }
                }
                else {
-                       /* We only copy spilled float arguments, as the float
-                          argument registers keep unchanged. */
+                       s1 = md->params[i].regoff + cd->stackframesize * 8;
+                       s2 = nmd->params[j].regoff;
+
+                       switch (t) {
+                       case TYPE_INT:
+                       case TYPE_ADR:
+                               M_ILD(REG_ITMP1, REG_SP, s1);
+                               M_IST(REG_ITMP1, REG_SP, s2);
+                               break;
 
-                       if (md->params[i].inmemory) {
-                               s1 = md->params[i].regoff + cd->stackframesize * 8;
-                               s2 = nmd->params[j].regoff;
+                       case TYPE_LNG:
+                               M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
+                               M_LST(REG_ITMP12_PACKED, REG_SP, s2);
+                               break;
 
+                       case TYPE_FLT:
                                M_DLD(REG_FTMP1, REG_SP, s1);
+                               M_FST(REG_FTMP1, REG_SP, s2);
+                               break;
 
-                               if (IS_2_WORD_TYPE(t))
-                                       M_DST(REG_FTMP1, REG_SP, s2);
-                               else
-                                       M_FST(REG_FTMP1, REG_SP, s2);
+                       case TYPE_DBL:
+                               M_DLD(REG_FTMP1, REG_SP, s1);
+                               M_DST(REG_FTMP1, REG_SP, s2);
+                               break;
                        }
                }
        }
 
-       /* put class into second argument register */
+       /* Handle native Java methods. */
 
-       if (m->flags & ACC_STATIC) {
-               disp = dseg_add_address(cd, m->class);
-               M_ALD(REG_A1, REG_PV, disp);
-       }
+       if (m->flags & ACC_NATIVE) {
+               /* put class into second argument register */
 
-       /* put env into first argument register */
+               if (m->flags & ACC_STATIC)
+                       M_MOV(REG_ITMP3, REG_A1);
 
-       disp = dseg_add_address(cd, _Jv_env);
-       M_ALD(REG_A0, REG_PV, disp);
+               /* put env into first argument register */
 
-       /* generate the actual native call */
+               disp = dseg_add_address(cd, VM_get_jnienv());
+               M_ALD(REG_A0, REG_PV, disp);
+       }
+
+       /* Call the native function. */
 
-       M_ALD(REG_ITMP3, REG_PV, funcdisp);
+       disp = dseg_add_functionptr(cd, f);
+       M_ALD(REG_ITMP3, REG_PV, disp);
        M_MTCTR(REG_ITMP3);
        M_JSR;
 
-       /* print call trace */
-
-       emit_verbosecall_exit(jd);
-
        /* save return value */
 
        switch (md->returntype.type) {
        case TYPE_INT:
        case TYPE_ADR:
-               M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_IST(REG_RESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_LNG:
-               M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_FLT:
        case TYPE_DBL:
-               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_VOID:
                break;
@@ -3143,7 +2998,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* remove native stackframe info */
 
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       M_MOV(REG_SP, REG_A0);
+       M_MOV(REG_PV, REG_A1);
        disp = dseg_add_functionptr(cd, codegen_finish_native_call);
        M_ALD(REG_ITMP1, REG_PV, disp);
        M_MTCTR(REG_ITMP1);
@@ -3155,19 +3011,30 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        switch (md->returntype.type) {
        case TYPE_INT:
        case TYPE_ADR:
-               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_LNG:
-               M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_FLT:
        case TYPE_DBL:
-               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_VOID:
                break;
        }
 
+#if defined(ENABLE_GC_CACAO)
+       /* Restore callee saved integer registers from stackframeinfo (GC
+          might have modified them during a collection). */
+        
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
+               OFFSET(stackframeinfo_t, intregs);
+
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
        M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
        M_MTLR(REG_ITMP2_XPC);
        M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe       */
@@ -3187,10 +3054,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        M_ALD(REG_ITMP3, REG_PV, disp);
        M_MTCTR(REG_ITMP3);
        M_RTS;
-
-       /* generate patcher traps */
-
-       emit_patcher_traps(jd);
 }