Skip to content

Commit

Permalink
Merge branch 'master' into truffle-head
Browse files Browse the repository at this point in the history
Conflicts:
	truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
  • Loading branch information
chrisseaton committed Feb 24, 2015
2 parents f5ba868 + 1e379ff commit 40311ef
Show file tree
Hide file tree
Showing 29 changed files with 870 additions and 248 deletions.
7 changes: 4 additions & 3 deletions core/src/main/java/org/jruby/RubyGlobal.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.jruby.util.KCode;
import org.jruby.util.OSEnvironment;
import org.jruby.util.RegexpOptions;
import org.jruby.util.ShellLauncher;
import org.jruby.util.cli.OutputStrings;
import org.jruby.util.io.BadDescriptorException;
import org.jruby.util.io.OpenFile;
Expand Down Expand Up @@ -191,11 +192,11 @@ public static void createGlobals(ThreadContext context, Ruby runtime) {
runtime.defineVariable(new BacktraceGlobalVariable(runtime, "$@"), THREAD);

IRubyObject stdin = RubyIO.prepStdio(
runtime, runtime.getIn(), prepareStdioChannel(runtime, STDIO.IN, runtime.getIn()), OpenFile.READABLE, runtime.getIO(), "<STDIN>");
runtime, runtime.getIn(), prepareStdioChannel(runtime, STDIO.IN, ShellLauncher.unwrapFilterInputStream(runtime.getIn())), OpenFile.READABLE, runtime.getIO(), "<STDIN>");
IRubyObject stdout = RubyIO.prepStdio(
runtime, runtime.getOut(), prepareStdioChannel(runtime, STDIO.OUT, runtime.getOut()), OpenFile.WRITABLE, runtime.getIO(), "<STDOUT>");
runtime, runtime.getOut(), prepareStdioChannel(runtime, STDIO.OUT, ShellLauncher.unwrapFilterOutputStream(runtime.getOut())), OpenFile.WRITABLE, runtime.getIO(), "<STDOUT>");
IRubyObject stderr = RubyIO.prepStdio(
runtime, runtime.getErr(), prepareStdioChannel(runtime, STDIO.ERR, runtime.getErr()), OpenFile.WRITABLE | OpenFile.SYNC, runtime.getIO(), "<STDERR>");
runtime, runtime.getErr(), prepareStdioChannel(runtime, STDIO.ERR, ShellLauncher.unwrapFilterOutputStream(runtime.getErr())), OpenFile.WRITABLE | OpenFile.SYNC, runtime.getIO(), "<STDERR>");

runtime.defineVariable(new InputGlobalVariable(runtime, "$stdin", stdin), GLOBAL);
runtime.defineVariable(new OutputGlobalVariable(runtime, "$stdout", stdout), GLOBAL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,16 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
if (IRRuntimeHelpers.isDebug()) doDebug();

InterpreterContext ic = ensureInstrsReady();
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} else {
try {
this.pre(ic, context, self, name, block, getImplementationClass());
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} finally {
this.post(ic, context);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.PositionAware;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
Expand Down Expand Up @@ -83,11 +84,35 @@ public Arity getArity() {
return this.arity;
}

protected void post(InterpreterContext ic, ThreadContext context) {
// update call stacks (pop: ..)
context.popFrame();
if (ic.popDynScope()) {
context.popScope();
}
}

protected void pre(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, Block block, RubyModule implClass) {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameOnly(implClass, name, self, block);
if (ic.pushNewDynScope()) {
context.pushScope(DynamicScope.newDynamicScope(ic.getStaticScope()));
}
context.setCurrentVisibility(getVisibility());
}

public InterpreterContext ensureInstrsReady() {
// Try unsync access first before calling more expensive method for getting IC
InterpreterContext ic = method.getInterpreterContext();

return ic == null ? method.prepareForInterpretation() : ic;
// Build/rebuild if necessary
if (ic == null) {
ic = method.prepareForInterpretation();
} else if (ic.needsRebuilding()) {
ic = method.prepareForInterpretation(true);
}

return ic;
}

@Override
Expand All @@ -105,12 +130,21 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

private static IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject[] args, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());

return ic.engine.interpret(context, self, ic, implClass, name, args, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, implClass, name, args, block, null);
} else {
try {
this.pre(ic, context, self, name, block, implClass);
return ic.engine.interpret(context, self, ic, implClass, name, args, block, null);
} finally {
this.post(ic, context);
}
}
} finally {
ThreadContext.popBacktrace(context);
}
Expand All @@ -131,12 +165,21 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

