Commit 95c4bb38 authored by Yi Lin's avatar Yi Lin

a CALL code patching yp

parent db6cb4e0
......@@ -28,6 +28,7 @@ public class Config {
public static final int USE_PAGE_PROTECTION_READ_YP = 1;
public static final int USE_PAGE_PROTECTION_WRITE_YP = 2;
public static final int USE_CODE_PATCHING_YP = 3;
public static final int USE_CODE_PATCHING_LOCAL_YP = 4;
public static final int USE_GLOBAL_CHECKING_YP = 10;
public static final int USE_GLOBAL_PAGE_PROTECTION_READ_YP = 11;
......@@ -53,7 +54,10 @@ public class Config {
YIELDPOINT_IMPL = USE_PAGE_PROTECTION_WRITE_YP;
} else if (config.getBooleanProperty("mmtk.use_code_patching_yp", false)) {
YIELDPOINT_IMPL = USE_CODE_PATCHING_YP;
} else if (config.getBooleanProperty("mmtk.use_no_yp", false)) {
} else if (config.getBooleanProperty("mmtk.use_code_patching_local_yp", false)) {
YIELDPOINT_IMPL = USE_CODE_PATCHING_LOCAL_YP;
}
else if (config.getBooleanProperty("mmtk.use_no_yp", false)) {
YIELDPOINT_IMPL = USE_NO_YP;
} else if (config.getBooleanProperty("mmtk.use_global_checking_yp", false)) {
YIELDPOINT_IMPL = USE_GLOBAL_CHECKING_YP;
......
#
# This file is part of the Jikes RVM project (http://jikesrvm.org).
#
# This file is licensed to You under the Eclipse Public License (EPL);
# You may not use this file except in compliance with the License. You
# may obtain a copy of the License at
#
# http://www.opensource.org/licenses/eclipse-1.0.php
#
# See the COPYRIGHT.txt file distributed with this work for information
# regarding copyright ownership.
#
# Default MMTk properties file.
mmtk.use_code_patching_local_yp = true
......@@ -1341,6 +1341,10 @@ public class GenerateAssembler {
emitTab(3);
emit("case FORCE6NOP_opcode:\n");
emitTab(4);
emit("if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_LOCAL_YP)\n");
emitTab(5);
emit("ir.compiledMethod.addYPOffset(mi);\n");
emitTab(4);
emit("emitNOP(6);\n");
emitTab(4);
emit("break;\n");
......
......@@ -32,6 +32,7 @@ import org.jikesrvm.classloader.TypeDescriptorParsing;
import org.jikesrvm.classloader.TypeReference;
import org.jikesrvm.compilers.baseline.BaselineCompiler;
import org.jikesrvm.compilers.common.BootImageCompiler;
import org.jikesrvm.compilers.common.CompiledMethod;
import org.jikesrvm.compilers.common.RuntimeCompiler;
import org.jikesrvm.mm.mminterface.MemoryManager;
import org.jikesrvm.runtime.BootRecord;
......@@ -42,6 +43,7 @@ import org.jikesrvm.runtime.RuntimeEntrypoints;
import org.jikesrvm.runtime.SysCall;
import static org.jikesrvm.runtime.SysCall.sysCall;
import org.jikesrvm.scheduler.Lock;
import org.jikesrvm.scheduler.MainThread;
import org.jikesrvm.scheduler.Synchronization;
......@@ -167,6 +169,47 @@ public class VM extends Properties {
*/
@Interruptible
private static void finishBooting() {
// code patching yieldpoint
// call
CompiledMethod.CALL[0] = (byte) 0xff;
CompiledMethod.CALL[1] = (byte) 0x15;
CompiledMethod.CALL[2] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()).toWord().and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[3] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()).toWord().rsha(8).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[4] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()).toWord().rsha(16).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[5] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()).toWord().rsha(24).and(Word.fromIntZeroExtend(0xff)).toInt();
// nop5
CompiledMethod.NOP6[0] = (byte) 0x66;
CompiledMethod.NOP6[1] = (byte) 0x0f;
CompiledMethod.NOP6[2] = (byte) 0x1f;
CompiledMethod.NOP6[3] = (byte) 0x44;
CompiledMethod.NOP6[4] = (byte) 0x00;
CompiledMethod.NOP6[5] = (byte) 0x00;
VM.sysWriteln("JTOC:", Magic.getJTOC());
VM.sysWrite("Check Method Offset:");
VM.sysWriteln(Entrypoints.optThreadSwitchCheckMethod.getOffset());
VM.sysWriteln("Call address:", Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()));
VM.sysWriteln("Call address (word):", Magic.getJTOC().plus(Entrypoints.optThreadSwitchCheckMethod.getOffset()).toWord());
VM.sysWrite("bytes[0]=");
VM.sysWriteHex(CompiledMethod.CALL[0]);
VM.sysWriteln();
VM.sysWrite("bytes[1]=");
VM.sysWriteHex(CompiledMethod.CALL[1]);
VM.sysWriteln();
VM.sysWrite("bytes[2]=");
VM.sysWriteHex(CompiledMethod.CALL[2]);
VM.sysWriteln();
VM.sysWrite("bytes[3]=");
VM.sysWriteHex(CompiledMethod.CALL[3]);
VM.sysWriteln();
VM.sysWrite("bytes[4]=");
VM.sysWriteHex(CompiledMethod.CALL[4]);
VM.sysWriteln();
VM.sysWrite("bytes[5]=");
VM.sysWriteHex(CompiledMethod.CALL[5]);
VM.sysWriteln();
// get pthread_id from OS and store into vm_processor field
//
......
......@@ -3935,7 +3935,8 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
// thread switch requested ??
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CHECKING_YP
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP) {
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_LOCAL_YP) {
ThreadLocalState.emitCompareFieldWithImm(asm, Entrypoints.takeYieldpointField.getOffset(), 0);
ForwardReference fr1;
if (whereFrom == RVMThread.PROLOGUE) {
......
......@@ -18,6 +18,7 @@ import org.jikesrvm.VM;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.classloader.RVMType;
import org.jikesrvm.runtime.DynamicLink;
import org.jikesrvm.runtime.Entrypoints;
import org.jikesrvm.runtime.ExceptionDeliverer;
import org.jikesrvm.runtime.Magic;
import org.jikesrvm.runtime.StackBrowser;
......@@ -106,6 +107,9 @@ public abstract class CompiledMethod {
static final byte INT3 = (byte) 0xcc;
static final byte NOP = (byte) 0x90;
public static final byte[] CALL = new byte[6];
public static final byte[] NOP6 = new byte[6];
@Uninterruptible
@Inline
public final void nop2int() {
......@@ -122,22 +126,6 @@ public abstract class CompiledMethod {
}
}
@Uninterruptible
public void nop2intDebug() {
VM.sysWriteln("Before patching:");
printInstructions();
VM.sysWriteln("Print nop offsets:");
for (int i = 0; i < ypOffsetsIndex; i++)
VM.sysWriteln(ypOffsets[i]);
VM.sysWriteln();
nop2int();
VM.sysWriteln("After patching:");
printInstructions();
}
@Uninterruptible
public void printInstructions() {
Address address = ObjectReference.fromObject(instructions).toAddress();
......@@ -159,6 +147,48 @@ public abstract class CompiledMethod {
for (int i = 0; i < ypOffsetsIndex; i++) {
instructions.set(ypOffsets[i], NOP);
}
}
@Uninterruptible
@Inline
public void nop2call() {
for (int i = 0; i < ypOffsetsIndex; i++) {
int first = ypOffsets[i];
// patch the first byte to int3
instructions.set(first, INT3);
// patch the rest
instructions.set(first+1, CALL[1]);
instructions.set(first+2, CALL[2]);
instructions.set(first+3, CALL[3]);
instructions.set(first+4, CALL[4]);
instructions.set(first+5, CALL[5]);
// patch the first to call
instructions.set(first, CALL[0]);
}
}
@Uninterruptible
@Inline
public void call2nop() {
for (int i = 0; i < ypOffsetsIndex; i++) {
int first = ypOffsets[i];
// patch the first byte to int3
instructions.set(first, INT3);
// patch the rest
instructions.set(first+1, NOP6[1]);
instructions.set(first+2, NOP6[2]);
instructions.set(first+3, NOP6[3]);
instructions.set(first+4, NOP6[4]);
instructions.set(first+5, NOP6[5]);
// patch the first to NOP
instructions.set(first, NOP6[0]);
}
}
/**
......
......@@ -331,6 +331,53 @@ public class CompiledMethods {
}
}
}
@Uninterruptible
public static void setNOP2CALL() {
VM.sysWriteln("-----Start patching code-----");
int patched = 0;
long start = Magic.getTimeBase();
for (int i = 0, n = numCompiledMethods(); i < n; i ++) {
CompiledMethod cm = getCompiledMethodUnchecked(i);
if (cm == null || !cm.isCompiled())
continue;
if (cm.getCompilerType() != CompiledMethod.OPT)
continue;
cm.nop2call();
patched ++;
}
long time = Magic.getTimeBase() - start;
YieldpointStatistics.methodsPatched(patched);
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
}
@Uninterruptible
public static void setCALL2NOP() {
int patched = 0;
long start = Magic.getTimeBase();
for (int i = 0, n = numCompiledMethods(); i < n; i ++) {
CompiledMethod cm = getCompiledMethodUnchecked(i);
if (cm == null || !cm.isCompiled())
continue;
if (cm.getCompilerType() != CompiledMethod.OPT)
continue;
cm.call2nop();
patched ++;
}
long time = Magic.getTimeBase() - start;
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
}
@Uninterruptible
public static void setNOP2INT() {
......
......@@ -445,6 +445,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP) {
expandCodePatchingYieldpoint(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_EPILOGUE_opcode:
......@@ -479,6 +482,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP) {
expandCodePatchingYieldpoint(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_BACKEDGE_opcode:
......@@ -513,6 +519,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP) {
expandCodePatchingYieldpoint(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_OSR_opcode:
......@@ -529,6 +538,10 @@ private static void expandCodePatchingYieldpoint(Instruction p, IR ir) {
MIR_Empty.mutate(p, FORCENOP);
}
private static void expandCodePatchingYieldpointNOP6(Instruction p, IR ir) {
MIR_Empty.mutate(p, FORCE6NOP);
}
private static void expandNopYieldpoint(Instruction p, IR ir, int n) {
Instruction nop = null;
if (n == 1) {
......
......@@ -75,6 +75,15 @@ public class OptSaveVolatile {
Address fp = Magic.getFramePointer();
RVMThread.yieldpoint(RVMThread.BACKEDGE, fp);
}
@Entrypoint
public static void checkAndTakeYieldpoint() {
// VM.sysWriteln("reach checkAndTakeYieldpoint()");
if (RVMThread.getCurrentThread().takeYieldpoint != 0) {
// Address fp = Magic.getFramePointer();
RVMThread.yieldpoint(RVMThread.PROLOGUE, Address.zero());
}
}
/**
* Handle timer interrupt taken in the prologue of a native method.
......
......@@ -205,6 +205,7 @@ public class BootRecord {
public Offset yieldpointFromPrologueOffset;
public Offset yieldpointFromPrologueOptOffset;
public Offset yieldpointCheckOffset;
/**
* an external signal has been sent e.g. kill -signalnumber processid
......
......@@ -477,6 +477,8 @@ public class Entrypoints {
public static final NormalMethod optNewArrayArrayMethod;
public static final NormalMethod optNew2DArrayMethod;
public static final NormalMethod sysArrayCopy;
public static final NormalMethod optThreadSwitchCheckMethod;
static {
if (VM.BuildForOptCompiler) {
......@@ -492,6 +494,8 @@ public class Entrypoints {
getMethod(org.jikesrvm.compilers.opt.runtimesupport.OptSaveVolatile.class, "yieldpointFromBackedge", "()V");
optThreadSwitchFromEpilogueMethod =
getMethod(org.jikesrvm.compilers.opt.runtimesupport.OptSaveVolatile.class, "yieldpointFromEpilogue", "()V");
optThreadSwitchCheckMethod =
getMethod(org.jikesrvm.compilers.opt.runtimesupport.OptSaveVolatile.class, "checkAndTakeYieldpoint", "()V");
yieldpointFromNativePrologueMethod =
getMethod(org.jikesrvm.compilers.opt.runtimesupport.OptSaveVolatile.class, "yieldpointFromNativePrologue", "()V");
yieldpointFromNativeEpilogueMethod =
......@@ -510,6 +514,7 @@ public class Entrypoints {
optThreadSwitchFromPrologueMethod = null;
optThreadSwitchFromBackedgeMethod = null;
optThreadSwitchFromEpilogueMethod = null;
optThreadSwitchCheckMethod = null;
yieldpointFromNativePrologueMethod = null;
yieldpointFromNativeEpilogueMethod = null;
optResolveMethod = null;
......
......@@ -913,6 +913,7 @@ public class RuntimeEntrypoints implements ArchitectureSpecific.StackframeLayout
BootRecord.the_boot_record.yieldpointFromPrologueOffset = Entrypoints.yieldpointFromPrologueMethod.getOffset();
if (VM.BuildForOptCompiler) {
BootRecord.the_boot_record.yieldpointFromPrologueOptOffset = Entrypoints.optThreadSwitchFromPrologueMethod.getOffset();
BootRecord.the_boot_record.yieldpointCheckOffset = Entrypoints.optThreadSwitchCheckMethod.getOffset();
}
// tell "RunBootImage.C" to set "RVMThread.debugRequested" flag
......
......@@ -104,7 +104,7 @@ const char *bootDataFilename = 0;
const char *bootRMapFilename = 0;
/* Emit trace information? */
int lib_verbose = 0;
int lib_verbose = 1;
/* Location of jtoc within virtual machine image. */
static Address VmToc;
......@@ -498,7 +498,7 @@ hardwareTrapHandler(int signo, siginfo_t *si, void *context)
isRecoverable = 1;
else if (signo == SIGTRAP) {
if (YIELDPOINT_IMPL == 3)
if (YIELDPOINT_IMPL == 3 || YIELDPOINT_IMPL == 4)
isRecoverable = 1;
else
isRecoverable = 0;
......@@ -652,6 +652,25 @@ hardwareTrapHandler(int signo, siginfo_t *si, void *context)
_exit(EXIT_STATUS_DYING_WITH_UNCAUGHT_EXCEPTION);
}
/* Test for code patching local*/
if (YIELDPOINT_IMPL == 4 && signo == 5) {
// we are patching code
// a temporary INT3 is triggered, we simply return
printf("reaching a temporary INT3\n");
/* Insert artifical stackframe at the stack top */
Address * sp = (Address *)(IA32_ESP(context) - 4);
IA32_ESP(context) = IA32_ESP(context) - 4;
instructionFollowing = getInstructionFollowing(localInstructionAddress);
// *sp = localInstructionAddress;
*sp = instructionFollowing;
unsigned int yieldPointHandlerAddress =
*(unsigned int *) (localJTOC + bootRecord->yieldpointCheckOffset);
IA32_EIP(context) = yieldPointHandlerAddress;
return;
}
/* Test for code patching yield point */
if (YIELDPOINT_IMPL == 3 && signo == 5){
// printf("code patching YP handler.\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment