Commit fe8bd0e9 authored by Yi Lin's avatar Yi Lin

a thread-local code patching yieldpoint. Runs quite slow with timer thread

parent a48564f1
......@@ -30,6 +30,8 @@ public class Config {
public static final int USE_CODE_PATCHING_INT3_YP = 3;
public static final int USE_CODE_PATCHING_CALL_YP = 4;
public static final int USE_CODE_PATCHING_CALL_LOCAL_YP = 5;
public static final int USE_GLOBAL_CHECKING_YP = 10;
public static final int USE_GLOBAL_PAGE_PROTECTION_READ_YP = 11;
public static final int USE_GLOBAL_PAGE_PROTECTION_WRITE_YP = 12;
......@@ -56,7 +58,9 @@ public class Config {
YIELDPOINT_IMPL = USE_CODE_PATCHING_INT3_YP;
} else if (config.getBooleanProperty("mmtk.use_code_patching_call_yp", false)) {
YIELDPOINT_IMPL = USE_CODE_PATCHING_CALL_YP;
}
} else if (config.getBooleanProperty("mmtk.use_code_patching_call_local_yp", false)) {
YIELDPOINT_IMPL = USE_CODE_PATCHING_CALL_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)) {
......
#
# 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_call_local_yp = true
......@@ -1341,7 +1341,7 @@ 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_CALL_YP)\n");
emit("if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP || org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP)\n");
emitTab(5);
emit("ir.compiledMethod.addYPOffset(mi);\n");
emitTab(4);
......
......@@ -174,10 +174,17 @@ public class VM extends Properties {
CompiledMethod.CALL[0] = (byte) 0xff;
CompiledMethod.CALL[1] = (byte) 0x15;
CompiledMethod.CALL[2] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[3] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(8).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[4] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(16).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[5] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(24).and(Word.fromIntZeroExtend(0xff)).toInt();
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP) {
CompiledMethod.CALL[2] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[3] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(8).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[4] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(16).and(Word.fromIntZeroExtend(0xff)).toInt();
CompiledMethod.CALL[5] = (byte) Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()).toWord().rsha(24).and(Word.fromIntZeroExtend(0xff)).toInt();
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
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;
......@@ -187,29 +194,29 @@ public class VM extends Properties {
CompiledMethod.NOP6[4] = (byte) 0x00;
CompiledMethod.NOP6[5] = (byte) 0x00;
VM.sysWriteln("JTOC:", Magic.getJTOC());
VM.sysWrite("Check Method Offset:");
VM.sysWriteln(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset());
VM.sysWriteln("Call address:", Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()));
VM.sysWriteln("Call address (word):", Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.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();
// VM.sysWriteln("JTOC:", Magic.getJTOC());
// VM.sysWrite("Check Method Offset:");
// VM.sysWriteln(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset());
// VM.sysWriteln("Call address:", Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.getOffset()));
// VM.sysWriteln("Call address (word):", Magic.getJTOC().plus(Entrypoints.optThreadSwitchFromPrologueMethod.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
//
......
......@@ -3936,7 +3936,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_INT3_YP
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP) {
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP
|| org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
ThreadLocalState.emitCompareFieldWithImm(asm, Entrypoints.takeYieldpointField.getOffset(), 0);
ForwardReference fr1;
if (whereFrom == RVMThread.PROLOGUE) {
......
......@@ -334,7 +334,7 @@ public class CompiledMethods {
@Uninterruptible
public static void setNOP2CALL() {
VM.sysWriteln("-----Start patching code-----");
// VM.sysWriteln("-----Start patching code-----");
int patched = 0;
long start = Magic.getTimeBase();
......@@ -353,8 +353,8 @@ public class CompiledMethods {
long time = Magic.getTimeBase() - start;
YieldpointStatistics.methodsPatched(patched);
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
// VM.sysWriteln("patched ", patched, " methods ");
// VM.sysWriteln(" in ", time, " cycles. ");
}
@Uninterruptible
......@@ -375,13 +375,13 @@ public class CompiledMethods {
long time = Magic.getTimeBase() - start;
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
// VM.sysWriteln("patched ", patched, " methods ");
// VM.sysWriteln(" in ", time, " cycles. ");
}
@Uninterruptible
public static void setNOP2INT() {
VM.sysWriteln("-----Start patching code-----");
// VM.sysWriteln("-----Start patching code-----");
int patched = 0;
long start = Magic.getTimeBase();
......@@ -400,8 +400,8 @@ public class CompiledMethods {
long time = Magic.getTimeBase() - start;
YieldpointStatistics.methodsPatched(patched);
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
// VM.sysWriteln("patched ", patched, " methods ");
// VM.sysWriteln(" in ", time, " cycles. ");
}
@Uninterruptible
......@@ -422,7 +422,7 @@ public class CompiledMethods {
long time = Magic.getTimeBase() - start;
VM.sysWriteln("patched ", patched, " methods ");
VM.sysWriteln(" in ", time, " cycles. ");
// VM.sysWriteln("patched ", patched, " methods ");
// VM.sysWriteln(" in ", time, " cycles. ");
}
}
......@@ -448,6 +448,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_EPILOGUE_opcode:
......@@ -485,6 +488,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_BACKEDGE_opcode:
......@@ -522,6 +528,9 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
expandCodePatchingYieldpointNOP6(p, ir);
}
break;
case YIELDPOINT_OSR_opcode:
......
......@@ -43,6 +43,7 @@ import org.jikesrvm.Services;
import org.jikesrvm.UnimplementedError;
import org.jikesrvm.adaptive.OnStackReplacementEvent;
import org.jikesrvm.adaptive.measurements.RuntimeMeasurements;
import org.jikesrvm.adaptive.measurements.organizers.Organizer;
import org.jikesrvm.compilers.common.CompiledMethod;
import org.jikesrvm.compilers.common.CompiledMethods;
import org.jikesrvm.osr.ObjectHolder;
......@@ -1386,6 +1387,7 @@ public final class RVMThread extends ThreadContext {
outOfMemoryError = new OutOfMemoryError();
dumpLock = new Monitor();
acctLock = new NoYieldpointsMonitor();
patchCodeLock = new NoYieldpointsMonitor();
debugLock = new NoYieldpointsMonitor();
outputLock = new NoYieldpointsMonitor();
softHandshakeDataLock = new Monitor();
......@@ -1798,6 +1800,10 @@ public final class RVMThread extends ThreadContext {
public boolean shouldBeSampled() {
return execStatus == IN_JAVA;
}
public boolean eligibleForTimerThread() {
return (collectorContext == null) && !(systemThread instanceof TimerThread);
}
/** A variant of checkBlock() that does not save the thread state. */
@NoInline
......@@ -2801,6 +2807,19 @@ public final class RVMThread extends ThreadContext {
}
acctLock.unlock();
// for call patching local yieldpoint
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
RVMThread.patchCodeLock.lockNoHandshake();
if (takeYieldpoint != 0) {
takeYieldpoint = 0;
threadsToReachYieldpoint--;
VM.sysWriteln(getName(), " about to quit, -- cound: ", threadsToReachYieldpoint);
}
RVMThread.patchCodeLock.unlock();
}
if (traceAcct)
VM.sysWriteln("done with accounting.");
......@@ -4049,6 +4068,17 @@ public final class RVMThread extends ThreadContext {
t.takeYieldpoint = 0;
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
// if this is the last thread to reach yieldpoint, we patch code back
RVMThread.patchCodeLock.lockNoHandshake();
threadsToReachYieldpoint--;
// VM.sysWriteln(t.getName(), "--, count: ", threadsToReachYieldpoint);
if (threadsToReachYieldpoint == 0) {
CompiledMethods.setCALL2NOP();
}
RVMThread.patchCodeLock.unlock();
}
return;
// boolean wasAtYieldpoint = t.atYieldpoint;
......@@ -5635,18 +5665,37 @@ public final class RVMThread extends ThreadContext {
public static final int PROTECT_PAGE_OFFSET_BL = BYTES_IN_PAGE;
public static final int PROTECT_PAGE_OFFSET_OPT = BYTES_IN_PAGE + 4;
public static final Extent PROTECT_PAGE_SIZE = Extent.fromIntSignExtend(BYTES_IN_PAGE);
static NoYieldpointsMonitor patchCodeLock;
static int threadsToReachYieldpoint = 0;
public void turnOnLocalYieldpoints() {
takeYieldpoint = 1;
public void turnOnLocalYieldpoints() {
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP ||
org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
takeYieldpoint = 1;
Address pageAddr = Magic.objectAsAddress(this).plus(PROTECT_PAGE_OFFSET_BL).toWord().and(Word.fromIntZeroExtend(0xfffff000)).toAddress();
Memory.mprotect(pageAddr, PROTECT_PAGE_SIZE, Memory.PROT_NONE);
}
// else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_YP) {
// CompiledMethods.setNOP2INT();
// }
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_CODE_PATCHING_CALL_LOCAL_YP) {
if (systemThread instanceof Organizer || systemThread instanceof FinalizerThread)
return;
RVMThread.patchCodeLock.lockNoHandshake();
if (takeYieldpoint == 0) {
if (threadsToReachYieldpoint == 0) {
// VM.sysWriteln(">>>patch code<<<");
CompiledMethods.setNOP2CALL();
}
threadsToReachYieldpoint++;
// VM.sysWriteln(getName(), "++, count: ", threadsToReachYieldpoint);
}
takeYieldpoint = 1;
RVMThread.patchCodeLock.unlock();
}
}
public void turnOffLocalYieldpoints() {
......
......@@ -42,33 +42,33 @@ public class TimerThread extends SystemThread {
// TODO: consider allowing GC to be sampled to enable profile-directed optimization of MMTk.
@Override
public void run() {
return;
// VM.disableYieldpoints();
// if (verbose>=1) VM.sysWriteln("TimerThread run routine entered");
// try {
// for (;;) {
// sysCall.sysNanoSleep(1000L*1000L*VM.interruptQuantum);
//
// if (VM.BuildForAdaptiveSystem) {
// // grab the lock to prevent threads from getting GC'd while we are
// // iterating (since this thread doesn't stop for GC)
// RVMThread.acctLock.lockNoHandshake();
// RVMThread.timerTicks++;
// for (int i=0;i<RVMThread.numThreads;++i) {
// RVMThread candidate=RVMThread.threads[i];
// if (candidate!=null && candidate.shouldBeSampled()) {
// candidate.timeSliceExpired++;
// candidate.takeYieldpoint=1;
// }
// }
// RVMThread.acctLock.unlock();
// }
//
// RVMThread.checkDebugRequest();
// }
// } catch (Throwable e) {
// printExceptionAndDie(e);
// }
// return;
VM.disableYieldpoints();
if (verbose>=1) VM.sysWriteln("TimerThread run routine entered");
try {
for (;;) {
sysCall.sysNanoSleep(1000L*1000L*VM.interruptQuantum);
if (VM.BuildForAdaptiveSystem) {
// grab the lock to prevent threads from getting GC'd while we are
// iterating (since this thread doesn't stop for GC)
RVMThread.acctLock.lockNoHandshake();
RVMThread.timerTicks++;
for (int i=0;i<RVMThread.numThreads;++i) {
RVMThread candidate=RVMThread.threads[i];
if (candidate!=null && candidate.shouldBeSampled() && candidate.eligibleForTimerThread()) {
candidate.timeSliceExpired++;
candidate.turnOnLocalYieldpoints();
}
}
RVMThread.acctLock.unlock();
}
RVMThread.checkDebugRequest();
}
} catch (Throwable e) {
printExceptionAndDie(e);
}
}
@UninterruptibleNoWarn
private static void printExceptionAndDie(Throwable e) {
......
......@@ -104,7 +104,7 @@ const char *bootDataFilename = 0;
const char *bootRMapFilename = 0;
/* Emit trace information? */
int lib_verbose = 1;
int lib_verbose = 0;
/* 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 || YIELDPOINT_IMPL == 4)
if (YIELDPOINT_IMPL == 3 || YIELDPOINT_IMPL == 4 || YIELDPOINT_IMPL == 5)
isRecoverable = 1;
else
isRecoverable = 0;
......@@ -656,6 +656,25 @@ hardwareTrapHandler(int signo, siginfo_t *si, void *context)
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->yieldpointFromPrologueOptOffset);
IA32_EIP(context) = yieldPointHandlerAddress;
return;
}
/* Test for code patching*/
if (YIELDPOINT_IMPL == 5 && 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 */
......@@ -666,7 +685,7 @@ hardwareTrapHandler(int signo, siginfo_t *si, void *context)
*sp = instructionFollowing;
unsigned int yieldPointHandlerAddress =
*(unsigned int *) (localJTOC + bootRecord->yieldpointFromPrologueOptOffset);
*(unsigned int *) (localJTOC + bootRecord->yieldpointCheckOffset);
IA32_EIP(context) = yieldPointHandlerAddress;
return;
}
......
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