private static IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());

return ic.engine.interpret(context, self, ic, implClass, name, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, implClass, name, block, null);
} else {
try {
this.pre(ic, context, self, name, block, implClass);
return ic.engine.interpret(context, self, ic, implClass, name, block, null);
} finally {
this.post(ic, context);
}
}
} finally {
ThreadContext.popBacktrace(context);
}
Expand All @@ -157,12 +200,21 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

private static IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());

return ic.engine.interpret(context, self, ic, implClass, name, arg1, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, implClass, name, arg1, block, null);
} else {
try {
this.pre(ic, context, self, name, block, implClass);
return ic.engine.interpret(context, self, ic, implClass, name, arg1, block, null);
} finally {
this.post(ic, context);
}
}
} finally {
ThreadContext.popBacktrace(context);
}
Expand All @@ -183,12 +235,21 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

private static IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());

return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, block, null);
} else {
try {
this.pre(ic, context, self, name, block, implClass);
return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, block, null);
} finally {
this.post(ic, context);
}
}
} finally {
ThreadContext.popBacktrace(context);
}
Expand All @@ -209,12 +270,21 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

private static IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());

return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, arg3, block, null);
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, arg3, block, null);
} else {
try {
this.pre(ic, context, self, name, block, implClass);
return ic.engine.interpret(context, self, ic, implClass, name, arg1, arg2, arg3, block, null);
} finally {
this.post(ic, context);
}
}
} finally {
ThreadContext.popBacktrace(context);
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/IRClosure.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ public IRClosure(IRManager manager, IRScope lexicalParent, int lineNumber, Stati
}

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

public void setBeginEndBlock() {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/IREvalScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public IREvalScript(IRManager manager, IRScope lexicalParent, String fileName,
}

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

@Override
Expand Down
98 changes: 84 additions & 14 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
* and so on ...
*/
public abstract class IRScope implements ParseResult {

private static final Logger LOG = LoggerFactory.getLogger("IRScope");

private static AtomicInteger globalScopeCount = new AtomicInteger();
Expand Down Expand Up @@ -139,6 +140,13 @@ public abstract class IRScope implements ParseResult {

private TemporaryVariable yieldClosureVariable;

// What state is this scope in?
enum ScopeState {
INIT, INTERPED, INSTRS_CLONED, CFG_BUILT
};

private ScopeState state = ScopeState.INIT;

// Used by cloning code
protected IRScope(IRScope s, IRScope lexicalParent) {
this.lexicalParent = lexicalParent;
Expand All @@ -163,6 +171,7 @@ protected IRScope(IRScope s, IRScope lexicalParent) {

this.localVars = new HashMap<String, LocalVariable>(s.localVars);
this.scopeId = globalScopeCount.getAndIncrement();
this.state = ScopeState.INIT; // SSS FIXME: Is this correct?

this.executedPasses = new ArrayList<CompilerPass>();

Expand Down Expand Up @@ -208,6 +217,7 @@ public IRScope(IRManager manager, IRScope lexicalParent, String name,

this.localVars = new HashMap<String, LocalVariable>();
this.scopeId = globalScopeCount.getAndIncrement();
this.state = ScopeState.INIT;

this.executedPasses = new ArrayList<CompilerPass>();

Expand Down Expand Up @@ -448,9 +458,10 @@ public CFG buildCFG() {
CFG newCFG = new CFG(this);
newCFG.build(getInstrs());
// Clear out instruction list after CFG has been built.
this.instrList = null;
instrList = null;

setCFG(newCFG);
state = ScopeState.CFG_BUILT;

return newCFG;
}
Expand All @@ -465,6 +476,20 @@ public CFG getCFG() {

@Interp
protected Instr[] prepareInstructions() {
if (getCFG() == null) {
int n = instrList.size();
Instr[] linearizedInstrArray = instrList.toArray(new Instr[n]);
for (int ipc = 0; ipc < n; ipc++) {
Instr i = linearizedInstrArray[ipc];
i.setIPC(ipc);
if (i instanceof LabelInstr) {
((LabelInstr)i).getLabel().setTargetPC(ipc+1);
}
}

return linearizedInstrArray;
}

setupLinearization();

boolean simple_method = this instanceof IRMethod;
Expand Down Expand Up @@ -584,6 +609,19 @@ private void optimizeSimpleScopes() {
}

protected void initScope(boolean jitMode) {
// FIXME: This is messy and prepareForInterpretation and prepareForCompilation need to
// clean up the lifecycle aspects of creating CFG from instrList and running passes in
// a consistent and predictable way. This is a hack atm to unbreak the fact JIT
// may happen before IC.build count and thus not have cloned the instrs (which then
// modifies instrs IC is using causing weird blowups.
//
// If the scope has already been interpreted once,
// the scope can be on the call stack right now.
// So, clone instructions before modifying them!
if (state != ScopeState.INIT && getCFG() == null) {
cloneInstrs();
}

runCompilerPasses(getManager().getCompilerPasses(this));

if (!jitMode && RubyInstanceConfig.IR_COMPILER_PASSES == null) {
Expand All @@ -603,26 +641,58 @@ protected void initScope(boolean jitMode) {
}

/** Make version specific to scope which needs it (e.g. Closure vs non-closure). */
public InterpreterContext allocateInterpreterContext(Instr[] instructionList) {
return new InterpreterContext(this, instructionList);
public InterpreterContext allocateInterpreterContext(Instr[] instructionList, boolean rebuild) {
return new InterpreterContext(this, instructionList, rebuild);
}

/** Run any necessary passes to get the IR ready for interpretation */
public synchronized InterpreterContext prepareForInterpretation() {
if (interpreterContext != null) return interpreterContext; // Already prepared
public InterpreterContext prepareForInterpretation() {
return prepareForInterpretation(false);
}

protected void cloneInstrs() {
cloneInstrs(new SimpleCloneInfo(this, false));
}

initScope(false);
protected void cloneInstrs(SimpleCloneInfo cloneInfo) {
// FIXME: not cloning if we happen to have a CFG violates the spirit of this method name.
// We do this currently because in a scenario where a nested closure is called much more than
// an outer scope we will process that closure first independently. If at a later point we
// process the outer scope then the inner scope will have nuked instrList and explode if we
// try to clone the non-existent instrList.
if (getCFG() != null) return;

List<Instr> newInstrList = new ArrayList<>(instrList.size());

for (Instr instr: this.instrList) {
newInstrList.add(instr.clone(cloneInfo));
}

// System.out.println("-- passes run for: " + this + " = " + java.util.Arrays.toString(executedPasses.toArray()));
instrList = newInstrList;
state = ScopeState.INSTRS_CLONED;
for (IRClosure cl : getClosures()) {
cl.cloneInstrs(cloneInfo.cloneForCloningClosure(cl));
}
}

// Always add call protocol instructions now for both interpreter and JIT
// since we are removing support for implicit stuff in the interpreter.
// When JIT later runs this same pass, it will be a NOP there.
if (!isUnsafeScope()) {
(new AddCallProtocolInstructions()).run(this);
/** Run any necessary passes to get the IR ready for interpretation */
public synchronized InterpreterContext prepareForInterpretation(boolean rebuild) {
if (interpreterContext == null) {
this.state = ScopeState.INTERPED;
} else if (!rebuild || getCFG() != null) {
return interpreterContext; // Already prepared/rebuilt
} else {
// Build CFG, run passes, etc.
initScope(false);

// Always add call protocol instructions now for both interpreter and JIT
// since we are removing support for implicit stuff in the interpreter.
// When JIT later runs this same pass, it will be a NOP there.
if (!isUnsafeScope()) {
(new AddCallProtocolInstructions()).run(this);
}
}

interpreterContext = allocateInterpreterContext(prepareInstructions());
interpreterContext = allocateInterpreterContext(prepareInstructions(), rebuild);

return interpreterContext;
}
Expand Down
Loading

0 comments on commit 40311ef

Please sign in to comment.