-/* An `rplpoint` represents a replacement point in a compiled method */
+/* src/vm/jit/replace.h - on-stack replacement of methods
+
+ 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
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
#ifndef _REPLACE_H
#define _REPLACE_H
#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)
+
+#else /* defined(ENABLE_REPLACEMENT) */
+
+/* forward typedefs ***********************************************************/
+
+typedef struct rplalloc rplalloc;
+typedef struct rplpoint rplpoint;
+typedef struct executionstate_t executionstate_t;
+typedef struct sourcestate_t sourcestate_t;
+typedef struct sourceframe_t sourceframe_t;
+typedef struct replace_safestack_t replace_safestack_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"
+
+
+/* alignment for the safe stack used during replacement */
+
+#define REPLACE_STACK_ALIGNMENT 16
+
+/* the size of the safe stack we use during replacement */
+/* Must be a multiple of REPLACE_STACK_ALIGNMENT. */
+
+#define REPLACE_SAFESTACK_SIZE 16384 /* bytes */
+
+
+/*** structs *********************************************************/
+
+#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 {
+ s4 index; /* local index, -1 for stack slot */
+ s4 regoff; /* register index / stack slot offset */
+ unsigned int flags:4; /* OR of (INMEMORY,...) */
+ 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 {
- void *pc; /* machine code PC of this point */
- rplpoint *hashlink; /* chain to next rplpoint in hash */
- codeinfo *code; /* codeinfo this point belongs to */
- rplpoint *target; /* target of the replacement */
+ u1 *pc; /* machine code PC of this point */
+ 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 */
+ 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 */
+};
+
- u1 regalloc[1]; /* VARIABLE LENGTH! */
+union replace_val_t {
+ s4 i;
+ s8 l;
+ ptrint p;
+ struct {
+ u4 lo;
+ u4 hi;
+ } words;
+ float f;
+ double d;
+ java_object_t *a;
};
+
/* An `executionsstate` represents the state of a thread as it reached */
/* an replacement point or is about to enter one. */
-#define MD_EXCSTATE_NREGS 32
-#define MD_EXCSTATE_NCALLEESAVED 8
+struct executionstate_t {
+ u1 *pc; /* program counter */
+ u1 *sp; /* stack pointer within method */
+ u1 *pv; /* procedure value. NULL means */
+ /* search the AVL tree */
-struct executionstate {
- u1 *pc;
- u8 regs[MD_EXCSTATE_NREGS];
- u8 savedregs[MD_EXCSTATE_NCALLEESAVED]; /* or read from frame */
+ ptrint intregs[INT_REG_CNT]; /* register values */
+ double fltregs[FLT_REG_CNT]; /* register values */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ ptrint adrregs[ADR_REG_CNT]; /* register values */
+#endif
- u1 *frame;
-
- java_objectheader *locked; /* XXX maybe just leave it in frame? */
+ codeinfo *code; /* codeinfo corresponding to the pv */
};
-/* `sourcestate` will probably only be used for debugging */
-struct sourcestate {
- u8 *javastack;
- s4 javastackdepth;
+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 */
- u8 javalocals;
- s4 javalocalscount;
+ replace_val_t *syncslots;
+ s4 syncslotcount; /* XXX do we need more than one? */
+
+ /* 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 *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)
+
+
+struct sourcestate_t {
+ sourceframe_t *frames; /* list of source frames, from bottom up */
+};
+
+
+/* replace_safestack_t *********************************************************
+
+ This struct is used to allocate a safe stack area to be used during the
+ last phase of replacement. It also contains copies of all data needed
+ during this phase. (The data cannot be kept in normal variables, as
+ the C stack may be destroyed during replacement.)
+
+ CAUTION: Do not change the layout of this struct! The assembler code
+ depends on the order of fields. (`stack` must be first,
+ directly followed by `es`.)
+
+*******************************************************************************/
+
+struct replace_safestack_t {
+ u1 stack[REPLACE_SAFESTACK_SIZE];
+ executionstate_t es;
+ sourcestate_t *ss;
+ u1 *mem; /* start of the allocated memory chunk */
+ s4 dumpsize;
+};
+
+
+/*** 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;
+
+/*** prototypes ********************************************************/
+
+bool replace_create_replacement_points(jitdata *jd);
+void replace_free_replacement_points(codeinfo *code);
+
+void replace_activate_replacement_points(codeinfo *code, bool mappable);
+void replace_deactivate_replacement_points(codeinfo *code);
+
+bool replace_me_wrapper(u1 *pc);
+
+void replace_me(rplpoint *rp,executionstate_t *es);
+
+#if !defined(NDEBUG)
+void replace_show_replacement_points(codeinfo *code);
+void replace_replacement_point_println(rplpoint *rp, int depth);
+void replace_executionstate_println(executionstate_t *es);
+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(codeinfo *code, s4 index, rplpoint *rp,
+ u1 *savedmcode);
#endif
-/* vim: noet ts=4 sw=4
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+#endif /* _REPLACE_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
*/