Skip to content

Commit

Permalink
JIT support for BEGIN and END.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Dec 22, 2014
1 parent 58ca80d commit a15af3e
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 6 deletions.
6 changes: 6 additions & 0 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2917,6 +2917,9 @@ public Operand buildPostExe(PostExeNode postExeNode, IRScope s) {
closureBuilder.addInstr(endClosure, new CopyInstr(endClosure.getCurrentModuleVariable(), new ScopeModule(0)));
closureBuilder.build(postExeNode.getBodyNode(), endClosure);

// END does not have either explicit or implicit return, so we add one
closureBuilder.addInstr(endClosure, new ReturnInstr(new Nil()));

// Add an instruction in 's' to record the end block in the 'topLevel' scope.
// 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
Expand All @@ -2936,6 +2939,9 @@ public Operand buildPreExe(PreExeNode preExeNode, IRScope s) {
closureBuilder.addInstr(beginClosure, new CopyInstr(beginClosure.getCurrentModuleVariable(), new ScopeModule(0)));
closureBuilder.build(preExeNode.getBodyNode(), beginClosure);

// BEGIN does not have either explicit or implicit return, so we add one
closureBuilder.addInstr(beginClosure, new ReturnInstr(new Nil()));

// Record the begin block at IR build time
s.getTopLevelScope().recordBeginBlock(beginClosure);
return manager.getNil();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Block;
Expand Down Expand Up @@ -55,7 +55,7 @@ public Instr clone(CloneInfo ii) {
@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
Block blk = (Block) endBlockClosure.retrieve(context, self, currScope, context.getCurrentScope(), temp);
context.runtime.pushExitBlock(context.runtime.newProc(Block.Type.LAMBDA, blk));
IRRuntimeHelpers.pushExitBlock(context, blk);
return null;
}

Expand Down
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
}

// Control should never get here!
// SSS FIXME: But looks like BEGIN/END blocks get here -- needs fixing
return null;
throw context.runtime.newRuntimeError("BUG: interpreter fell through to end unexpectedly");
}

/*
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -1287,4 +1287,9 @@ public static IRubyObject irNot(ThreadContext context, IRubyObject obj) {
public static RaiseException newRequiredKeywordArgumentError(ThreadContext context, String name) {
return context.runtime.newArgumentError("missing keyword: " + name);
}

@JIT
public static void pushExitBlock(ThreadContext context, Block blk) {
context.runtime.pushExitBlock(context.runtime.newProc(Block.Type.LAMBDA, blk));
}
}
11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,17 @@ public void ReceiveSelfInstr(ReceiveSelfInstr receiveselfinstr) {
jvmStoreLocal(receiveselfinstr.getResult());
}

@Override
public void RecordEndBlockInstr(RecordEndBlockInstr recordEndBlockInstr) {
jvmMethod().loadContext();

jvmMethod().loadContext();
visit(recordEndBlockInstr.getEndBlockClosure());
jvmMethod().invokeIRHelper("getBlockFromObject", sig(Block.class, ThreadContext.class, Object.class));

jvmMethod().invokeIRHelper("pushExitBlock", sig(void.class, ThreadContext.class, Block.class));
}

@Override
public void ReqdArgMultipleAsgnInstr(ReqdArgMultipleAsgnInstr reqdargmultipleasgninstr) {
jvmMethod().loadContext();
Expand Down
4 changes: 2 additions & 2 deletions spec/compiler/general_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -670,12 +670,12 @@ def self.remove; remove_method :gh1239; end
run("def foo; yield; end; x = false; foo { break 5 if x; begin; ensure; x = true; redo; end; break 6}") {|result| expect(result).to eq 5 }
end

it "compiles END BLocks", pending: "JIT support" do
it "compiles END Blocks" do
# END block
expect { run("END {}"){} }.to_not raise_error
end

it "compiles BEGIN blocks", pending: "JIT support" do
it "compiles BEGIN blocks" do
# BEGIN block
run("BEGIN { $begin = 5 }; $begin") {|result| expect(result).to eq 5 }
end
Expand Down

0 comments on commit a15af3e

Please sign in to comment.