* src/vm/jit/powerpc/md.c (md_patch_replacement_point): Added.
[cacao.git] / src / vm / jit / alpha / codegen.c
index 311651eeb920de107ea599953954fba1fb2b87cd..5ac5add885f650580b394e4fe8dae0fce8df3d86 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
 
-   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
+   Copyright (C) 1996-2005, 2006 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.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Andreas Krall
             Reinhard Grafl
    Changes: Joseph Wenninger
             Christian Thalinger
             Christian Ullrich
+            Edwin Steiner
 
-   $Id: codegen.c 3719 2005-11-19 02:04:39Z edwin $
+   $Id: codegen.c 4653 2006-03-18 04:14:17Z edwin $
 
 */
 
 
+#include "config.h"
+
+#include <assert.h>
 #include <stdio.h>
 
-#include "config.h"
 #include "vm/types.h"
 
 #include "md.h"
 #include "md-abi.h"
-#include "md-abi.inc"
 
 #include "vm/jit/alpha/arch.h"
 #include "vm/jit/alpha/codegen.h"
 
-#include "cacao/cacao.h"
 #include "native/jni.h"
 #include "native/native.h"
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/loader.h"
+#include "vm/options.h"
 #include "vm/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/vm.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/dseg.h"
 #include "vm/jit/jit.h"
-
-#if defined(LSRA)
-# include "vm/jit/lsra.h"
-# include "vm/jit/lsra.inc"
-#endif
-
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/reg.inc"
+#include "vm/jit/replace.h"
+
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
 
 
 /* codegen *********************************************************************
@@ -91,6 +93,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
        builtintable_entry *bte;
        methoddesc         *md;
+       rplpoint           *replacementpoint;
 
        /* prevent compiler warnings */
 
@@ -113,10 +116,8 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        parentargs_base = rd->memuse + savedregs_num;
 
 #if defined(USE_THREADS)           /* space to save argument of monitor_enter */
-
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
                parentargs_base++;
-
 #endif
 
        /* create method header */
@@ -125,7 +126,6 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        (void) dseg_adds4(cd, parentargs_base * 8);             /* FrameSize      */
 
 #if defined(USE_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
@@ -133,16 +133,14 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        */
 
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_adds4(cd, (rd->memuse + 1) * 8);     /* IsSync         */
+               (void) dseg_adds4(cd, (rd->memuse + 1) * 8);        /* IsSync         */
        else
-
 #endif
-
-       (void) dseg_adds4(cd, 0);                               /* IsSync         */
+               (void) dseg_adds4(cd, 0);                           /* IsSync         */
                                               
        (void) dseg_adds4(cd, m->isleafmethod);                 /* IsLeaf         */
-       (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse);/* IntSave  */
-       (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse);/* FltSave  */
+       (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse);  /* IntSave        */
+       (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse);  /* FltSave        */
 
        dseg_addlinenumbertablesize(cd);
 
@@ -159,15 +157,12 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        
        /* initialize mcode variables */
        
-       mcodeptr = (s4 *) cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
-       MCODECHECK(128 + m->paramcount);
+       mcodeptr = (s4 *) cd->mcodeptr;
 
        /* create stack frame (if necessary) */
 
-       if (parentargs_base) {
+       if (parentargs_base)
                M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
-       }
 
        /* save return address and used callee saved registers */
 
@@ -243,7 +238,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                s1 = rd->memuse;
 
