Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c5994bb38c15
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a439381762c8
Choose a head ref
  • 7 commits
  • 13 files changed
  • 1 contributor

Commits on Oct 23, 2014

  1. Copy the full SHA
    15e08d2 View commit details
  2. Hmm how did this compile before

    enebo committed Oct 23, 2014
    Copy the full SHA
    88b24eb View commit details
  3. Rearrange debug so if JIT is active we still see CFG print out (made …

    …some fixmes too).
    
    Remove weird name == null logic from debug.
    Small refactoring to show jit/non-jit intent (similar to how we had this for call/non-call protocol).
    enebo committed Oct 23, 2014
    Copy the full SHA
    c014409 View commit details
  4. Copy the full SHA
    69e1ae7 View commit details
  5. Copy the full SHA
    93f6f74 View commit details
  6. Copy the full SHA
    1fd9dfb View commit details
  7. Cosmetic fixes to ir output

    enebo committed Oct 23, 2014
    Copy the full SHA
    a439381 View commit details
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.PositionAware;
import org.jruby.runtime.ThreadContext;
@@ -25,8 +24,6 @@
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import static org.jruby.ir.IRFlags.HAS_EXPLICIT_CALL_PROTOCOL;

public class InterpretedIRMethod extends DynamicMethod implements IRMethodArgs, PositionAware {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRMethod");

@@ -102,79 +99,88 @@ public InterpreterContext ensureInstrsReady() {

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, args, block);
DynamicMethod jittedMethod = box.actualMethod;

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

return Interpreter.INTERPRET_METHOD(context, this, self, name, args, block);
if (jittedMethod != null) {
return jittedMethod.call(context, self, clazz, name, args, block);
} else {
return Interpreter.INTERPRET_METHOD(context, this, self, name, args, block);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, block);

InterpreterContext ic = ensureInstrsReady();
DynamicMethod jittedMethod = box.actualMethod;

if (IRRuntimeHelpers.isDebug()) doDebug();

return Interpreter.INTERPRET_METHOD(context, this, self, name, IRubyObject.NULL_ARRAY, block);
if (jittedMethod != null) {
return jittedMethod.call(context, self, clazz, name, block);
} else {
return Interpreter.INTERPRET_METHOD(context, this, self, name, IRubyObject.NULL_ARRAY, block);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, block);

InterpreterContext ic = ensureInstrsReady();
DynamicMethod jittedMethod = box.actualMethod;

if (IRRuntimeHelpers.isDebug()) doDebug();

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0), block);
if (jittedMethod != null) {
return jittedMethod.call(context, self, clazz, name, arg0, block);
} else {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0), block);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, arg1, block);

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();
DynamicMethod jittedMethod = box.actualMethod;

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1), block);
if (jittedMethod != null) {
return jittedMethod.call(context, self, clazz, name, arg0, arg1, block);
} else {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1), block);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, arg1, arg2, block);

InterpreterContext ic = ensureInstrsReady();
DynamicMethod jittedMethod = box.actualMethod;

if (IRRuntimeHelpers.isDebug()) doDebug();

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1, arg2), block);
if (jittedMethod != null) {
return jittedMethod.call(context, self, clazz, name, arg0, arg1, arg2, block);
} else {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1, arg2), block);
}
}

