Skip to content

Commit

Permalink
Showing 3 changed files with 41 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -28,11 +28,6 @@ public class FullInterpreterContext extends InterpreterContext {
// FIXME: At some point when we relinearize after running another phase of passes we should document that here to know how this field is changed
private BasicBlock[] linearizedBBList = null;

// Contains pairs of values. The first value is number of instrs in this range + number of instrs before
// this range. The second number is the rescuePC. getRescuePC(ipc) will walk this list and first odd value
// less than this value will be the rpc.
private int[] rescueIPCs = null;

/** Map of name -> dataflow problem */
private Map<String, DataFlowProblem> dataFlowProblems;

Original file line number Diff line number Diff line change
@@ -2,13 +2,17 @@

import java.util.EnumSet;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.Callable;

import org.jruby.ir.IRFlags;
import org.jruby.ir.IRMetaClassBody;
import org.jruby.ir.IRScope;
import org.jruby.ir.instructions.ExceptionRegionEndMarkerInstr;
import org.jruby.ir.instructions.ExceptionRegionStartMarkerInstr;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.LabelInstr;
import org.jruby.ir.operands.Label;
import org.jruby.ir.representations.CFG;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
@@ -22,6 +26,11 @@ public class InterpreterContext {
// much later after running compiler passes. JIT will not use this field at all.
protected Instr[] instructions;

// Contains pairs of values. The first value is number of instrs in this range + number of instrs before
// this range. The second number is the rescuePC. getRescuePC(ipc) will walk this list and first odd value
// less than this value will be the rpc.
protected int[] rescueIPCs = null;

// Cached computed fields
private boolean hasExplicitCallProtocol;
private boolean pushNewDynScope;
@@ -85,15 +94,38 @@ private void retrieveFlags() {
private Instr[] prepareBuildInstructions(List<Instr> instructions) {
int length = instructions.size();
Instr[] linearizedInstrArray = instructions.toArray(new Instr[length]);

for (int ipc = 0; ipc < length; ipc++) {
Instr i = linearizedInstrArray[ipc];

if (i instanceof LabelInstr) ((LabelInstr) i).getLabel().setTargetPC(ipc + 1);
}

Stack<Integer> markers = new Stack();
rescueIPCs = new int[length];
int rpc = -1;

for (int ipc = 0; ipc < length; ipc++) {
Instr i = linearizedInstrArray[ipc];

if (i instanceof ExceptionRegionStartMarkerInstr) {
rpc = ((ExceptionRegionStartMarkerInstr) i).getFirstRescueBlockLabel().getTargetPC();
markers.push(rpc);
} else if (i instanceof ExceptionRegionEndMarkerInstr) {
markers.pop();
rpc = markers.isEmpty() ? -1 : markers.peek().intValue();
}

rescueIPCs[ipc] = rpc;
}

return linearizedInstrArray;
}

public int[] getRescueIPCs() {
return rescueIPCs;
}

public int getRequiredArgsCount() {
return getStaticScope().getSignature().required();
}
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
DynamicScope currDynScope = context.getCurrentScope();
boolean acceptsKeywordArgument = interpreterContext.receivesKeywordArguments();

Stack<ExceptionRegionStartMarkerInstr> rescuePCs = null;
int[] rescuePCs = interpreterContext.getRescueIPCs();

// Init profiling this scope
boolean debug = IRRuntimeHelpers.isDebug();
@@ -55,15 +55,13 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel

Operation operation = instr.getOperation();
if (debug) {
Interpreter.LOG.info("I: {" + ipc + "} " + instr + "; <#RPCs=" + (rescuePCs == null ? 0 : rescuePCs.size()) + ">");
Interpreter.LOG.info("I: " + ipc + ", R: " + rescuePCs[ipc] + " - " + instr + ">");
Interpreter.interpInstrsCount++;
} else if (profile) {
Profiler.instrTick(operation);
Interpreter.interpInstrsCount++;
}

ipc++;

try {
switch (operation.opClass) {
case ARG_OP:
@@ -82,10 +80,11 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
ipc = jump.getJumpTarget().getTargetPC();
break;
default:
ipc = instr.interpretAndGetNewIPC(context, currDynScope, currScope, self, temp, ipc);
ipc = instr.interpretAndGetNewIPC(context, currDynScope, currScope, self, temp, ipc + 1);
break;

}
break;
continue;
case BOOK_KEEPING_OP:
switch (operation) {
case PUSH_METHOD_BINDING:
@@ -94,26 +93,8 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
// which will now use the updated value of currDynScope.
currDynScope = interpreterContext.newDynamicScope(context);
context.pushScope(currDynScope);
case EXC_REGION_START: {
if (rescuePCs == null) {
rescuePCs = new Stack<>();
rescuePCs.push((ExceptionRegionStartMarkerInstr) instr);
} else {
// We use EXC_REGION_{START,END} as actual instructions instead of markers
// in this particular interpreter. Unfortunately, these can never be guaranteed to
// execute in matched pairs since other instrs (like from a jump representing a Ruby
// next) may happen before hitting the END instr. Because of this we will look to
// see if the stack is dirty and prune back to a proper clean point. Otherwise it is
// clean and we push a new entry. This mechanism works because these exc. regions
// represent lexical boundaries and you cannot see the same boundary nested in itself.
// If we try to push something already there then the space-time continuum is blown
// and we have to clean the universe up.
pushOrPrune((ExceptionRegionStartMarkerInstr) instr, rescuePCs);
}
}
break;
case EXC_REGION_START:
case EXC_REGION_END:
rescuePCs.pop();
break;
default:
processBookKeepingOp(context, block, instr, operation, name, args, self, blockArg, implClass, currDynScope, temp, currScope);
@@ -123,14 +104,12 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
processOtherOp(context, block, instr, operation, currDynScope, currScope, temp, self);
break;
}

ipc++;
} catch (Throwable t) {
if (debug) extractToMethodToAvoidC2Crash(instr, t);

if (rescuePCs == null || rescuePCs.empty()) {
ipc = -1;
} else {
ipc = rescuePCs.pop().getFirstRescueBlockLabel().getTargetPC();
}
ipc = rescuePCs == null ? -1 : rescuePCs[ipc];

if (debug) {
Interpreter.LOG.info("in : " + interpreterContext.getScope() + ", caught Java throwable: " + t + "; excepting instr: " + instr);
@@ -149,20 +128,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
throw context.runtime.newRuntimeError("BUG: interpreter fell through to end unexpectedly");
}

private void pushOrPrune(ExceptionRegionStartMarkerInstr element, Stack<ExceptionRegionStartMarkerInstr> stack) {
int firstOccurrence = stack.indexOf(element);

if (firstOccurrence != -1) {
int elementsToPrune = stack.size() - (firstOccurrence + 1);

for (int i = 0; i < elementsToPrune; i++) {
stack.pop();
}
} else {
stack.push(element);
}
}

protected static void processOtherOp(ThreadContext context, Block block, Instr instr, Operation operation, DynamicScope currDynScope,
StaticScope currScope, Object[] temp, IRubyObject self) {
Block.Type blockType = block == null ? null : block.type;

0 comments on commit 28d18cf

Please sign in to comment.