GNU header update.
[cacao.git] / src / vm / jit / x86_64 / codegen.c
index 541c7fa40d0a1cb9a1eff6f0713f0a9d8368dfbd..ebadb228d67f0c41e0db44c7f7abc9d7dbb17566 100644 (file)
@@ -1,10 +1,9 @@
 /* jit/x86_64/codegen.c - machine code generator for x86_64
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Institut f. Computersprachen, TU Wien
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
-   S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
-   J. Wenninger
+   Copyright (C) 1996-2005 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
 
    This file is part of CACAO.
 
    Authors: Andreas Krall
             Christian Thalinger
 
-   $Id: codegen.c 1494 2004-11-12 13:34:26Z twisti $
+   $Id: codegen.c 1735 2004-12-07 14:33:27Z twisti $
 
 */
 
+
 #define _GNU_SOURCE
 
-#include "global.h"
 #include <stdio.h>
-#include <signal.h>
-#include <sys/ucontext.h>
-#include "builtin.h"
-#include "asmpart.h"
-#include "jni.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "jit/jit.h"
-#include "jit/reg.h"
-#include "jit/parse.h"
-#include "jit/x86_64/codegen.h"
-#include "jit/x86_64/emitfuncs.h"
-#include "jit/x86_64/types.h"
+#include <ucontext.h>
+
+#include "native/native.h"
+/*  #include "native/jni.h" */
+#include "vm/global.h"
+#include "vm/builtin.h"
+#include "vm/loader.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/x86_64/arch.h"
+#include "vm/jit/x86_64/codegen.h"
+#include "vm/jit/x86_64/emitfuncs.h"
+#include "vm/jit/x86_64/types.h"
+#include "vm/jit/x86_64/asmoffsets.h"
 
 
 /* register descripton - array ************************************************/
 
 /* #define REG_END   -1        last entry in tables                           */
 
-int nregdescint[] = {
+static int nregdescint[] = {
     REG_RET, REG_ARG, REG_ARG, REG_TMP, REG_RES, REG_SAV, REG_ARG, REG_ARG,
     REG_ARG, REG_ARG, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
     REG_END
 };
 
 
-int nregdescfloat[] = {
-       /*      REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, */
-       /*      REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, */
+static int nregdescfloat[] = {
+/*      REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, */
+/*      REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, */
     REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
     REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
     REG_END
 };
 
 
-/*******************************************************************************
-
-    include independent code generation stuff -- include after register
-    descriptions to avoid extern definitions
-
-*******************************************************************************/
+/* Include independent code generation stuff -- include after register        */
+/* descriptions to avoid extern definitions.                                  */
 
-#include "jit/codegen.inc"
-#include "jit/reg.inc"
+#include "vm/jit/codegen.inc"
+#include "vm/jit/reg.inc"
+#ifdef LSRA
+#include "vm/jit/lsra.inc"
+#endif
 
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
@@ -2281,14 +2282,25 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
                                      /* op1 = type, val.a = field address            */
 
-                       /* if class isn't yet initialized, do it */
+                       /* If the static fields' class is not yet initialized, we do it   */
+                       /* now. The call code is generated later.                         */
                        if (!((fieldinfo *) iptr->val.a)->class->initialized) {
-                               /* call helper function which patches this code */
-                               x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
-                               x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
-                               x86_64_call_reg(cd, REG_ITMP2);
+                               codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
+
+                               /* This is just for debugging purposes. Is very difficult to  */
+                               /* read patched code. Here we patch the following 5 nop's     */
+                               /* so that the real code keeps untouched.                     */
+                               if (showdisassemble) {
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                               }
                        }
 
+                       /* This approach is much faster than moving the field address     */
+                       /* inline into a register. */
                        a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
                        x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
                        switch (iptr->op1) {
@@ -2309,21 +2321,35 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                var_to_reg_flt(s2, src, REG_FTMP1);
                                x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
                                break;
-                       default: panic("internal error");
+                       default:
+                               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                                  "Unknown PUTSTATIC operand type %d",
+                                                                                  iptr->op1);
                        }
                        break;
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
                                      /* op1 = type, val.a = field address            */
 
-                       /* if class isn't yet initialized, do it */
+                       /* If the static fields' class is not yet initialized, we do it   */
+                       /* now. The call code is generated later.                         */
                        if (!((fieldinfo *) iptr->val.a)->class->initialized) {
-                               /* call helper function which patches this code */
-                               x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
-                               x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
-                               x86_64_call_reg(cd, REG_ITMP2);
+                               codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
+
+                               /* This is just for debugging purposes. Is very difficult to  */
+                               /* read patched code. Here we patch the following 5 nop's     */
+                               /* so that the real code keeps untouched.                     */
+                               if (showdisassemble) {
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                                       x86_64_nop(cd);
+                               }
                        }
 
+                       /* This approach is much faster than moving the field address     */
+                       /* inline into a register. */
                        a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
                        x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
                        switch (iptr->op1) {
@@ -2348,47 +2374,45 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
                                store_reg_to_var_flt(iptr->dst, d);
                                break;
-                       default: panic("internal error");
+                       default:
+                               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                                  "Unknown GETSTATIC operand type %d",
+                                                                                  iptr->op1);
                        }
                        break;
 
                case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
                                      /* op1 = type, val.i = field offset             */
 
-                       /* if class isn't yet initialized, do it */
-                       if (!((fieldinfo *) iptr->val.a)->class->initialized) {
-                               /* call helper function which patches this code */
-                               x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
-                               x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
-                               x86_64_call_reg(cd, REG_ITMP2);
-                       }
-
                        a = ((fieldinfo *)(iptr->val.a))->offset;
                        var_to_reg_int(s1, src->prev, REG_ITMP1);
                        switch (iptr->op1) {
-                               case TYPE_INT:
-                                       var_to_reg_int(s2, src, REG_ITMP2);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movl_reg_membase(cd, s2, s1, a);
-                                       break;
-                               case TYPE_LNG:
-                               case TYPE_ADR:
-                                       var_to_reg_int(s2, src, REG_ITMP2);
-                                       gen_nullptr_check(s1);
-                                       x86_64_mov_reg_membase(cd, s2, s1, a);
-                                       break;
-                               case TYPE_FLT:
-                                       var_to_reg_flt(s2, src, REG_FTMP2);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movss_reg_membase(cd, s2, s1, a);
-                                       break;
-                               case TYPE_DBL:
-                                       var_to_reg_flt(s2, src, REG_FTMP2);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movsd_reg_membase(cd, s2, s1, a);
-                                       break;
-                               default: panic ("internal error");
-                               }
+                       case TYPE_INT:
+                               var_to_reg_int(s2, src, REG_ITMP2);
+                               gen_nullptr_check(s1);
+                               x86_64_movl_reg_membase(cd, s2, s1, a);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               var_to_reg_int(s2, src, REG_ITMP2);
+                               gen_nullptr_check(s1);
+                               x86_64_mov_reg_membase(cd, s2, s1, a);
+                               break;
+                       case TYPE_FLT:
+                               var_to_reg_flt(s2, src, REG_FTMP2);
+                               gen_nullptr_check(s1);
+                               x86_64_movss_reg_membase(cd, s2, s1, a);
+                               break;
+                       case TYPE_DBL:
+                               var_to_reg_flt(s2, src, REG_FTMP2);
+                               gen_nullptr_check(s1);
+                               x86_64_movsd_reg_membase(cd, s2, s1, a);
+                               break;
+                       default:
+                               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                                  "Unknown PUTFIELD operand type %d",
+                                                                                  iptr->op1);
+                       }
                        break;
 
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
@@ -2397,33 +2421,36 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        a = ((fieldinfo *)(iptr->val.a))->offset;
                        var_to_reg_int(s1, src, REG_ITMP1);
                        switch (iptr->op1) {
-                               case TYPE_INT:
-                                       d = reg_of_var(rd, iptr->dst, REG_ITMP1);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movl_membase_reg(cd, s1, a, d);
-                                       store_reg_to_var_int(iptr->dst, d);
-                                       break;
-                               case TYPE_LNG:
-                               case TYPE_ADR:
-                                       d = reg_of_var(rd, iptr->dst, REG_ITMP1);
-                                       gen_nullptr_check(s1);
-                                       x86_64_mov_membase_reg(cd, s1, a, d);
-                                       store_reg_to_var_int(iptr->dst, d);
-                                       break;
-                               case TYPE_FLT:
-                                       d = reg_of_var(rd, iptr->dst, REG_FTMP1);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movss_membase_reg(cd, s1, a, d);
-                                       store_reg_to_var_flt(iptr->dst, d);
-                                       break;
-                               case TYPE_DBL:                          
-                                       d = reg_of_var(rd, iptr->dst, REG_FTMP1);
-                                       gen_nullptr_check(s1);
-                                       x86_64_movsd_membase_reg(cd, s1, a, d);
-                                       store_reg_to_var_flt(iptr->dst, d);
-                                       break;
-                               default: panic ("internal error");
-                               }
+                       case TYPE_INT:
+                               d = reg_of_var(rd, iptr->dst, REG_ITMP1);
+                               gen_nullptr_check(s1);
+                               x86_64_movl_membase_reg(cd, s1, a, d);
+                               store_reg_to_var_int(iptr->dst, d);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               d = reg_of_var(rd, iptr->dst, REG_ITMP1);
+                               gen_nullptr_check(s1);
+                               x86_64_mov_membase_reg(cd, s1, a, d);
+                               store_reg_to_var_int(iptr->dst, d);
+                               break;
+                       case TYPE_FLT:
+                               d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+                               gen_nullptr_check(s1);
+                               x86_64_movss_membase_reg(cd, s1, a, d);
+                               store_reg_to_var_flt(iptr->dst, d);
+                               break;
+                       case TYPE_DBL:                          
+                               d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+                               gen_nullptr_check(s1);
+                               x86_64_movsd_membase_reg(cd, s1, a, d);
+                               store_reg_to_var_flt(iptr->dst, d);
+                               break;
+                       default:
+                               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                                  "Unknown GETFIELD operand type %d",
+                                                                                  iptr->op1);
+                       }
                        break;
 
 
