X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fx86_64%2Fpatcher.c;h=81cc09e0e8bbc78583471327af0d14c9203634c0;hb=67da78971605bb8a2953a9f6d5a7862857049538;hp=61a328e0bd1f929e55477a2cb49b54153ba9ab36;hpb=f10dbf6366ebee691384961d8fef9cb3b1998009;p=cacao.git diff --git a/src/vm/jit/x86_64/patcher.c b/src/vm/jit/x86_64/patcher.c index 61a328e0b..81cc09e0e 100644 --- a/src/vm/jit/x86_64/patcher.c +++ b/src/vm/jit/x86_64/patcher.c @@ -1,9 +1,7 @@ /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions - 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, 2009 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -32,29 +30,21 @@ #include "vm/types.h" #include "vm/jit/x86_64/codegen.h" +#include "vm/jit/x86_64/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "native/native.h" +#include "native/native.hpp" -#include "vm/builtin.h" -#include "vm/exceptions.h" -#include "vm/initialize.h" +#include "vm/jit/builtin.hpp" +#include "vm/class.hpp" +#include "vm/field.hpp" +#include "vm/initialize.hpp" +#include "vm/options.h" +#include "vm/references.h" +#include "vm/resolve.hpp" -#include "vm/jit/patcher-common.h" -#include "vm/jit/stacktrace.h" - -#include "vmcore/class.h" -#include "vmcore/field.h" -#include "vmcore/options.h" -#include "vmcore/references.h" -#include "vm/resolve.h" - - -#define PATCH_BACK_ORIGINAL_MCODE \ - do { \ - *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \ - } while (0) +#include "vm/jit/patcher-common.hpp" /* patcher_patch_code ********************************************************** @@ -65,7 +55,23 @@ void patcher_patch_code(patchref_t *pr) { - PATCH_BACK_ORIGINAL_MCODE; + *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode; + md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE); +} + +/** + * Check if the trap instruction at the given PC is valid. + * + * @param pc Program counter. + * + * @return true if valid, false otherwise. + */ +bool patcher_is_valid_trap_instruction_at(void* pc) +{ + uint16_t mcode = *((uint16_t*) pc); + + // Check for the undefined instruction we use. + return (mcode == 0x0b0f); } @@ -95,23 +101,23 @@ void patcher_patch_code(patchref_t *pr) bool patcher_resolve_classref_to_classinfo(patchref_t *pr) { - constant_classref *cr; - intptr_t *datap; - classinfo *c; - - cr = (constant_classref *) pr->ref; - datap = (intptr_t *) pr->datap; + constant_classref* cr = (constant_classref*) pr->ref; + uintptr_t* datap = (uintptr_t*) pr->datap; - /* get the classinfo */ + // Resolve the class. + classinfo* c = resolve_classref_eager(cr); - if (!(c = resolve_classref_eager(cr))) + if (c == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; + // Patch the class. + *datap = (uintptr_t) c; - /* patch the classinfo pointer */ + // Synchronize data cache. + md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P); - *datap = (intptr_t) c; + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -128,25 +134,23 @@ bool patcher_resolve_classref_to_classinfo(patchref_t *pr) bool patcher_resolve_classref_to_vftbl(patchref_t *pr) { - constant_classref *cr; - intptr_t *datap; - classinfo *c; + constant_classref* cr = (constant_classref*) pr->ref; + uintptr_t* datap = (uintptr_t*) pr->datap; - /* get stuff from the stack */ + // Resolve the field. + classinfo* c = resolve_classref_eager(cr); - cr = (constant_classref *) pr->ref; - datap = (intptr_t *) pr->datap; - - /* get the fieldinfo */ - - if (!(c = resolve_classref_eager(cr))) + if (c == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; + // Patch super class' vftbl. + *datap = (uintptr_t) c->vftbl; - /* patch super class' vftbl */ + // Synchronize data cache. + md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P); - *datap = (intptr_t) c->vftbl; + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -162,31 +166,28 @@ bool patcher_resolve_classref_to_vftbl(patchref_t *pr) bool patcher_resolve_classref_to_flags(patchref_t *pr) { - constant_classref *cr; - int32_t *datap; - classinfo *c; - uint8_t *ra; - - cr = (constant_classref *) pr->ref; - datap = (int32_t *) pr->datap; - ra = (uint8_t *) pr->mpc; + constant_classref* cr = (constant_classref*) pr->ref; +/* int32_t* datap = (int32_t*) pr->datap; */ + uint8_t* ra = (uint8_t*) pr->mpc; - /* get the fieldinfo */ + // Resolve the field. + classinfo* c = resolve_classref_eager(cr); - if (!(c = resolve_classref_eager(cr))) + if (c == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; + ra += PATCHER_CALL_SIZE; - /* if we show disassembly, we have to skip the nop's */ - - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; + // Patch class flags. +/* *datap = c->flags; */ + *((int32_t*) (ra + 2)) = c->flags; - /* patch class flags */ + // Synchronize data cache. +/* md_dcacheflush(datap, sizeof(int32_t)); */ + md_icacheflush(ra + 2, sizeof(int32_t)); -/* *datap = c->flags; */ - *((int32_t *) (ra + 2)) = c->flags; + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -204,29 +205,31 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr) bool patcher_get_putstatic(patchref_t *pr) { - unresolved_field *uf; - intptr_t *datap; - fieldinfo *fi; + unresolved_field* uf = (unresolved_field*) pr->ref; + uintptr_t* datap = (uintptr_t*) pr->datap; + uint8_t* ra = (uint8_t*) pr->mpc; - uf = (unresolved_field *) pr->ref; - datap = (intptr_t *) pr->datap; + // Resolve the field. + fieldinfo* fi = resolve_field_eager(uf); - /* get the fieldinfo */ - - if (!(fi = resolve_field_eager(uf))) + if (fi == NULL) return false; - /* check if the field's class is initialized */ + ra += PATCHER_CALL_SIZE; - if (!(fi->class->state & CLASS_INITIALIZED)) - if (!initialize_class(fi->class)) + // Check if the field's class is initialized/ + if (!(fi->clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(fi->clazz)) return false; - PATCH_BACK_ORIGINAL_MCODE; + // Patch the field value's address. + *datap = (uintptr_t) fi->value; - /* patch the field value's address */ + // Synchronize data cache. + md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P); - *datap = (intptr_t) fi->value; + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -243,50 +246,40 @@ bool patcher_get_putstatic(patchref_t *pr) bool patcher_get_putfield(patchref_t *pr) { - uint8_t *ra; - unresolved_field *uf; - fieldinfo *fi; - uint8_t byte; - - ra = (uint8_t *) pr->mpc; - uf = (unresolved_field *) pr->ref; + uint8_t* pc = (uint8_t*) pr->mpc; + unresolved_field* uf = (unresolved_field*) pr->ref; - /* get the fieldinfo */ + // Resolve the field. + fieldinfo* fi = resolve_field_eager(uf); - if (!(fi = resolve_field_eager(uf))) + if (fi == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ - - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; - - /* Patch the field's offset: we check for the field type, because - the instructions have different lengths. */ + pc += PATCHER_CALL_SIZE; + // Patch the field's offset: we check for the field type, because + // the instructions have different lengths. if (IS_INT_LNG_TYPE(fi->type)) { - /* Check for special case: %rsp or %r12 as base register. */ - - byte = *(ra + 3); - - if (byte == 0x24) - *((int32_t *) (ra + 4)) = fi->offset; + // Check for special case: %rsp or %r12 as base register. + if (pc[3] == 0x24) + *((int32_t*) (pc + 4)) = fi->offset; else - *((int32_t *) (ra + 3)) = fi->offset; + *((int32_t*) (pc + 3)) = fi->offset; } else { - /* Check for special case: %rsp or %r12 as base register. */ - - byte = *(ra + 5); - - if (byte == 0x24) - *((int32_t *) (ra + 6)) = fi->offset; + // Check for special case: %rsp or %r12 as base register. + if (pc[5] == 0x24) + *((int32_t*) (pc + 6)) = fi->offset; else - *((int32_t *) (ra + 5)) = fi->offset; + *((int32_t*) (pc + 5)) = fi->offset; } + // Synchronize instruction cache. + md_icacheflush(pc, 6 + sizeof(int32_t)); + + // Patch back the original code. + patcher_patch_code(pr); + return true; } @@ -302,53 +295,39 @@ bool patcher_get_putfield(patchref_t *pr) bool patcher_putfieldconst(patchref_t *pr) { - uint8_t *ra; - unresolved_field *uf; - fieldinfo *fi; - uint8_t byte; - - ra = (uint8_t *) pr->mpc; - uf = (unresolved_field *) pr->ref; + uint8_t* pc = (uint8_t*) pr->mpc; + unresolved_field* uf = (unresolved_field*) pr->ref; - /* get the fieldinfo */ + // Resolve the field. + fieldinfo* fi = resolve_field_eager(uf); - if (!(fi = resolve_field_eager(uf))) + if (fi == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ - - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; - - /* patch the field's offset */ + pc += PATCHER_CALL_SIZE; + // Patch the field's offset. if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) { - /* handle special case when the base register is %r12 */ - - byte = *(ra + 2); - - if (byte == 0x84) { - *((uint32_t *) (ra + 4)) = fi->offset; - *((uint32_t *) (ra + 12 + 4)) = fi->offset + 4; - } - else { - *((uint32_t *) (ra + 3)) = fi->offset; - *((uint32_t *) (ra + 11 + 3)) = fi->offset + 4; - } + // Handle special case when the base register is %r12. + if (pc[12] == 0x94) + *((uint32_t*) (pc + 14)) = fi->offset; + else + *((uint32_t*) (pc + 13)) = fi->offset; } else { - /* handle special case when the base register is %r12 */ - - byte = *(ra + 2); - - if (byte == 0x84) - *((uint32_t *) (ra + 4)) = fi->offset; + // Handle special case when the base register is %r12. + if (pc[2] == 0x84) + *((uint32_t*) (pc + 4)) = fi->offset; else - *((uint32_t *) (ra + 3)) = fi->offset; + *((uint32_t*) (pc + 3)) = fi->offset; } + // Synchronize instruction cache. + md_icacheflush(pc, 14 + sizeof(int32_t)); + + // Patch back the original code. + patcher_patch_code(pr); + return true; } @@ -365,25 +344,23 @@ bool patcher_putfieldconst(patchref_t *pr) bool patcher_invokestatic_special(patchref_t *pr) { - unresolved_method *um; - intptr_t *datap; - methodinfo *m; - - /* get stuff from the stack */ + unresolved_method* um = (unresolved_method*) pr->ref; + uintptr_t* datap = (uintptr_t*) pr->datap; - um = (unresolved_method *) pr->ref; - datap = (intptr_t *) pr->datap; + // Resolve the method. + methodinfo* m = resolve_method_eager(um); - /* get the fieldinfo */ - - if (!(m = resolve_method_eager(um))) + if (m == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; + // Patch stubroutine. + *datap = (uintptr_t) m->stubroutine; - /* patch stubroutine */ + // Synchronize data cache. + md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P); - *datap = (intptr_t) m->stubroutine; + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -402,30 +379,25 @@ bool patcher_invokestatic_special(patchref_t *pr) bool patcher_invokevirtual(patchref_t *pr) { - uint8_t *ra; - unresolved_method *um; - methodinfo *m; - - ra = (uint8_t *) pr->mpc; - um = (unresolved_method *) pr->ref; + uint8_t* pc = (uint8_t*) pr->mpc; + unresolved_method* um = (unresolved_method*) pr->ref; - /* get the methodinfo */ + // Resovlve the method. + methodinfo* m = resolve_method_eager(um); - if (!(m = resolve_method_eager(um))) + if (m == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ + pc += PATCHER_CALL_SIZE; - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; + // Patch vftbl index. + *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex); - /* patch vftbl index */ + // Synchronize instruction cache. + md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P); - *((int32_t *) (ra + 3 + 3)) = - (int32_t) (OFFSET(vftbl_t, table[0]) + - sizeof(methodptr) * m->vftblindex); + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -445,37 +417,28 @@ bool patcher_invokevirtual(patchref_t *pr) bool patcher_invokeinterface(patchref_t *pr) { - uint8_t *ra; - unresolved_method *um; - methodinfo *m; + uint8_t* pc = (uint8_t*) pr->mpc; + unresolved_method* um = (unresolved_method*) pr->ref; - /* get stuff from the stack */ + // Resolve the method. + methodinfo* m = resolve_method_eager(um); - ra = (uint8_t *) pr->mpc; - um = (unresolved_method *) pr->ref; - - /* get the fieldinfo */ - - if (!(m = resolve_method_eager(um))) + if (m == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ + pc += PATCHER_CALL_SIZE; - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; + // Patch interfacetable index. + *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index); - /* patch interfacetable index */ + // Patch method offset. + *((int32_t*) (pc + 3 + 7 + 3)) = (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)); - *((int32_t *) (ra + 3 + 3)) = - (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr) * m->class->index); + // Synchronize instruction cache. + md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P); - /* patch method offset */ - - *((int32_t *) (ra + 3 + 7 + 3)) = - (int32_t) (sizeof(methodptr) * (m - m->class->methods)); + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -496,32 +459,27 @@ bool patcher_invokeinterface(patchref_t *pr) bool patcher_checkcast_interface(patchref_t *pr) { - uint8_t *ra; - constant_classref *cr; - classinfo *c; - - ra = (uint8_t *) pr->mpc; - cr = (constant_classref *) pr->ref; + uint8_t* pc = (uint8_t*) pr->mpc; + constant_classref* cr = (constant_classref*) pr->ref; - /* get the fieldinfo */ + // Resolve the class. + classinfo* c = resolve_classref_eager(cr); - if (!(c = resolve_classref_eager(cr))) + if (c == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ + pc += PATCHER_CALL_SIZE; - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; + // Patch super class index. + *((int32_t*) (pc + 7 + 3)) = c->index; - /* patch super class index */ + *((int32_t*) (pc + 7 + 7 + 6 + 8 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)); - *((int32_t *) (ra + 7 + 3)) = c->index; + // Synchronize instruction cache. + md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t)); - *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) = - (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - - c->index * sizeof(methodptr*)); + // Patch back the original code. + patcher_patch_code(pr); return true; } @@ -541,32 +499,27 @@ bool patcher_checkcast_interface(patchref_t *pr) bool patcher_instanceof_interface(patchref_t *pr) { - uint8_t *ra; - constant_classref *cr; - classinfo *c; + uint8_t* pc = (uint8_t*) pr->mpc; + constant_classref* cr = (constant_classref*) pr->ref; - ra = (uint8_t *) pr->mpc; - cr = (constant_classref *) pr->ref; + // Resolve the class. + classinfo* c = resolve_classref_eager(cr); - /* get the fieldinfo */ - - if (!(c = resolve_classref_eager(cr))) + if (c == NULL) return false; - PATCH_BACK_ORIGINAL_MCODE; - - /* if we show disassembly, we have to skip the nop's */ + pc += PATCHER_CALL_SIZE; - if (opt_shownops) - ra = ra + PATCHER_CALL_SIZE; + // Patch super class index. + *((int32_t*) (pc + 7 + 3)) = c->index; - /* patch super class index */ + *((int32_t*) (pc + 7 + 7 + 6 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)); - *((int32_t *) (ra + 7 + 3)) = c->index; + // Synchronize instruction cache. + md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 3 + sizeof(int32_t)); - *((int32_t *) (ra + 7 + 7 + 6 + 3)) = - (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - - c->index * sizeof(methodptr*)); + // Patch back the original code. + patcher_patch_code(pr); return true; }