* src/vm/jit/x86_64/codegen.c (codegen_emit PUTFIELDCONST, PUTSTATICCONST):
[cacao.git] / src / vm / jit / replace.h
index eb497607eb34eef04a52202ffd4b3c1859fd9a5b..752cd385f4c8f8a633638c33688272101c781511 100644 (file)
@@ -1,6 +1,6 @@
-/* vm/jit/replace.h - on-stack replacement of methods
+/* src/vm/jit/replace.h - on-stack replacement of methods
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Edwin Steiner
-
-   Changes:
-
-   $Id$
-
 */
 
 
 
 #include "config.h"
 #include "vm/types.h"
-#include "vm/method.h"
+
+#if !defined(ENABLE_REPLACEMENT)
+
+/*** macros for the codegens (disabled version) ************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd)
+#define REPLACEMENT_POINTS_RESET(cd, jd)
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr)
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
+#define REPLACEMENT_POINT_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#else /* defined(ENABLE_REPLACEMENT) */
+
+/* forward typedefs ***********************************************************/
+
+typedef struct rplalloc rplalloc;
+typedef struct rplpoint rplpoint;
+typedef struct sourcestate_t sourcestate_t;
+typedef struct sourceframe_t sourceframe_t;
+typedef union  replace_val_t replace_val_t;
+
 #include "arch.h"
 #include "md-abi.h"
 
+#include "vm/jit/reg.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/method.h"
+
+
 /*** structs *********************************************************/
 
-typedef struct rplalloc rplalloc;
+#define RPLALLOC_STACK  -1
+#define RPLALLOC_PARAM  -2
+#define RPLALLOC_SYNC   -3
 
 /* `rplalloc` is a compact struct for register allocation info        */
 
+/* XXX optimize this for space efficiency */
 struct rplalloc {
-       unsigned int index:16;  /* register index / stack slot offset     */
+       s4           index;     /* local index, -1 for stack slot         */
+       s4           regoff;    /* register index / stack slot offset     */
        unsigned int flags:4;   /* OR of (INMEMORY,...)                   */
-       int          type:4;    /* TYPE_... constant                      */
-       unsigned int next:1;    /* if true, switch to next local          */
+       unsigned int type:4;    /* TYPE_... constant                      */
 };
 
 #if INMEMORY > 0x08
 #error value of INMEMORY is too big to fit in rplalloc.flags
 #endif
 
+
+/* XXX what to do about overlapping rplpoints? */
+/* CAUTION: Do not change the numerical values. These are used as     */
+/*          indices into replace_normalize_type_map.                  */
+#define RPLPOINT_TYPE_STD     BBTYPE_STD
+#define RPLPOINT_TYPE_EXH     BBTYPE_EXH
+#define RPLPOINT_TYPE_SBR     BBTYPE_SBR
+#define RPLPOINT_TYPE_CALL    3
+#define RPLPOINT_TYPE_INLINE  4
+#define RPLPOINT_TYPE_RETURN  5
+#define RPLPOINT_TYPE_BODY    6
+
+#define RPLPOINT_FLAG_NOTRAP     0x01  /* rplpoint cannot be trapped */
+#define RPLPOINT_FLAG_COUNTDOWN  0x02  /* count down hits            */
+#define RPLPOINT_FLAG_ACTIVE     0x08  /* trap is active             */
+
+
+#if !defined(NDEBUG)
+#define RPLPOINT_CHECK(type)     , RPLPOINT_TYPE_##type
+#define RPLPOINT_CHECK_BB(bptr)  , (bptr)->type
+#else
+#define RPLPOINT_CHECK(type)
+#define RPLPOINT_CHECK_BB(bptr)
+#endif
+
+
 /* An `rplpoint` represents a replacement point in a compiled method  */
 
 struct rplpoint {
        u1          *pc;           /* machine code PC of this point       */
-       u1          *outcode;      /* pointer to replacement-out code     */
-       codeinfo    *code;         /* codeinfo this point belongs to      */
-       rplpoint    *target;       /* target of the replacement           */
-       u8           mcode;        /* saved maching code for patching     */
+       methodinfo  *method;       /* source method this point is in      */
+       rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
        rplalloc    *regalloc;     /* pointer to register index table     */
-       unsigned int regalloccount:24; /* number of local allocations     */
-       unsigned int type:4;           /* BBTYPE_... constant             */
+       s4           id;           /* id of the rplpoint within method    */
+       s4           callsize;     /* size of call code in bytes          */
+       unsigned int regalloccount:20; /* number of local allocations     */
+       unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
        unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
 };
 
-/* An `executionsstate` represents the state of a thread as it reached */
-/* an replacement point or is about to enter one.                      */
 