@@ -2434,7 +2461,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s1, src, REG_ITMP1);
                        M_INTMOVE(s1, REG_ITMP1_XPTR);
 
-                       x86_64_call_imm(cd, 0); /* passing exception pointer                  */
+                       x86_64_call_imm(cd, 0); /* passing exception pointer              */
                        x86_64_pop_reg(cd, REG_ITMP2_XPC);
 
                        x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
@@ -3408,7 +3435,9 @@ gen_method: {
                        store_reg_to_var_int(iptr->dst, s1);
                        break;
 
-               default: error("Unknown pseudo command: %d", iptr->opc);
+               default:
+                       throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                          "Unknown ICMD %d", iptr->opc);
        } /* switch */
                
        } /* for instruction */
@@ -3710,6 +3739,46 @@ gen_method: {
                        x86_64_jmp_reg(cd, REG_ITMP3);
                }
        }
+
+       /* generate put/getstatic stub call code */
+
+       {
+               clinitref   *cref;
+               codegendata *tmpcd;
+               u1           xmcode;
+               u4           mcode;
+
+               tmpcd = DNEW(codegendata);
+
+               for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
+                       /* Get machine code which is patched back in later. A             */
+                       /* `call rel32' is 5 bytes long.                                  */
+                       xcodeptr = cd->mcodebase + cref->branchpos;
+                       xmcode = *xcodeptr;
+                       mcode = *((u4 *) (xcodeptr + 1));
+
+                       MCODECHECK(50);
+
+                       /* patch in `call rel32' to call the following code               */
+                       tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
+                       x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+                       /* Save current stack pointer into a temporary register.          */
+                       x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+                       /* Push machine code bytes to patch onto the stack.               */
+                       x86_64_push_imm(cd, (u1) xmcode);
+                       x86_64_push_imm(cd, (u4) mcode);
+
+                       x86_64_push_imm(cd, (u8) cref->class);
+
+                       /* Push previously saved stack pointer onto stack.                */
+                       x86_64_push_reg(cd, REG_ITMP1);
+
+                       x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
+                       x86_64_jmp_reg(cd, REG_ITMP1);
+               }
+       }
        }
 
        codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
@@ -3738,8 +3807,8 @@ u1 *createcompilerstub(methodinfo *m)
        cd->mcodeptr = s;
 
        /* code for the stub */
-       x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1); /* pass method to compiler     */
-       x86_64_mov_imm_reg(cd, (s8) asm_call_jit_compiler, REG_ITMP3);/* load address */
+       x86_64_mov_imm_reg(cd, (u8) m, REG_ITMP1); /* pass method to compiler     */
+       x86_64_mov_imm_reg(cd, (u8) asm_call_jit_compiler, REG_ITMP3);/* load address */
        x86_64_jmp_reg(cd, REG_ITMP3);      /* jump to compiler                   */
 
 #if defined(STATISTICS)
@@ -3788,6 +3857,10 @@ u1 *createnativestub(functionptr f, methodinfo *m)
        t_inlining_globals *id;
        s4 dumpsize;
 
+       void **callAddrPatchPos=0;
+       u1 *jmpInstrPos=0;
+       void **jmpInstrPatchPos=0;
+
        /* mark start of dump memory area */
 
        dumpsize = dump_size();
@@ -3801,7 +3874,10 @@ u1 *createnativestub(functionptr f, methodinfo *m)
        inlining_setup(m, id);
        reg_setup(m, rd, id);
 
+       /* set some required varibles which are normally set by codegen_setup */
+       cd->mcodebase = s;
        cd->mcodeptr = s;
+       cd->clinitrefs = NULL;
 
     descriptor2types(m);                /* set paramcount and paramtypes      */
 
@@ -3810,34 +3886,32 @@ u1 *createnativestub(functionptr f, methodinfo *m)
        if (m->flags & ACC_STATIC) {
                /* if class isn't yet initialized, do it */
                if (!m->class->initialized) {
-                       /* call helper function which patches this code */
-                       x86_64_mov_imm_reg(cd, (u8) m->class, REG_ITMP1);
-                       x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP2);
-                       x86_64_call_reg(cd, REG_ITMP2);
+                       codegen_addclinitref(cd, cd->mcodeptr, m->class);
                }
        }
 
-       if (runverbose) {
-               s4 p, l, s1;
 
-               x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
+       x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
 
-               x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
-               x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
-               x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
-               x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
-               x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
-               x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
+       x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
 
-               x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
-               x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
-               x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
-               x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
+       x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
+       x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
+       x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
+       x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
 /*             x86_64_movq_reg_membase(cd, rd->argfltregs[4], REG_SP, 11 * 8); */
 /*             x86_64_movq_reg_membase(cd, rd->argfltregs[5], REG_SP, 12 * 8); */
 /*             x86_64_movq_reg_membase(cd, rd->argfltregs[6], REG_SP, 13 * 8); */
 /*             x86_64_movq_reg_membase(cd, rd->argfltregs[7], REG_SP, 14 * 8); */
 
+       if (runverbose) {
+               s4 p, l, s1;
+
                /* show integer hex code for float arguments */
                for (p = 0, l = 0; p < m->paramcount; p++) {
                        if (IS_FLT_DBL_TYPE(m->paramtypes[p])) {
@@ -3852,27 +3926,44 @@ u1 *createnativestub(functionptr f, methodinfo *m)
 
                x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1);
                x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 8);
-               x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
+               x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
                x86_64_call_reg(cd, REG_ITMP1);
+       }
+/* call method to resolve native function if needed */
+#ifndef STATIC_CLASSPATH
+       if (f==0) { /* only if not already resolved */
+               x86_64_jmp_imm(cd,0);
+               jmpInstrPos=cd->mcodeptr-4; /*needed to patch a jump over this block*/
+               x86_64_mov_imm_reg(cd,(u8)m,rd->argintregs[0]);
+               x86_64_mov_imm_reg(cd,0,rd->argintregs[1]);
+               callAddrPatchPos=cd->mcodeptr-8; /* at this position the place is specified where the native function adress should be patched into*/
+               x86_64_mov_imm_reg(cd,0,rd->argintregs[2]);
+               jmpInstrPatchPos=cd->mcodeptr-8;
+               x86_64_mov_imm_reg(cd,jmpInstrPos,rd->argintregs[3]);
+               x86_64_mov_imm_reg(cd,(s8)codegen_resolve_native,REG_ITMP1);
+               x86_64_call_reg(cd,REG_ITMP1);
+               *(jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-1; /*=opcode jmp_imm size*/
+       }
+#endif
 
-               x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
-               x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
-               x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
-               x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
-               x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
-               x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
-
-               x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
-               x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
-               x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
-               x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
+       x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
+       x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
+       x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
+       x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
+       x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
+       x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
+
+       x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
+       x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
+       x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
+       x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
 /*             x86_64_movq_membase_reg(cd, REG_SP, 11 * 8, rd->argfltregs[4]); */
 /*             x86_64_movq_membase_reg(cd, REG_SP, 12 * 8, rd->argfltregs[5]); */
 /*             x86_64_movq_membase_reg(cd, REG_SP, 13 * 8, rd->argfltregs[6]); */
 /*             x86_64_movq_membase_reg(cd, REG_SP, 14 * 8, rd->argfltregs[7]); */
 
-               x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
-       }
+       x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
+       
 
 #if 0
        x86_64_alu_imm_reg(cd, X86_64_SUB, 7 * 8, REG_SP);    /* keep stack 16-byte aligned */
@@ -3941,6 +4032,10 @@ u1 *createnativestub(functionptr f, methodinfo *m)
        x86_64_mov_imm_reg(cd, (u8) &env, rd->argintregs[0]);
 
        x86_64_mov_imm_reg(cd, (u8) f, REG_ITMP1);
+#ifndef STATIC_CLASSPATH
+       if (f==0)
+               (*callAddrPatchPos)=cd->mcodeptr-8;
+#endif
        x86_64_call_reg(cd, REG_ITMP1);
 
        /* remove stackframe if there is one */
@@ -4016,6 +4111,46 @@ u1 *createnativestub(functionptr f, methodinfo *m)
        x86_64_mov_imm_reg(cd, (s8) asm_handle_nat_exception, REG_ITMP3);
        x86_64_jmp_reg(cd, REG_ITMP3);
 
+       {
+               u1          *xcodeptr;
+               clinitref   *cref;
+               codegendata *tmpcd;
+               u1           xmcode;
+               u4           mcode;
+
+               tmpcd = DNEW(codegendata);
+
+               /* there can only be one clinit ref entry                             */
+               cref = cd->clinitrefs;
+
+               if (cref) {
+                       /* Get machine code which is patched back in later. A             */
+                       /* `call rel32' is 5 bytes long.                                  */
+                       xcodeptr = cd->mcodebase + cref->branchpos;
+                       xmcode = *xcodeptr;
+                       mcode = *((u4 *) (xcodeptr + 1));
+
+                       /* patch in `call rel32' to call the following code               */
+                       tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
+                       x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+                       /* Save current stack pointer into a temporary register.          */
+                       x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+                       /* Push machine code bytes to patch onto the stack.               */
+                       x86_64_push_imm(cd, (u1) xmcode);
+                       x86_64_push_imm(cd, (u4) mcode);
+
+                       x86_64_push_imm(cd, (u8) cref->class);
+
+                       /* Push previously saved stack pointer onto stack.                */
+                       x86_64_push_reg(cd, REG_ITMP1);
+
+                       x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
+                       x86_64_jmp_reg(cd, REG_ITMP1);
+               }
+       }
+
 #if 0
        {
                static int stubprinted;