/* src/vm/jit/replace.c - 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdlib.h>
#include "arch.h"
+#include "md.h"
#if defined(ENABLE_GC_CACAO)
# include "mm/cacao-gc/gc.h"
#include "mm/memory.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/disass.h"
+#include "vm/jit/executionstate.h"
#include "vm/jit/jit.h"
-#include "vm/jit/md.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/replace.h"
#include "vm/jit/show.h"
#if !defined(NDEBUG)
static void java_value_print(s4 type, replace_val_t value);
-static void replace_stackframeinfo_println(stackframeinfo *sfi);
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
#endif
#if !defined(NDEBUG)
m = code->m;
- /* set codeinfo flags */
-
- if (jd->isleafmethod)
- CODE_SETFLAG_LEAFMETHOD(code);
-
/* in instance methods, we may need a rplpoint at the method entry */
#if defined(REPLACE_PATCH_DYNAMIC_CALL)
/* read the return address */
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (CODE_IS_LEAFMETHOD(es->code))
+ if (code_is_leafmethod(es->code))
ra = (u1*) (ptrint) es->intregs[REPLACE_REG_RA];
else
#endif
ra = md_stacktrace_get_returnaddress(es->sp,
SIZE_OF_STACKSLOT * es->code->stackframesize);
- DOLOG( printf("return address: %p\n", (void*)ra); );
+ DOLOG( printf("RA = %p\n", (void*)ra); );
assert(ra);
#if defined(REPLACE_RA_TOP_OF_FRAME)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!CODE_IS_LEAFMETHOD(es->code))
+ if (!code_is_leafmethod(es->code))
#endif
es->intregs[REPLACE_REG_RA] = *--basesp;
#endif /* REPLACE_RA_TOP_OF_FRAME */
#if defined(REPLACE_RA_LINKAGE_AREA)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!CODE_IS_LEAFMETHOD(es->code))
+ if (!code_is_leafmethod(es->code))
#endif
es->intregs[REPLACE_REG_RA] = basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
#endif /* REPLACE_RA_LINKAGE_AREA */
/* find the new codeinfo */
pv = md_codegen_get_pv_from_pc(ra);
-
DOLOG( printf("PV = %p\n", (void*) pv); );
- if (pv == NULL) /* XXX can this really happen? */
- return NULL;
-
- code = *(codeinfo **)(pv + CodeinfoPointer);
-
+ code = code_get_codeinfo_for_pv(pv);
DOLOG( printf("CODE = %p\n", (void*) code); );
/* return NULL if we reached native code */
(void*) *mpp, (void*)entrypoint); );
#if !defined(NDEBUG)
- oldcode = *(codeinfo **)((u1*)(*mpp) + CodeinfoPointer);
- newcode = *(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer);
+ oldcode = code_get_codeinfo_for_pv(*mpp);
+ newcode = code_get_codeinfo_for_pv(entrypoint);
DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
method_println(oldcode->m);
u1 *entrypoint;
};
-#define CODEINFO_OF_CODE(entrypoint) \
- (*(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer))
-
-#define METHOD_OF_CODE(entrypoint) \
- (CODEINFO_OF_CODE(entrypoint)->m)
-
void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
{
vftbl_t *vftbl = c->vftbl;
if (vftbl != NULL
&& vftbl->vftbllength > pd->m->vftblindex
&& vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror
- && METHOD_OF_CODE(vftbl->table[pd->m->vftblindex]) == pd->m)
+ && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
{
replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
}
sourceframe_t *callerframe,
sourceframe_t *calleeframe)
{
- u1 *patchpos;
- methodptr entrypoint;
- methodptr oldentrypoint;
- bool atentry;
- stackframeinfo sfi;
- codeinfo *calleecode;
- methodinfo *calleem;
- java_object_t *obj;
- vftbl_t *vftbl;
+ u1 *patchpos;
+ methodptr entrypoint;
+ methodptr oldentrypoint;
+ bool atentry;
+ void *pv;
+ codeinfo *calleecode;
+ methodinfo *calleem;
+ java_object_t *obj;
+ vftbl_t *vftbl;
assert(ra);
assert(callerframe->down == calleeframe);
/* get the position to patch, in case it was a statically bound call */
- sfi.pv = callerframe->fromcode->entrypoint;
- patchpos = md_get_method_patch_address(ra, &sfi, NULL);
+ pv = callerframe->fromcode->entrypoint;
+ patchpos = md_jit_method_patch_address(pv, ra, NULL);
if (patchpos == NULL) {
/* the call was dispatched dynamically */
obj = calleeframe->instance.a;
vftbl = obj->vftbl;
- assert(vftbl->class->vftbl == vftbl);
+ assert(vftbl->clazz->vftbl == vftbl);
- DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->class); );
+ DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
}
#if defined(REPLACE_RA_TOP_OF_FRAME)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!CODE_IS_LEAFMETHOD(calleecode))
+ if (!code_is_leafmethod(calleecode))
#endif
*--basesp = (ptrint) ra;
#endif /* REPLACE_RA_TOP_OF_FRAME */
#if defined(REPLACE_RA_LINKAGE_AREA)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!CODE_IS_LEAFMETHOD(calleecode))
+ if (!code_is_leafmethod(calleecode))
#endif
basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
#endif /* REPLACE_RA_LINKAGE_AREA */
static void replace_pop_native_frame(executionstate_t *es,
sourcestate_t *ss,
- stackframeinfo *sfi)
+ stackframeinfo_t *sfi)
{
sourceframe_t *frame;
codeinfo *code;
# endif
#endif
- /* restore pv, pc, and sp */
-
- if (sfi->pv == NULL) {
- /* frame of a native function call */
- es->pv = md_codegen_get_pv_from_pc(sfi->ra);
- }
- else {
- es->pv = sfi->pv;
- }
- es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
- es->sp = sfi->sp;
-
- /* find the new codeinfo */
-
- DOLOG( printf("PV = %p\n", (void*) es->pv); );
+ /* restore codeinfo of the native stub */
- assert(es->pv != NULL);
+ code = code_get_codeinfo_for_pv(sfi->pv);
- code = *(codeinfo **)(es->pv + CodeinfoPointer);
+ /* restore sp, pv, pc and codeinfo of the parent method */
- DOLOG( printf("CODE = %p\n", (void*) code); );
-
- es->code = code;
+ /* XXX michi: use this instead:
+ es->sp = sfi->sp + code->stackframesize; */
+ es->sp = sfi->sp + (*(s4 *) (sfi->pv + FrameSize));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ es->sp += SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+ es->pv = md_codegen_get_pv_from_pc(sfi->ra);
+ es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
+ es->code = code_get_codeinfo_for_pv(es->pv);
}
ss->frames = frame->down;
+ /* skip sp for the native stub */
+
+ es->sp -= (*(s4 *) (frame->sfi->pv + FrameSize));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+
/* assert that the native frame has not moved */
assert(es->sp == frame->sfi->sp);
*******************************************************************************/
sourcestate_t *replace_recover_source_state(rplpoint *rp,
- stackframeinfo *sfi,
+ stackframeinfo_t *sfi,
executionstate_t *es)
{
sourcestate_t *ss;
while (rp || sfi) {
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
/* if we are not at a replacement point, it is a native frame */
replace_push_activation_record(es, rp, prevframe, ss->frames);
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
}
rp = ss->frames->torp;
replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
if (rp->type == RPLPOINT_TYPE_CALL) {
parent = NULL;
static void replace_me(rplpoint *rp, executionstate_t *es)
{
- stackframeinfo *sfi;
+ stackframeinfo_t *sfi;
sourcestate_t *ss;
sourceframe_t *frame;
- s4 dumpsize;
codeinfo *origcode;
rplpoint *origrp;
#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
threadobject *thread;
#endif
+ int32_t dumpmarker;
origcode = es->code;
origrp = rp;
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
- /* get the stackframeinfo for the current thread */
+ /* Get the stackframeinfo for the current thread. */
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* recover source state */
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
}
if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
+#if !defined(NDEBUG)
+ executionstate_sanity_check(context);
+#endif
+
/* set codeinfo pointer in execution state */
es.code = code;
/* read execution state from current context */
- md_replace_executionstate_read(&es, context);
+ md_executionstate_read(&es, context);
DOLOG( printf("REPLACEMENT READ: ");
- replace_executionstate_println(&es); );
+ executionstate_println(&es); );
/* do the actual replacement */
/* write execution state to current context */
- md_replace_executionstate_write(&es, context);
+ md_executionstate_write(&es, context);
DOLOG( printf("REPLACEMENT WRITE: ");
- replace_executionstate_println(&es); );
+ executionstate_println(&es); );
/* new code is entered after returning */
#if defined(ENABLE_GC_CACAO)
void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
{
- stackframeinfo *sfi;
+ stackframeinfo_t *sfi;
executionstate_t *es;
sourcestate_t *ss;
- /* get the stackframeinfo of this thread */
+ /* Get the stackframeinfo of this thread. */
+
assert(thread == THREADOBJECT);
- sfi = STACKFRAMEINFO;
+
+ sfi = threads_get_current_stackframeinfo();
/* create the execution state */
es = DNEW(executionstate_t);
#endif
-/* replace_executionstate_println **********************************************
-
- Print execution state
-
- IN:
- es...............the execution state to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_executionstate_println(executionstate_t *es)
-{
- int i;
- int slots;
- stackslot_t *sp;
- int extraslots;
-
- if (!es) {
- printf("(executionstate_t *)NULL\n");
- return;
- }
-
- printf("executionstate_t:\n");
- printf("\tpc = %p",(void*)es->pc);
- printf(" sp = %p",(void*)es->sp);
- printf(" pv = %p\n",(void*)es->pv);
-#if defined(ENABLE_DISASSEMBLER)
- for (i=0; i<INT_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
-#if SIZEOF_VOID_P == 8
- printf("%-3s = %016llx",abi_registers_integer_name[i],(unsigned long long)es->intregs[i]);
-#else
- printf("%-3s = %08lx",abi_registers_integer_name[i],(unsigned long)es->intregs[i]);
-#endif
- if (i%4 == 3)
- printf("\n");
- }
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
- printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
- if (i%4 == 3)
- printf("\n");
- }
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
- printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
- if (i%4 == 3)
- printf("\n");
- }
-# endif
-#endif
-
- sp = (stackslot_t *) es->sp;
-
- extraslots = 2;
-
- if (es->code) {
- methoddesc *md = es->code->m->parseddesc;
- slots = es->code->stackframesize;
- extraslots = 1 + md->memuse;
- }
- else
- slots = 0;
-
-
- if (slots) {
- printf("\tstack slots(+%d) at sp:", extraslots);
- for (i=0; i<slots+extraslots; ++i) {
- if (i%4 == 0)
- printf("\n\t\t");
- printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
-#ifdef HAS_4BYTE_STACKSLOT
- printf("%08lx",(unsigned long)*sp++);
-#else
- printf("%016llx",(unsigned long long)*sp++);
-#endif
- printf("%c", (i >= slots) ? ')' : ' ');
- }
- printf("\n");
- }
-
- printf("\tcode: %p", (void*)es->code);
- if (es->code != NULL) {
- printf(" stackframesize=%d ", es->code->stackframesize);
- method_print(es->code->m);
- }
- printf("\n");
-
- printf("\n");
-}
-#endif
-
#if !defined(NDEBUG)
static void java_value_print(s4 type, replace_val_t value)
{
if (type == TYPE_ADR && value.a != NULL) {
obj = value.a;
putchar(' ');
- utf_display_printable_ascii_classname(obj->vftbl->class->name);
+ utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
- if (obj->vftbl->class == class_java_lang_String) {
+ if (obj->vftbl->clazz == class_java_lang_String) {
printf(" \"");
u = javastring_toutf(obj, false);
utf_display_printable_ascii(u);
if (REPLACE_IS_NATIVE_FRAME(frame)) {
printf("NATIVE (pc %p size %d) ",
- (void*)frame->nativepc, frame->nativeframesize);
+ (void*)frame->nativepc, frame->nativeframesize);
replace_stackframeinfo_println(frame->sfi);
continue;
}
#endif
#if !defined(NDEBUG)
-static void replace_stackframeinfo_println(stackframeinfo *sfi)
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
{
printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
(void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
(void*)sfi->ra, (void*)sfi->xpc);
- if (sfi->method)
- method_println(sfi->method);
+ if (sfi->code)
+ method_println(sfi->code->m);
else
printf("(nil)\n");
}
#endif
+
/*
* 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