-struct executionstate {
-       u1           *pc;                               /* program counter */
-       u1           *sp;                   /* stack pointer within method */
-
-       u8            intregs[INT_REG_CNT];             /* register values */
-       u8            fltregs[FLT_REG_CNT];             /* register values */
+union replace_val_t {
+       s4             i;
+       s8             l;
+       ptrint         p;
+       struct {
+               u4 lo;
+               u4 hi;
+       }              words;
+       float          f;
+       double         d;
+       java_object_t *a;
 };
 
-/* `sourcestate` will probably only be used for debugging              */
 
-struct sourcestate {
-       u8           *javastack;
-       s4            javastackdepth;
+       u1           *ra;                /* return address / link register */
+struct sourceframe_t {
+       sourceframe_t *down;           /* source frame down the call chain */
+
+       methodinfo    *method;                  /* method this frame is in */
+       s4             id;
+       s4             type;
+
+       /* values */
+       replace_val_t  instance;
+
+       replace_val_t *javastack;                  /* values of stack vars */
+       u1            *javastacktype;              /*  types of stack vars */
+       s4             javastackdepth;             /* number of stack vars */
+
+       replace_val_t *javalocals;                 /* values of javalocals */
+       u1            *javalocaltype;              /*  types of javalocals */
+       s4             javalocalcount;             /* number of javalocals */
+
+       replace_val_t *syncslots;
+       s4             syncslotcount; /* XXX do we need more than one? */
 
-       u8           *javalocals;      /* indexed by (i*5 + type) */
-       s4            javalocalcount;
+       /* mapping info */
+       rplpoint      *fromrp;         /* rplpoint used to read this frame */
+       codeinfo      *fromcode;              /* code this frame was using */
+       rplpoint      *torp;          /* rplpoint this frame was mapped to */
+       codeinfo      *tocode;            /* code this frame was mapped to */
+
+       /* info for native frames */
+       stackframeinfo_t *sfi;      /* sfi for native frames, otherwise NULL */
+       s4             nativeframesize;    /* size (bytes) of native frame */
+       u1            *nativepc;
+       ptrint         nativesavint[INT_SAV_CNT]; /* XXX temporary */
+       double         nativesavflt[FLT_REG_CNT]; /* XXX temporary */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       ptrint         nativesavadr[ADR_SAV_CNT]; /* XXX temporary */
+#endif
+};
+
+#define REPLACE_IS_NATIVE_FRAME(frame)  ((frame)->sfi != NULL)
+#define REPLACE_IS_JAVA_FRAME(frame)    ((frame)->sfi == NULL)
 
-       u8            savedintregs[INT_SAV_CNT + 1]; /* XXX */
-       u8            savedfltregs[FLT_SAV_CNT + 1]; /* XXX */
 
-       u8           *syncslots;
-       s4            syncslotcount;
+struct sourcestate_t {
+       sourceframe_t *frames;    /* list of source frames, from bottom up */
 };
 
+
+/*** macros for the codegens *******************************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd)                              \
+    if (!replace_create_replacement_points(jd))                      \
+        return false;                                                \
+    (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINTS_RESET(cd, jd)                             \
+    (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)                      \
+    if ((bptr)->bitflags & BBFLAG_REPLACEMENT)                       \
+        codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
+
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr)                     \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
+
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)                      \
+    codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
+
+#define REPLACEMENT_POINT_RETURN(cd, iptr)                           \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
+
+#define REPLACEMENT_POINT_INVOKE(cd, iptr)                           \
+    codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd,  iptr)                   \
+    if (iptr->opc != ICMD_BUILTIN)                                   \
+        cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+                    - (ptrint) cd->replacementpoint[-1].pc;
+
+
+/*** macros for the codegens (for GC) **********************************/
+
+#if defined(ENABLE_GC_CACAO)
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)                    \
+       codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)             \
+       if (iptr->opc == ICMD_BUILTIN)                                   \
+               cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+                                       - (ptrint) cd->replacementpoint[-1].pc;
+
+#else /* defined(ENABLE_GC_CACAO) */
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#endif /* defined(ENABLE_GC_CACAO) */
+
+
 /*** prototypes ********************************************************/
 
-bool replace_create_replacement_points(codeinfo *code,registerdata *rd);
+bool replace_create_replacement_points(jitdata *jd);
 void replace_free_replacement_points(codeinfo *code);
 
-void replace_activate_replacement_point(rplpoint *rp,rplpoint *target);
-void replace_deactivate_replacement_point(rplpoint *rp);
-void replace_activate(codeinfo *code,codeinfo *target);
+void replace_activate_replacement_points(codeinfo *code, bool mappable);
+void replace_deactivate_replacement_points(codeinfo *code);
 
-void replace_me(rplpoint *rp,executionstate *es);
+bool replace_me_wrapper(u1 *pc, void *context);
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
 void replace_show_replacement_points(codeinfo *code);
-void replace_replacement_point_println(rplpoint *rp);
-void replace_executionstate_println(executionstate *es,codeinfo *code);
-void replace_sourcestate_println(sourcestate *ss);
+void replace_replacement_point_println(rplpoint *rp, int depth);
+void replace_sourcestate_println(sourcestate_t *ss);
+void replace_sourcestate_println_short(sourcestate_t *ss);
+void replace_source_frame_println(sourceframe_t *frame);
 #endif
 
 /* machine dependent functions (code in ARCH_DIR/md.c) */
 
 #if defined(ENABLE_JIT)
-void md_patch_replacement_point(rplpoint *rp);
+void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
 #endif
 
-#endif
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+#endif /* _REPLACE_H */
+
 
 /*
  * These are local overrides for various environment variables in Emacs.