-               if (runverbose) {
+               if (opt_verbosecall) {
                        M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
 
                        for (p = 0; p < INT_ARG_CNT; p++)
@@ -259,9 +254,8 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                if (m->flags & ACC_STATIC) {
                        disp = dseg_addaddress(cd, m->class);
-                       M_ALD(REG_ITMP1, REG_PV, disp);
-                       M_AST(REG_ITMP1, REG_SP, s1 * 8);
-                       M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
+                       M_ALD(rd->argintregs[0], REG_PV, disp);
+                       M_AST(rd->argintregs[0], REG_SP, s1 * 8);
                        disp = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
                        M_ALD(REG_PV, REG_PV, disp);
                        M_JSR(REG_RA, REG_PV);
@@ -270,7 +264,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                } else {
                        M_BEQZ(rd->argintregs[0], 0);
-                       codegen_addxnullrefs(cd, mcodeptr);
+                       codegen_add_nullpointerexception_ref(cd, mcodeptr);
                        M_AST(rd->argintregs[0], REG_SP, s1 * 8);
                        disp = dseg_addaddress(cd, BUILTIN_monitorenter);
                        M_ALD(REG_PV, REG_PV, disp);
@@ -279,7 +273,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        M_LDA(REG_PV, REG_RA, disp);
                }
 
-               if (runverbose) {
+               if (opt_verbosecall) {
                        for (p = 0; p < INT_ARG_CNT; p++)
                                M_LLD(rd->argintregs[p], REG_SP, p * 8);
 
@@ -293,7 +287,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
        /* call trace function */
 
-       if (runverbose) {
+       if (opt_verbosecall) {
                M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
                M_AST(REG_RA, REG_SP, 1 * 8);
 
@@ -362,6 +356,8 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
        /* end of header generation */
 
+       replacementpoint = cd->code->rplpoints;
+
        /* walk through all basic blocks */
 
        for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
@@ -380,12 +376,20 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        }
                }
 
+               /* handle replacement points */
+
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+                       replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
+                       
+                       replacementpoint++;
+               }
+
                /* copy interface registers to their destination */
 
                src = bptr->instack;
                len = bptr->indepth;
                MCODECHECK(64+len);
-#ifdef LSRA
+#if defined(ENABLE_LSRA)
                if (opt_lsra) {
                while (src != NULL) {
                        len--;
@@ -434,7 +438,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                }
                                src = src->prev;
                        }
-#ifdef LSRA
+#if defined(ENABLE_LSRA)
                }
 #endif
 
@@ -463,7 +467,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                        var_to_reg_int(s1, src, REG_ITMP1);
                        M_BEQZ(s1, 0);
-                       codegen_addxnullrefs(cd, mcodeptr);
+                       codegen_add_nullpointerexception_ref(cd, mcodeptr);
                        break;
 
                /* constant operations ************************************************/
@@ -874,7 +878,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s2, src, REG_ITMP2);
                        d = reg_of_var(rd, iptr->dst, REG_RESULT);
                        M_BEQZ(s2, 0);
-                       codegen_addxdivrefs(cd, mcodeptr);
+                       codegen_add_arithmeticexception_ref(cd, mcodeptr);
 
                        M_MOV(s1, rd->argintregs[0]);
                        M_MOV(s2, rd->argintregs[1]);
@@ -896,7 +900,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s2, src, REG_ITMP2);
                        d = reg_of_var(rd, iptr->dst, REG_RESULT);
                        M_BEQZ(s2, 0);
-                       codegen_addxdivrefs(cd, mcodeptr);
+                       codegen_add_arithmeticexception_ref(cd, mcodeptr);
 
                        M_MOV(s1, rd->argintregs[0]);
                        M_MOV(s2, rd->argintregs[1]);
@@ -1897,7 +1901,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        M_LDA(REG_PV, REG_RA, -disp);
 
                        M_BEQZ(REG_RESULT, 0);
-                       codegen_addxstorerefs(cd, mcodeptr);
+                       codegen_add_arraystoreexception_ref(cd, mcodeptr);
 
                        var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
                        var_to_reg_int(s2, src->prev, REG_ITMP2);
@@ -2020,7 +2024,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
                                      /* op1 = type, val.a = field address            */
 