protected void doDebug() {
// FIXME: name should probably not be "" ever.
String realName = name == null || "".equals(name) ? method.getName() : name;
LOG.info("Executing '" + realName + "'");
if (displayedCFG == false) {
// FIXME: This is printing out IRScope CFG but JIT may be active and it might not reflect
// currently executing. Move into JIT and into interp since they will be getting CFG from
// different sources
// FIXME: This is only printing out CFG once. If we keep applying more passes then we
// will want to print out after those new passes.
ensureInstrsReady();
LOG.info("Executing '" + method.getName() + "'");
if (!displayedCFG) {
CFG cfg = method.getCFG();
LOG.info("Graph:\n" + cfg.toStringGraph());
LOG.info("CFG:\n" + cfg.toStringInstrs());
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -2957,7 +2957,8 @@ public Operand buildPostExe(PostExeNode postExeNode, IRScope s) {
// SSS FIXME: IR support for end-blocks that access vars in non-toplevel-scopes
// might be broken currently. We could either fix it or consider dropping support
// for END blocks altogether or only support them in the toplevel. Not worth the pain.
addInstr(s, new RecordEndBlockInstr(topLevel, endClosure));
s.recordEndBlock(endClosure);
addInstr(s, new RecordEndBlockInstr(topLevel, new WrappedIRClosure(s.getSelf(), endClosure)));
return manager.getNil();
}

7 changes: 7 additions & 0 deletions core/src/main/java/org/jruby/ir/IREvalScript.java
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

import org.jruby.EvalType;
import org.jruby.RubyModule;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.interpreter.BeginEndInterpreterContext;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.ClosureLocalVariable;
@@ -56,6 +58,11 @@ public IREvalScript(IRManager manager, IRScope lexicalParent, String fileName,
}
}

@Override
public InterpreterContext allocateInterpreterContext(Instr[] instructionList) {
return new BeginEndInterpreterContext(this, instructionList);
}

@Override
public Label getNewLabel() {
return getNewLabel("EV" + closureId + "_LBL");
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -1120,12 +1120,12 @@ public void inlineMethod(IRScope method, RubyModule implClass, int classToken, B
}
}

/* Record a begin block -- not all scope implementations can handle them */
/** Record a begin block. Only eval and script body scopes support this */
public void recordBeginBlock(IRClosure beginBlockClosure) {
throw new RuntimeException("BEGIN blocks cannot be added to: " + this.getClass().getName());
}

/* Record an end block -- not all scope implementations can handle them */
/* Record an end block. Only eval and script body scopes support this */
public void recordEndBlock(IRClosure endBlockClosure) {
throw new RuntimeException("END blocks cannot be added to: " + this.getClass().getName());
}
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/IRScriptBody.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.jruby.ir;

import org.jruby.ir.instructions.Instr;
import org.jruby.ir.interpreter.BeginEndInterpreterContext;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.interpreter.ScriptBodyInterpreterContext;
import org.jruby.parser.StaticScope;

import java.util.ArrayList;
@@ -22,7 +22,7 @@ public IRScriptBody(IRManager manager, String sourceName, StaticScope staticScop

@Override
public InterpreterContext allocateInterpreterContext(Instr[] instructionList) {
return new ScriptBodyInterpreterContext(this, instructionList);
return new BeginEndInterpreterContext(this, instructionList);
}

@Override
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ public Operand[] getOperands() {

@Override
public String toString() {
return getOperation().toString() + "(" + ", " + getNewName() + ", " + getOldName() + ")";
return getOperation().toString() + "(" + getNewName() + ", " + getOldName() + ")";
}

@Override
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ public Instr clone(CloneInfo ii) {

@Override
public String toString() {
return "" + getOperation() + "()";
return "" + getOperation();
}

@Override
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.jruby.ir.instructions;

import org.jruby.ir.*;
import org.jruby.ir.interpreter.BeginEndInterpreterContext;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.WrappedIRClosure;
import org.jruby.ir.transformations.inlining.CloneInfo;

public class RecordEndBlockInstr extends Instr implements FixedArityInstr {
private final IRScope declaringScope;
private final IRClosure endBlockClosure;
private final WrappedIRClosure endBlockClosure;

public RecordEndBlockInstr(IRScope declaringScope, IRClosure endBlockClosure) {
public RecordEndBlockInstr(IRScope declaringScope, WrappedIRClosure endBlockClosure) {
super(Operation.RECORD_END_BLOCK);

this.declaringScope = declaringScope;
@@ -19,18 +21,18 @@ public IRScope getDeclaringScope() {
return declaringScope;
}

public IRClosure getEndBlockClosure() {
public WrappedIRClosure getEndBlockClosure() {
return endBlockClosure;
}

@Override
public Operand[] getOperands() {
return EMPTY_OPERANDS;
return new Operand[] { endBlockClosure };
}

@Override
public String toString() {
return getOperation().toString() + "(" + endBlockClosure.getName() + ")";
return getOperation().toString() + "(" + endBlockClosure + ")";
}

@Override
@@ -42,11 +44,11 @@ public boolean computeScopeFlags(IRScope scope) {
@Override
public Instr clone(CloneInfo ii) {
// SSS FIXME: Correct in all situations??
return new RecordEndBlockInstr(declaringScope, endBlockClosure);
return new RecordEndBlockInstr(declaringScope, (WrappedIRClosure) endBlockClosure.cloneForInlining(ii));
}

public void interpret() {
declaringScope.getTopLevelScope().recordEndBlock(endBlockClosure);
((BeginEndInterpreterContext) declaringScope.getTopLevelScope().getInterpreterContext()).recordEndBlock(endBlockClosure);
}

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.jruby.ir.interpreter;

import java.util.ArrayList;
import java.util.List;
import org.jruby.ir.IRClosure;
import org.jruby.ir.IRScope;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.operands.WrappedIRClosure;

/**
* Script body and Evals both have begin/end bodies and need the same state
* to interpret.
*/
public class BeginEndInterpreterContext extends InterpreterContext {
private List<IRClosure> beginBlocks;
private List<WrappedIRClosure> endBlocks = null;

public BeginEndInterpreterContext(IRScope scope, Instr[] instructions) {
super(scope, instructions);

beginBlocks = scope.getBeginBlocks();
}

public void recordEndBlock(WrappedIRClosure block) {
if (endBlocks == null) endBlocks = new ArrayList<>();

if (!endBlocks.contains(block)) endBlocks.add(block);
}

public List<IRClosure> getBeginBlocks() {
return beginBlocks;
}

public List<WrappedIRClosure> getEndBlocks() {
return endBlocks;
}
}
23 changes: 18 additions & 5 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
@@ -75,14 +75,19 @@ private static IRScope getEvalContainerScope(StaticScope evalScope) {
return s;
}

/**
* Note: Currently a unique item in that we always interpret evals. If we ever implement an eval
* cache then this should be migrated to use an eval interpreter context and save off things like
* their begin/end blocks so that the eval can eventually be JIT'd.
*/
public static IRubyObject interpretCommonEval(Ruby runtime, String file, int lineNumber, String backtraceName, RootNode rootNode, IRubyObject self, Block block, EvalType evalType) {
StaticScope ss = rootNode.getStaticScope();
IRScope containingIRScope = getEvalContainerScope(ss);
IREvalScript evalScript = IRBuilder.createIRBuilder(runtime, runtime.getIRManager()).buildEvalRoot(ss, containingIRScope, file, lineNumber, rootNode, evalType);
// ClosureInterpreterContext never retrieved as an operand in this context.
// So, self operand is not required here.
// Passing null to force early crasher if ever used differently.
evalScript.prepareForInterpretation();
BeginEndInterpreterContext ic = (BeginEndInterpreterContext) evalScript.prepareForInterpretation();
ThreadContext context = runtime.getCurrentContext();

IRubyObject rv = null;
@@ -103,7 +108,7 @@ public static IRubyObject interpretCommonEval(Ruby runtime, String file, int lin
runBeginEndBlocks(evalScript.getBeginBlocks(), context, self, ss, null); // FIXME: No temp vars yet right?
rv = evalScript.call(context, self, evalScript.getStaticScope().getModule(), s, block, backtraceName);
} finally {
runBeginEndBlocks(evalScript.getEndBlocks(), context, self, ss, null); // FIXME: No temp vars right?
runEndBlocks(ic.getEndBlocks(), context, self, ss, null); // FIXME: No temp vars right?
s.clearEvalType();
context.popScope();
}
@@ -129,9 +134,17 @@ public static void runBeginEndBlocks(List<IRClosure> beBlocks, ThreadContext con
}
}

public static void runEndBlocks(List<WrappedIRClosure> blocks, ThreadContext context, IRubyObject self, StaticScope currScope, Object[] temp) {
if (blocks == null) return;

for (WrappedIRClosure block: blocks) {
((Block) block.retrieve(context, self, currScope, context.getCurrentScope(), temp)).yield(context, null);
}
}

@Override
protected IRubyObject execute(Ruby runtime, IRScriptBody irScope, IRubyObject self) {
ScriptBodyInterpreterContext ic = (ScriptBodyInterpreterContext) irScope.prepareForInterpretation();
BeginEndInterpreterContext ic = (BeginEndInterpreterContext) irScope.prepareForInterpretation();
ThreadContext context = runtime.getCurrentContext();
String name = "(root)";

@@ -155,14 +168,14 @@ protected IRubyObject execute(Ruby runtime, IRScriptBody irScope, IRubyObject se
context.setCurrentVisibility(Visibility.PRIVATE);

try {
Interpreter.runBeginEndBlocks(irScope.getBeginBlocks(), context, self, scope, null);
Interpreter.runBeginEndBlocks(ic.getBeginBlocks(), context, self, scope, null);
retVal = Interpreter.INTERPRET_ROOT(context, self, ic, currModule, name);

Interpreter.dumpStats();
} catch (IRBreakJump bj) {
throw IRException.BREAK_LocalJumpError.getException(context.runtime);
} finally {
Interpreter.runBeginEndBlocks(irScope.getEndBlocks(), context, self, scope, null);
Interpreter.runEndBlocks(ic.getEndBlocks(), context, self, scope, null);
if (!ic.isDynscopeEliminated()) context.popScope();
}

Original file line number Diff line number Diff line change
@@ -143,7 +143,7 @@ public String toString() {
buf.append(fileName).append(':').append(lineNumber);
if (name != null) buf.append(' ').append(name);

buf.append("\nCFG:\n").append(cfg);
buf.append("\nCFG:\n").append(cfg.toStringInstrs());

return buf.toString();
}
Loading