-                       if (!iptr->val.a) {
+                       if (iptr->val.a == NULL) {
                                disp = dseg_addaddress(cd, 0);
 
                                codegen_addpatchref(cd, mcodeptr,
@@ -2036,7 +2040,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                                disp = dseg_addaddress(cd, &(fi->value));
 
-                               if (!fi->class->initialized) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        codegen_addpatchref(cd, mcodeptr,
                                                                                PATCHER_clinit, fi->class, 0);
 
@@ -2078,7 +2082,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
                                      /* op1 = type, val.a = field address            */
 
-                       if (!iptr->val.a) {
+                       if (iptr->val.a == NULL) {
                                disp = dseg_addaddress(cd, 0);
 
                                codegen_addpatchref(cd, mcodeptr,
@@ -2093,7 +2097,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                                disp = dseg_addaddress(cd, &(fi->value));
 
-                               if (!fi->class->initialized) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        codegen_addpatchref(cd, mcodeptr,
                                                                                PATCHER_clinit, fi->class, 0);
 
@@ -2132,7 +2136,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                          /* op1 = type, val.a = field address (in    */
                                          /* following NOP)                           */
 
-                       if (!iptr[1].val.a) {
+                       if (iptr[1].val.a == NULL) {
                                disp = dseg_addaddress(cd, 0);
 
                                codegen_addpatchref(cd, mcodeptr,
@@ -2147,7 +2151,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        
                                disp = dseg_addaddress(cd, &(fi->value));
 
-                               if (!fi->class->initialized) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        codegen_addpatchref(cd, mcodeptr,
                                                                                PATCHER_clinit, fi->class, 0);
 
@@ -2183,7 +2187,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s1, src, REG_ITMP1);
                        gen_nullptr_check(s1);
 
-                       if (!iptr->val.a) {
+                       if (iptr->val.a == NULL) {
                                codegen_addpatchref(cd, mcodeptr,
                                                                        PATCHER_get_putfield,
                                                                        (unresolved_field *) iptr->target, 0);
@@ -2238,7 +2242,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                var_to_reg_flt(s2, src, REG_FTMP2);
                        }
 
-                       if (!iptr->val.a) {
+                       if (iptr->val.a == NULL) {
                                codegen_addpatchref(cd, mcodeptr,
                                                                        PATCHER_get_putfield,
                                                                        (unresolved_field *) iptr->target, 0);
@@ -2279,7 +2283,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s1, src, REG_ITMP1);
                        gen_nullptr_check(s1);
 
-                       if (!iptr[1].val.a) {
+                       if (iptr[1].val.a == NULL) {
                                codegen_addpatchref(cd, mcodeptr,
                                                                        PATCHER_get_putfield,
                                                                        (unresolved_field *) iptr[1].target, 0);
@@ -2320,6 +2324,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s1, src, REG_ITMP1);
                        M_INTMOVE(s1, REG_ITMP1_XPTR);
 
+#ifdef ENABLE_VERIFIER
                        if (iptr->val.a) {
                                codegen_addpatchref(cd, mcodeptr,
                                                                        PATCHER_athrow_areturn,
@@ -2328,6 +2333,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                if (opt_showdisassemble)
                                        M_NOP;
                        }
+#endif /* ENABLE_VERIFIER */
 
                        disp = dseg_addaddress(cd, asm_handle_exception);
                        M_ALD(REG_ITMP2, REG_PV, disp);
@@ -2894,6 +2900,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        var_to_reg_int(s1, src, REG_RESULT);
                        M_INTMOVE(s1, REG_RESULT);
 
+#ifdef ENABLE_VERIFIER
                        if (iptr->val.a) {
                                codegen_addpatchref(cd, mcodeptr,
                                                                        PATCHER_athrow_areturn,
@@ -2902,6 +2909,7 @@ bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                if (opt_showdisassemble)
                                        M_NOP;
                        }
+#endif /* ENABLE_VERIFIER */
                        goto nowperformreturn;
 
                case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
@@ -2921,7 +2929,7 @@ nowperformreturn:
                        
                        /* call trace function */
 
-                       if (runverbose) {
+                       if (opt_verbosecall) {
                                M_LDA(REG_SP, REG_SP, -3 * 8);
                                M_AST(REG_RA, REG_SP, 0 * 8);
                                M_LST(REG_RESULT, REG_SP, 1 * 8);
@@ -3173,13 +3181,13 @@ gen_method:
 
                                if (iptr->op1 == true) {
                                        M_BEQZ(REG_RESULT, 0);
-                                       codegen_addxexceptionrefs(cd, mcodeptr);
+                                       codegen_add_fillinstacktrace_ref(cd, mcodeptr);
                                }
                                break;
 
                        case ICMD_INVOKESPECIAL:
                                M_BEQZ(rd->argintregs[0], 0);
-                               codegen_addxnullrefs(cd, mcodeptr);
+                               codegen_add_nullpointerexception_ref(cd, mcodeptr);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
@@ -3383,12 +3391,12 @@ gen_method:
                                                  OFFSET(vftbl_t, interfacetablelength));
                                        M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
                                        M_BLEZ(REG_ITMP3, 0);
-                                       codegen_addxcastrefs(cd, mcodeptr);
+                                       codegen_add_classcastexception_ref(cd, mcodeptr);
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                                                                superindex * sizeof(methodptr*)));
                                        M_BEQZ(REG_ITMP3, 0);
-                                       codegen_addxcastrefs(cd, mcodeptr);
+                                       codegen_add_classcastexception_ref(cd, mcodeptr);
 
                                        if (!super)
                                                M_BR(s3);
@@ -3437,7 +3445,7 @@ gen_method:
                                        /*                              } */
                                        M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
                                        M_BEQZ(REG_ITMP3, 0);
-                                       codegen_addxcastrefs(cd, mcodeptr);
+                                       codegen_add_classcastexception_ref(cd, mcodeptr);
                                }
                                d = reg_of_var(rd, iptr->dst, s1);
 
@@ -3467,7 +3475,7 @@ gen_method:
                                M_LDA(REG_PV, REG_RA, -disp);
 
                                M_BEQZ(REG_RESULT, 0);
-                               codegen_addxcastrefs(cd, mcodeptr);
+                               codegen_add_classcastexception_ref(cd, mcodeptr);
 
                                var_to_reg_int(s1, src, REG_ITMP1);
                                d = reg_of_var(rd, iptr->dst, s1);
@@ -3627,7 +3635,7 @@ gen_method:
                        break;
 
                case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
-                                     /* op1 = dimension, val.a = array descriptor    */
+                                     /* op1 = dimension, val.a = class               */
 
                        /* check for negative sizes and copy sizes to stack if necessary  */
 
@@ -3648,11 +3656,12 @@ gen_method:
 
                        /* is patcher function set? */
 
-                       if (iptr->target) {
+                       if (iptr->val.a == NULL) {
                                disp = dseg_addaddress(cd, 0);
 
                                codegen_addpatchref(cd, mcodeptr,
-                                                                       (functionptr) iptr->target, iptr->val.a,
+                                                                       PATCHER_builtin_multianewarray,
+                                                                       (constant_classref *) iptr->target,
                                                                        disp);
 
                                if (opt_showdisassemble)
@@ -3670,7 +3679,7 @@ gen_method:
 
                        M_INTMOVE(REG_SP, rd->argintregs[2]);
 
-                       disp = dseg_addaddress(cd, (void *) BUILTIN_multianewarray);
+                       disp = dseg_addaddress(cd, BUILTIN_multianewarray);
                        M_ALD(REG_PV, REG_PV, disp);
                        M_JSR(REG_RA, REG_PV);
                        disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
@@ -3679,7 +3688,7 @@ gen_method:
                        /* check for exception before result assignment */
 
                        M_BEQZ(REG_RESULT, 0);
-                       codegen_addxexceptionrefs(cd, mcodeptr);
+                       codegen_add_fillinstacktrace_ref(cd, mcodeptr);
 
                        d = reg_of_var(rd, iptr->dst, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -3699,7 +3708,7 @@ gen_method:
        src = bptr->outstack;
        len = bptr->outdepth;
        MCODECHECK(64+len);
-#ifdef LSRA
+#if defined(ENABLE_LSRA)
        if (!opt_lsra) 
 #endif
        while (src) {
@@ -3730,349 +3739,112 @@ gen_method:
        } /* if (bptr -> flags >= BBREACHED) */
        } /* for basic block */
 
-       codegen_createlinenumbertable(cd);
-
-       {
-
-       s4 *xcodeptr = NULL;
-       branchref *bref;
-
-       /* generate ArithmeticException stubs */
-
-       for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1 *) mcodeptr - cd->mcodebase);
-
-               MCODECHECK(100);
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
-
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
-
-               } else {
-                       xcodeptr = mcodeptr;
-
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-                       M_ALD(rd->argintregs[2],
-                                 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-
-                       M_LDA(REG_SP, REG_SP, -1 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
-
-                       disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 1 * 8);
-
-                       disp = dseg_addaddress(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-       }
-
-       /* generate ArrayIndexOutOfBoundsException stubs */
-
-       xcodeptr = NULL;
-
-       for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1*) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1*) mcodeptr - cd->mcodebase);
-
-               MCODECHECK(100);
-
-               /* move index register into REG_ITMP1 */
-
-               M_MOV(bref->reg, REG_ITMP1);
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
-
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
-
-               } else {
-                       xcodeptr = mcodeptr;
-
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-
-                       if (m->isleafmethod)
-                               M_MOV(REG_RA, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
-
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-                       M_MOV(REG_ITMP1, rd->argintregs[4]);
-
-                       M_LDA(REG_SP, REG_SP, -2 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
-
-                       if (m->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
-
-                       disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                       if (m->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
-
-                       disp = dseg_addaddress(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-       }
-
-       /* generate ArrayStoreException stubs */
-
-       xcodeptr = NULL;
-       
-       for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1 *) mcodeptr - cd->mcodebase);
-
-               MCODECHECK(100);
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
-
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
-
-               } else {
-                       xcodeptr = mcodeptr;
-
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-                       M_ALD(rd->argintregs[2],
-                                 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-
-                       M_LDA(REG_SP, REG_SP, -1 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
-
-                       disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 1 * 8);
-
-                       disp = dseg_addaddress(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-       }
-
-       /* generate ClassCastException stubs */
-
-       xcodeptr = NULL;
-       
-       for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1 *) mcodeptr - cd->mcodebase);
-
-               MCODECHECK(100);
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
-
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
-
-               } else {
-                       xcodeptr = mcodeptr;
-
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-
-                       if (m->isleafmethod)
-                               M_MOV(REG_RA, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
-
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+       dseg_createlinenumbertable(cd);
 
-                       M_LDA(REG_SP, REG_SP, -2 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
 
-                       if (m->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
+       /* generate exception and patcher stubs */
 
-                       disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                       if (m->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
-
-                       disp = dseg_addaddress(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-       }
-
-       /* generate NullPointerException stubs */
-
-       xcodeptr = NULL;
-
-       for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1 *) mcodeptr - cd->mcodebase);
-
-               MCODECHECK(100);
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
-
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
+       {
+               exceptionref *eref;
+               patchref     *pref;
+               u4            mcode;
+               s4           *savedmcodeptr;
+               s4           *tmpmcodeptr;
 
-               } else {
-                       xcodeptr = mcodeptr;
+               savedmcodeptr = NULL;
 
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
+               /* generate exception stubs */
 
-                       if (m->isleafmethod)
-                               M_MOV(REG_RA, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
+               for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
+                       gen_resolvebranch((u1 *) cd->mcodebase + eref->branchpos, 
+                                                         eref->branchpos,
+                                                         (u1 *) mcodeptr - cd->mcodebase);
 
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+                       MCODECHECK(100);
 
-                       M_LDA(REG_SP, REG_SP, -2 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
+                       /* move index register into REG_ITMP1 */
 
-                       if (m->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
+                       /* Check if the exception is an
+                          ArrayIndexOutOfBoundsException.  If so, move index register
+                          into REG_ITMP1. */
 
-                       disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+                       if (eref->reg != -1)
+                               M_MOV(eref->reg, REG_ITMP1);
 
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+                       /* calcuate exception address */
 
-                       if (m->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
+                       M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
+                       /* move function to call into REG_ITMP3 */
 
-                       disp = dseg_addaddress(cd, asm_handle_exception);
+                       disp = dseg_addaddress(cd, eref->function);
                        M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-       }
-
-       /* generate exception check stubs */
 
-       xcodeptr = NULL;
+                       if (savedmcodeptr != NULL) {
+                               disp = savedmcodeptr - mcodeptr - 1;
+                               M_BR(disp);
 
-       for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
-               gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
-                                 bref->branchpos,
-                                                 (u1 *) mcodeptr - cd->mcodebase);
+                       } else {
+                               savedmcodeptr = mcodeptr;
 
-               MCODECHECK(100);
+                               M_MOV(REG_PV, rd->argintregs[0]);
+                               M_MOV(REG_SP, rd->argintregs[1]);
 
-               M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
+                               if (m->isleafmethod)
+                                       M_MOV(REG_RA, rd->argintregs[2]);
+                               else
+                                       M_ALD(rd->argintregs[2],
+                                                 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
 
-               if (xcodeptr != NULL) {
-                       disp = xcodeptr - mcodeptr - 1;
-                       M_BR(disp);
+                               M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+                               M_MOV(REG_ITMP1, rd->argintregs[4]);
 
-               } else {
-                       xcodeptr = mcodeptr;
+                               M_LDA(REG_SP, REG_SP, -2 * 8);
+                               M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
 
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-                       M_ALD(rd->argintregs[2],
-                                 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+                               if (m->isleafmethod)
+                                       M_AST(REG_RA, REG_SP, 1 * 8);
 
-                       M_LDA(REG_SP, REG_SP, -1 * 8);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
+                               M_MOV(REG_ITMP3, REG_PV);
+                               M_JSR(REG_RA, REG_PV);
+                               disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
 
-                       disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
-                       M_ALD(REG_PV, REG_PV, disp);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+                               M_MOV(REG_RESULT, REG_ITMP1_XPTR);
 
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+                               if (m->isleafmethod)
+                                       M_ALD(REG_RA, REG_SP, 1 * 8);
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 1 * 8);
+                               M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
+                               M_LDA(REG_SP, REG_SP, 2 * 8);
 
-                       disp = dseg_addaddress(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
+                               disp = dseg_addaddress(cd, asm_handle_exception);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_JMP(REG_ZERO, REG_ITMP3);
+                       }
                }
-       }
 
-       /* generate patcher stub call code */
 
-       {
-               patchref *pref;
-               u4        mcode;
-               s4       *tmpmcodeptr;
+               /* generate code patching stub call code */
 
                for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
                        /* check code segment size */
 
                        MCODECHECK(100);
 
-                       /* Get machine code which is patched back in later. The call is   */
-                       /* 1 instruction word long.                                       */
+                       /* Get machine code which is patched back in later. The
+                          call is 1 instruction word long. */
 
-                       xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
-                       mcode = *xcodeptr;
+                       savedmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
+                       mcode = *savedmcodeptr;
 
-                       /* patch in the call to call the following code (done at compile  */
-                       /* time)                                                          */
+                       /* Patch in the call to call the following code (done at
+                          compile time). */
 
                        tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
-                       mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
+                       mcodeptr    = savedmcodeptr;    /* set mcodeptr to patch position */
 
-                       M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
+                       M_BSR(REG_ITMP3, tmpmcodeptr - (savedmcodeptr + 1));
 
                        mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
 
@@ -4126,7 +3898,49 @@ gen_method:
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JMP(REG_ZERO, REG_ITMP3);
                }
-       }
+
+               /* generate replacement-out stubs */
+
+               {
+                       int i;
+
+                       replacementpoint = cd->code->rplpoints;
+                       for (i=0; i<cd->code->rplpointcount; ++i, ++replacementpoint) {
+                               /* check code segment size */
+
+                               MCODECHECK(100);
+
+                               /* note start of stub code */
+
+                               replacementpoint->outcode = (u1*) (ptrint)((u1*)mcodeptr - cd->mcodebase);
+
+                               /* make machine code for patching */
+
+                               tmpmcodeptr = mcodeptr;
+                               mcodeptr = (s4*) &(replacementpoint->mcode);
+
+                               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
+                               M_BR(disp);
+
+                               mcodeptr = tmpmcodeptr;
+
+                               /* create stack frame */
+
+                               M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
+
+                               /* push address of `rplpoint` struct */
+
+                               disp = dseg_addaddress(cd, replacementpoint);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_AST(REG_ITMP3, REG_SP, 0 * 8);
+
+                               /* jump to replacement function */
+
+                               disp = dseg_addaddress(cd, asm_replacement_out);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_JMP(REG_ZERO, REG_ITMP3);
+                       }
+               }
        }
 
        codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
@@ -4143,26 +3957,45 @@ gen_method:
        
 *******************************************************************************/
 
-#define COMPSTUBSIZE    3
+#define COMPILERSTUB_DATASIZE    2 * SIZEOF_VOID_P
+#define COMPILERSTUB_CODESIZE    3 * 4
 
-functionptr createcompilerstub(methodinfo *m)
+#define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
+
+
+u1 *createcompilerstub(methodinfo *m)
 {
-       u8 *s = CNEW(u8, COMPSTUBSIZE);     /* memory to hold the stub            */
-       s4 *mcodeptr = (s4 *) s;            /* code generation pointer            */
+       u1     *s;                          /* memory to hold the stub            */
+       ptrint *d;
+       s4     *mcodeptr;                   /* code generation pointer            */
+
+       s = CNEW(u1, COMPILERSTUB_SIZE);
+
+       /* set data pointer and code pointer */
+
+       d = (ptrint *) s;
+       s = s + COMPILERSTUB_DATASIZE;
+
+       mcodeptr = (s4 *) s;
        
-                                           /* code for the stub                  */
-       M_ALD(REG_PV, REG_PV, 16);          /* load pointer to the compiler       */
-       M_JMP(0, REG_PV);                   /* jump to the compiler, return address
-                                              in reg 0 is used as method pointer */
-       s[1] = (ptrint) m;                  /* literals to be adressed            */
-       s[2] = (ptrint) asm_call_jit_compiler; /* jump directly via PV from above */
-
-#if defined(STATISTICS)
+       /* Store the methodinfo* in the same place as in the methodheader
+          for compiled methods. */
+
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+
+       /* code for the stub */
+
+       M_ALD(REG_ITMP1, REG_PV, -1 * 8);   /* load methodinfo pointer            */
+       M_ALD(REG_PV, REG_PV, -2 * 8);      /* load pointer to the compiler       */
+       M_JMP(REG_ZERO, REG_PV);            /* jump to the compiler               */
+
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               count_cstub_len += COMPSTUBSIZE * 8;
+               count_cstub_len += COMPILERSTUB_SIZE;
 #endif
 
-       return (functionptr) s;
+       return s;
 }
 
 
@@ -4172,8 +4005,8 @@ functionptr createcompilerstub(methodinfo *m)
 
 *******************************************************************************/
 
-functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
-                                                        registerdata *rd, methoddesc *nmd)
+u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
+                                        registerdata *rd, methoddesc *nmd)
 {
        s4         *mcodeptr;               /* code generation pointer            */
        s4          stackframesize;         /* size of stackframe if needed       */
@@ -4215,8 +4048,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        /* initialize mcode variables */
        
-       mcodeptr = (s4 *) cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+       mcodeptr = (s4 *) cd->mcodeptr;
 
 
        /* generate stub code */
@@ -4227,7 +4059,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        /* call trace function */
 
-       if (runverbose) {
+       if (opt_verbosecall) {
                /* save integer argument registers */
 
                for (i = 0, j = 1; i < md->paramcount && i < INT_ARG_CNT; i++) {
@@ -4288,7 +4120,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        funcdisp = dseg_addaddress(cd, f);
 
-#if !defined(ENABLE_STATICVM)
+#if !defined(WITH_STATIC_CLASSPATH)
        if (f == NULL) {
                codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
 
@@ -4403,7 +4235,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        /* put env into first argument register */
 
-       disp = dseg_addaddress(cd, &env);
+       disp = dseg_addaddress(cd, _Jv_env);
        M_ALD(rd->argintregs[0], REG_PV, disp);
 
        /* do the native function call */
@@ -4431,7 +4263,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        /* call finished trace */
 
-       if (runverbose) {
+       if (opt_verbosecall) {
                /* just restore the value we need, don't care about the other */
 
                if (IS_INT_LNG_TYPE(md->returntype.type))
@@ -4499,31 +4331,32 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        {
                patchref *pref;
-               s4       *xcodeptr;
                u4        mcode;
+               s4       *savedmcodeptr;
                s4       *tmpmcodeptr;
 
-               /* there can only be one <clinit> ref entry                           */
+               /* there can only be one <clinit> ref entry */
+
                pref = cd->patchrefs;
 
                for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
-                       /* Get machine code which is patched back in later. The call is   */
-                       /* 1 instruction word long.                                       */
+                       /* Get machine code which is patched back in later. The
+                          call is 1 instruction word long. */
 
-                       xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
-                       mcode = (u4) *xcodeptr;
+                       savedmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
+                       mcode = (u4) *savedmcodeptr;
 
                        /* patch in the call to call the following code (done at compile  */
                        /* time)                                                          */
 
                        tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
-                       mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
+                       mcodeptr    = savedmcodeptr;    /* set mcodeptr to patch position */
 
-                       M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
+                       M_BSR(REG_ITMP3, tmpmcodeptr - (savedmcodeptr + 1));
 
                        mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
 
-                       /* create stack frame                                             */
+                       /* create stack frame */
 
                        M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
 
@@ -4577,7 +4410,7 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
 
        codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
 
-       return m->entrypoint;
+       return cd->code->entrypoint;
 }
 
 
@@ -4592,4 +4425,5 @@ functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */