Created
January 9, 2015 20:14
-
-
Save headius/5be78335c9dd9121fe15 to your computer and use it in GitHub Desktop.
Switching closure instrs to operands for jruby/jruby#2447.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 7fcd16e2e39fc6319c67f83a96f999eef916384e | |
Author: Charles Oliver Nutter <headius@headius.com> | |
Date: Fri Jan 9 14:10:14 2015 -0600 | |
Switch closure loads to operands. | |
LoadImplicitClosure = PassedBlock, for the directly-passed block. | |
LoadFrameCLosure = ImplicitBlock for the implicitly-passed block. | |
Note that this patch does not quite work; unresolved_super ends up | |
with PassedBlock as an operand, but since Operand#retrieve does | |
not get the passed block, it can't be returned. | |
diff --git a/core/src/main/java/org/jruby/ir/IRBuilder.java b/core/src/main/java/org/jruby/ir/IRBuilder.java | |
index b9e4ddf..ef0cbe2 100644 | |
--- a/core/src/main/java/org/jruby/ir/IRBuilder.java | |
+++ b/core/src/main/java/org/jruby/ir/IRBuilder.java | |
@@ -1844,8 +1844,7 @@ public class IRBuilder { | |
Variable blockVar = s.getLocalVariable(blockArgName, 0); | |
if (s instanceof IRMethod) ((IRMethod) s).addArgDesc(IRMethodArgs.ArgType.block, blockArgName); | |
Variable tmp = s.createTemporaryVariable(); | |
- addInstr(s, new LoadImplicitClosureInstr(tmp)); | |
- addInstr(s, new ReifyClosureInstr(blockVar, tmp)); | |
+ addInstr(s, new ReifyClosureInstr(blockVar, PassedBlock.INSTANCE)); | |
} | |
} | |
@@ -1861,9 +1860,9 @@ public class IRBuilder { | |
// used for yields; metaclass body (sclass) inherits yield var from surrounding, and accesses it as implicit | |
if (s instanceof IRMethod || s instanceof IRMetaClassBody) { | |
- addInstr(s, new LoadImplicitClosureInstr(s.getYieldClosureVariable())); | |
+ addInstr(s, new CopyInstr(s.getYieldClosureVariable(), PassedBlock.INSTANCE)); | |
} else { | |
- addInstr(s, new LoadFrameClosureInstr(s.getYieldClosureVariable())); | |
+ addInstr(s, new CopyInstr(s.getYieldClosureVariable(), ImplicitBlock.INSTANCE)); | |
} | |
} | |
diff --git a/core/src/main/java/org/jruby/ir/IRVisitor.java b/core/src/main/java/org/jruby/ir/IRVisitor.java | |
index d00a733..277e8a7 100644 | |
--- a/core/src/main/java/org/jruby/ir/IRVisitor.java | |
+++ b/core/src/main/java/org/jruby/ir/IRVisitor.java | |
@@ -73,8 +73,6 @@ public abstract class IRVisitor { | |
public void LexicalSearchConstInstr(LexicalSearchConstInstr lexicalsearchconstinstr) { error(lexicalsearchconstinstr); } | |
public void LineNumberInstr(LineNumberInstr linenumberinstr) { error(linenumberinstr); } | |
public void LoadLocalVarInstr(LoadLocalVarInstr loadlocalvarinstr) { error(loadlocalvarinstr); } | |
- public void LoadImplicitClosure(LoadImplicitClosureInstr loadimplicitclosureinstr) { error(loadimplicitclosureinstr); } | |
- public void LoadFrameClosure(LoadFrameClosureInstr loadframeclosureinstr) { error(loadframeclosureinstr); } | |
public void Match2Instr(Match2Instr match2instr) { error(match2instr); } | |
public void Match3Instr(Match3Instr match3instr) { error(match3instr); } | |
public void MatchInstr(MatchInstr matchinstr) { error(matchinstr); } | |
@@ -161,12 +159,14 @@ public abstract class IRVisitor { | |
public void GlobalVariable(GlobalVariable globalvariable) { error(globalvariable); } | |
public void Hash(Hash hash) { error(hash); } | |
public void IRException(IRException irexception) { error(irexception); } | |
+ public void ImplicitBlock(ImplicitBlock implicitblock) { error(implicitblock); } | |
public void Label(Label label) { error(label); } | |
public void LocalVariable(LocalVariable localvariable) { error(localvariable); } | |
public void Nil(Nil nil) { error(nil); } | |
public void NthRef(NthRef nthref) { error(nthref); } | |
public void NullBlock(NullBlock nullblock) { error(nullblock); } | |
public void ObjectClass(ObjectClass objectclass) { error(objectclass); } | |
+ public void PassedBlock(PassedBlock passedBlock) { error(passedBlock); } | |
public void Rational(Rational rational) { error(rational); } | |
public void Regexp(Regexp regexp) { error(regexp); } | |
public void ScopeModule(ScopeModule scopemodule) { error(scopemodule); } | |
diff --git a/core/src/main/java/org/jruby/ir/instructions/LoadFrameClosureInstr.java b/core/src/main/java/org/jruby/ir/instructions/LoadFrameClosureInstr.java | |
deleted file mode 100644 | |
index 90929d7..0000000 | |
--- a/core/src/main/java/org/jruby/ir/instructions/LoadFrameClosureInstr.java | |
+++ /dev/null | |
@@ -1,62 +0,0 @@ | |
-package org.jruby.ir.instructions; | |
- | |
-import org.jruby.ir.IRVisitor; | |
-import org.jruby.ir.Operation; | |
-import org.jruby.ir.operands.Operand; | |
-import org.jruby.ir.operands.Variable; | |
-import org.jruby.ir.operands.WrappedIRClosure; | |
-import org.jruby.ir.transformations.inlining.CloneInfo; | |
-import org.jruby.ir.transformations.inlining.InlineCloneInfo; | |
-import org.jruby.ir.transformations.inlining.SimpleCloneInfo; | |
- | |
-/** | |
- * Load the block passed to this scope via the on-heap frame (or similar cross-call structure). | |
- * This is typically used to access the "yieldable" target for blocks and evals. Only used | |
- * when within a scope that will use an on-heap frame. | |
- */ | |
-public class LoadFrameClosureInstr extends Instr implements ResultInstr, FixedArityInstr { | |
- private Variable result; | |
- | |
- public LoadFrameClosureInstr(Variable result) { | |
- super(Operation.LOAD_FRAME_CLOSURE); | |
- | |
- assert result != null : "LoadFrameClosureInstr result is null"; | |
- | |
- this.result = result; | |
- } | |
- | |
- @Override | |
- public Operand[] getOperands() { | |
- return EMPTY_OPERANDS; | |
- } | |
- | |
- @Override | |
- public Variable getResult() { | |
- return result; | |
- } | |
- | |
- @Override | |
- public void updateResult(Variable v) { | |
- this.result = v; | |
- } | |
- | |
- @Override | |
- public Instr clone(CloneInfo info) { | |
- if (info instanceof SimpleCloneInfo) return new LoadFrameClosureInstr(info.getRenamedVariable(result)); | |
- | |
- // SSS FIXME: This code below is for inlining and is untested. | |
- | |
- InlineCloneInfo ii = (InlineCloneInfo) info; | |
- | |
- // SSS FIXME: This is not strictly correct -- we have to wrap the block into an | |
- // operand type that converts the static code block to a proc which is a closure. | |
- if (ii.getCallClosure() instanceof WrappedIRClosure) return NopInstr.NOP; | |
- | |
- return new CopyInstr(ii.getRenamedVariable(result), ii.getCallClosure()); | |
- } | |
- | |
- @Override | |
- public void visit(IRVisitor visitor) { | |
- visitor.LoadFrameClosure(this); | |
- } | |
-} | |
diff --git a/core/src/main/java/org/jruby/ir/instructions/LoadImplicitClosureInstr.java b/core/src/main/java/org/jruby/ir/instructions/LoadImplicitClosureInstr.java | |
deleted file mode 100644 | |
index 4cfe706..0000000 | |
--- a/core/src/main/java/org/jruby/ir/instructions/LoadImplicitClosureInstr.java | |
+++ /dev/null | |
@@ -1,61 +0,0 @@ | |
-package org.jruby.ir.instructions; | |
- | |
-import org.jruby.ir.IRVisitor; | |
-import org.jruby.ir.Operation; | |
-import org.jruby.ir.operands.Operand; | |
-import org.jruby.ir.operands.Variable; | |
-import org.jruby.ir.operands.WrappedIRClosure; | |
-import org.jruby.ir.transformations.inlining.CloneInfo; | |
-import org.jruby.ir.transformations.inlining.InlineCloneInfo; | |
-import org.jruby.ir.transformations.inlining.SimpleCloneInfo; | |
- | |
-/** | |
- * Load the "implicit" closure for this scope. Currently this is always the "block" passed | |
- * to a body of code on the JVM stack. | |
- */ | |
-public class LoadImplicitClosureInstr extends Instr implements ResultInstr, FixedArityInstr { | |
- private Variable result; | |
- | |
- public LoadImplicitClosureInstr(Variable result) { | |
- super(Operation.LOAD_IMPLICIT_CLOSURE); | |
- | |
- assert result != null : "LoadImplicitClosureInstr result is null"; | |
- | |
- this.result = result; | |
- } | |
- | |
- @Override | |
- public Operand[] getOperands() { | |
- return EMPTY_OPERANDS; | |
- } | |
- | |
- @Override | |
- public Variable getResult() { | |
- return result; | |
- } | |
- | |
- @Override | |
- public void updateResult(Variable v) { | |
- this.result = v; | |
- } | |
- | |
- @Override | |
- public Instr clone(CloneInfo info) { | |
- if (info instanceof SimpleCloneInfo) return new LoadImplicitClosureInstr(info.getRenamedVariable(result)); | |
- | |
- // SSS FIXME: This code below is for inlining and is untested. | |
- | |
- InlineCloneInfo ii = (InlineCloneInfo) info; | |
- | |
- // SSS FIXME: This is not strictly correct -- we have to wrap the block into an | |
- // operand type that converts the static code block to a proc which is a closure. | |
- if (ii.getCallClosure() instanceof WrappedIRClosure) return NopInstr.NOP; | |
- | |
- return new CopyInstr(ii.getRenamedVariable(result), ii.getCallClosure()); | |
- } | |
- | |
- @Override | |
- public void visit(IRVisitor visitor) { | |
- visitor.LoadImplicitClosure(this); | |
- } | |
-} | |
diff --git a/core/src/main/java/org/jruby/ir/instructions/ProcessModuleBodyInstr.java b/core/src/main/java/org/jruby/ir/instructions/ProcessModuleBodyInstr.java | |
index 68e5d69..309f9ee 100644 | |
--- a/core/src/main/java/org/jruby/ir/instructions/ProcessModuleBodyInstr.java | |
+++ b/core/src/main/java/org/jruby/ir/instructions/ProcessModuleBodyInstr.java | |
@@ -32,7 +32,7 @@ public class ProcessModuleBodyInstr extends Instr implements ResultInstr, FixedA | |
@Override | |
public Operand[] getOperands() { | |
- return new Operand[]{moduleBody,block}; | |
+ return new Operand[]{moduleBody, block}; | |
} | |
@Override | |
@@ -52,6 +52,7 @@ public class ProcessModuleBodyInstr extends Instr implements ResultInstr, FixedA | |
@Override | |
public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) { | |
moduleBody = moduleBody.getSimplifiedOperand(valueMap, force); | |
+ block = block.getSimplifiedOperand(valueMap, force); | |
} | |
@Override | |
diff --git a/core/src/main/java/org/jruby/ir/instructions/ReifyClosureInstr.java b/core/src/main/java/org/jruby/ir/instructions/ReifyClosureInstr.java | |
index 2cb9bfb..a6e92f6 100644 | |
--- a/core/src/main/java/org/jruby/ir/instructions/ReifyClosureInstr.java | |
+++ b/core/src/main/java/org/jruby/ir/instructions/ReifyClosureInstr.java | |
@@ -21,10 +21,10 @@ import java.util.Map; | |
/* Receive the closure argument (either implicit or explicit in Ruby source code) */ | |
public class ReifyClosureInstr extends Instr implements ResultInstr, FixedArityInstr { | |
- private Variable source; | |
+ private Operand source; | |
private Variable result; | |
- public ReifyClosureInstr(Variable result, Variable source) { | |
+ public ReifyClosureInstr(Variable result, Operand source) { | |
super(Operation.REIFY_CLOSURE); | |
assert result != null: "ReceiveClosureInstr result is null"; | |
@@ -43,7 +43,7 @@ public class ReifyClosureInstr extends Instr implements ResultInstr, FixedArityI | |
return new Operand[]{source}; | |
} | |
- public Variable getSource() { | |
+ public Operand getSource() { | |
return source; | |
} | |
@@ -54,7 +54,7 @@ public class ReifyClosureInstr extends Instr implements ResultInstr, FixedArityI | |
@Override | |
public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) { | |
- source = (Variable)source.getSimplifiedOperand(valueMap, force); | |
+ source = source.getSimplifiedOperand(valueMap, force); | |
} | |
@Override | |
@@ -70,7 +70,7 @@ public class ReifyClosureInstr extends Instr implements ResultInstr, FixedArityI | |
@Override | |
public Instr clone(CloneInfo info) { | |
- if (info instanceof SimpleCloneInfo) return new ReifyClosureInstr(info.getRenamedVariable(result), info.getRenamedVariable(source)); | |
+ if (info instanceof SimpleCloneInfo) return new ReifyClosureInstr(info.getRenamedVariable(result), source); | |
// SSS FIXME: This code below is for inlining and is untested. | |
diff --git a/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java b/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java | |
index 22a0f2b..bbb67b5 100644 | |
--- a/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java | |
+++ b/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java | |
@@ -127,7 +127,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
} | |
- private static Object retrieveOp(Operand r, ThreadContext context, IRubyObject self, DynamicScope currDynScope, StaticScope currScope, Object[] temp) { | |
+ private static Object retrieveOp(Operand r, ThreadContext context, IRubyObject self, DynamicScope currDynScope, StaticScope currScope, Object[] temp, Block block) { | |
Object res; | |
if (r instanceof Self) { | |
return self; | |
@@ -135,9 +135,11 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
res = temp[((TemporaryLocalVariable)r).offset]; | |
return res == null ? context.nil : res; | |
} else if (r instanceof LocalVariable) { | |
- LocalVariable lv = (LocalVariable)r; | |
+ LocalVariable lv = (LocalVariable) r; | |
res = currDynScope.getValue(lv.getLocation(), lv.getScopeDepth()); | |
return res == null ? context.nil : res; | |
+ } else if (r instanceof PassedBlock) { // FIXME: hacky to special-case this in interpreter | |
+ return block; | |
} else { | |
return r.retrieve(context, self, currScope, currDynScope, temp); | |
} | |
@@ -264,27 +266,27 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
} | |
- private static void processCall(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, StaticScope currScope, Object[] temp, IRubyObject self) { | |
+ private static void processCall(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, StaticScope currScope, Object[] temp, IRubyObject self, Block block) { | |
Object result; | |
switch(operation) { | |
case CALL_1F: { | |
OneFixnumArgNoBlockCallInstr call = (OneFixnumArgNoBlockCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
result = call.getCallSite().call(context, self, r, call.getFixnumArg()); | |
setResult(temp, currDynScope, call.getResult(), result); | |
break; | |
} | |
case CALL_1D: { | |
OneFloatArgNoBlockCallInstr call = (OneFloatArgNoBlockCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
result = call.getCallSite().call(context, self, r, call.getFloatArg()); | |
setResult(temp, currDynScope, call.getResult(), result); | |
break; | |
} | |
case CALL_1O: { | |
OneOperandArgNoBlockCallInstr call = (OneOperandArgNoBlockCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
IRubyObject o = (IRubyObject)call.getArg1().retrieve(context, self, currScope, currDynScope, temp); | |
result = call.getCallSite().call(context, self, r, o); | |
setResult(temp, currDynScope, call.getResult(), result); | |
@@ -292,7 +294,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
case CALL_1OB: { | |
OneOperandArgBlockCallInstr call = (OneOperandArgBlockCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
IRubyObject o = (IRubyObject)call.getArg1().retrieve(context, self, currScope, currDynScope, temp); | |
Block preparedBlock = call.prepareBlock(context, self, currScope, currDynScope, temp); | |
result = call.getCallSite().call(context, self, r, o, preparedBlock); | |
@@ -301,14 +303,14 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
case CALL_0O: { | |
ZeroOperandArgNoBlockCallInstr call = (ZeroOperandArgNoBlockCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
result = call.getCallSite().call(context, self, r); | |
setResult(temp, currDynScope, call.getResult(), result); | |
break; | |
} | |
case NORESULT_CALL_1O: { | |
OneOperandArgNoBlockNoResultCallInstr call = (OneOperandArgNoBlockNoResultCallInstr)instr; | |
- IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject r = (IRubyObject)retrieveOp(call.getReceiver(), context, self, currDynScope, currScope, temp, block); | |
IRubyObject o = (IRubyObject)call.getArg1().retrieve(context, self, currScope, currDynScope, temp); | |
call.getCallSite().call(context, self, r, o); | |
break; | |
@@ -365,12 +367,12 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
} | |
- private static IRubyObject processReturnOp(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, Object[] temp, IRubyObject self, Block.Type blockType, StaticScope currScope) | |
+ private static IRubyObject processReturnOp(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, Object[] temp, IRubyObject self, Block block, Block.Type blockType, StaticScope currScope) | |
{ | |
switch(operation) { | |
// --------- Return flavored instructions -------- | |
case RETURN: { | |
- return (IRubyObject)retrieveOp(((ReturnBase)instr).getReturnValue(), context, self, currDynScope, currScope, temp); | |
+ return (IRubyObject)retrieveOp(((ReturnBase)instr).getReturnValue(), context, self, currDynScope, currScope, temp, block); | |
} | |
case BREAK: { | |
BreakInstr bi = (BreakInstr)instr; | |
@@ -384,14 +386,14 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
case NONLOCAL_RETURN: { | |
NonlocalReturnInstr ri = (NonlocalReturnInstr)instr; | |
- IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, currScope, temp); | |
+ IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, currScope, temp, block); | |
return IRRuntimeHelpers.initiateNonLocalReturn(context, currDynScope, blockType, rv); | |
} | |
} | |
return null; | |
} | |
- private static void processOtherOp(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, StaticScope currScope, Object[] temp, IRubyObject self, Block.Type blockType, double[] floats, long[] fixnums, boolean[] booleans) | |
+ private static void processOtherOp(ThreadContext context, Instr instr, Operation operation, DynamicScope currDynScope, StaticScope currScope, Object[] temp, IRubyObject self, Block block, Block.Type blockType, double[] floats, long[] fixnums, boolean[] booleans) | |
{ | |
Object result; | |
switch(operation) { | |
@@ -404,7 +406,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} else if (res instanceof TemporaryFixnumVariable) { | |
setFixnumVar(fixnums, (TemporaryFixnumVariable)res, getFixnumArg(fixnums, src)); | |
} else { | |
- setResult(temp, currDynScope, res, retrieveOp(src, context, self, currDynScope, currScope, temp)); | |
+ setResult(temp, currDynScope, res, retrieveOp(src, context, self, currDynScope, currScope, temp, block)); | |
} | |
break; | |
} | |
@@ -465,7 +467,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
case UNBOX_FLOAT: { | |
UnboxInstr ui = (UnboxInstr)instr; | |
- Object val = retrieveOp(ui.getValue(), context, self, currDynScope, currScope, temp); | |
+ Object val = retrieveOp(ui.getValue(), context, self, currDynScope, currScope, temp, block); | |
if (val instanceof RubyFloat) { | |
floats[((TemporaryLocalVariable)ui.getResult()).offset] = ((RubyFloat)val).getValue(); | |
} else { | |
@@ -476,7 +478,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
case UNBOX_FIXNUM: { | |
UnboxInstr ui = (UnboxInstr)instr; | |
- Object val = retrieveOp(ui.getValue(), context, self, currDynScope, currScope, temp); | |
+ Object val = retrieveOp(ui.getValue(), context, self, currDynScope, currScope, temp, block); | |
if (val instanceof RubyFloat) { | |
fixnums[((TemporaryLocalVariable)ui.getResult()).offset] = ((RubyFloat)val).getLongValue(); | |
} else { | |
@@ -540,10 +542,10 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
break; | |
case CALL_OP: | |
if (profile) Profiler.updateCallSite(instr, scope, scopeVersion); | |
- processCall(context, instr, operation, currDynScope, currScope, temp, self); | |
+ processCall(context, instr, operation, currDynScope, currScope, temp, self, block); | |
break; | |
case RET_OP: | |
- return processReturnOp(context, instr, operation, currDynScope, temp, self, blockType, currScope); | |
+ return processReturnOp(context, instr, operation, currDynScope, temp, self, block, blockType, currScope); | |
case BRANCH_OP: | |
switch (operation) { | |
case JUMP: ipc = ((JumpInstr)instr).getJumpTarget().getTargetPC(); break; | |
@@ -562,7 +564,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> { | |
} | |
break; | |
case OTHER_OP: | |
- processOtherOp(context, instr, operation, currDynScope, currScope, temp, self, blockType, floats, fixnums, booleans); | |
+ processOtherOp(context, instr, operation, currDynScope, currScope, temp, self, block, blockType, floats, fixnums, booleans); | |
break; | |
} | |
} catch (Throwable t) { | |
diff --git a/core/src/main/java/org/jruby/ir/operands/ImplicitBlock.java b/core/src/main/java/org/jruby/ir/operands/ImplicitBlock.java | |
new file mode 100644 | |
index 0000000..eb1c48a | |
--- /dev/null | |
+++ b/core/src/main/java/org/jruby/ir/operands/ImplicitBlock.java | |
@@ -0,0 +1,48 @@ | |
+package org.jruby.ir.operands; | |
+ | |
+import org.jruby.ir.IRVisitor; | |
+import org.jruby.ir.transformations.inlining.CloneInfo; | |
+import org.jruby.parser.StaticScope; | |
+import org.jruby.runtime.DynamicScope; | |
+import org.jruby.runtime.ThreadContext; | |
+import org.jruby.runtime.builtin.IRubyObject; | |
+ | |
+import java.util.List; | |
+ | |
+/** | |
+ * The Block available to this scope via some off-stack structure like a call frame. | |
+ * | |
+ * This is used for yields in blocks and most other non-method forms. | |
+ */ | |
+public class ImplicitBlock extends Operand { | |
+ public static final ImplicitBlock INSTANCE = new ImplicitBlock(); | |
+ | |
+ private ImplicitBlock() { | |
+ super(OperandType.PASSED_BLOCK); | |
+ } | |
+ | |
+ @Override | |
+ public void addUsedVariables(List<Variable> l) { | |
+ /* Nothing to do */ | |
+ } | |
+ | |
+ @Override | |
+ public Operand cloneForInlining(CloneInfo ii) { | |
+ return this; | |
+ } | |
+ | |
+ @Override | |
+ public boolean canCopyPropagate() { | |
+ return true; | |
+ } | |
+ | |
+ @Override | |
+ public Object retrieve(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope currDynScope, Object[] temp) { | |
+ return context.getFrameBlock(); | |
+ } | |
+ | |
+ @Override | |
+ public void visit(IRVisitor visitor) { | |
+ visitor.ImplicitBlock(this); | |
+ } | |
+} | |
diff --git a/core/src/main/java/org/jruby/ir/operands/OperandType.java b/core/src/main/java/org/jruby/ir/operands/OperandType.java | |
index 11c2626..7d0470f 100644 | |
--- a/core/src/main/java/org/jruby/ir/operands/OperandType.java | |
+++ b/core/src/main/java/org/jruby/ir/operands/OperandType.java | |
@@ -47,6 +47,8 @@ public enum OperandType { | |
WRAPPED_IR_CLOSURE((byte) 'w'), | |
FROZEN_STRING((byte) 'z'), | |
NULL_BLOCK((byte) 'o'), | |
+ PASSED_BLOCK((byte) 'p'), | |
+ IMPLICIT_BLOCK((byte) 'i') | |
; | |
private final byte coded; | |
diff --git a/core/src/main/java/org/jruby/ir/operands/PassedBlock.java b/core/src/main/java/org/jruby/ir/operands/PassedBlock.java | |
new file mode 100644 | |
index 0000000..5435fd4 | |
--- /dev/null | |
+++ b/core/src/main/java/org/jruby/ir/operands/PassedBlock.java | |
@@ -0,0 +1,48 @@ | |
+package org.jruby.ir.operands; | |
+ | |
+import org.jruby.ir.IRVisitor; | |
+import org.jruby.ir.transformations.inlining.CloneInfo; | |
+import org.jruby.parser.StaticScope; | |
+import org.jruby.runtime.DynamicScope; | |
+import org.jruby.runtime.ThreadContext; | |
+import org.jruby.runtime.builtin.IRubyObject; | |
+ | |
+import java.util.List; | |
+ | |
+/** | |
+ * The Block passed directly to this scope, as opposed to via an external frame. | |
+ * | |
+ * This is used for yields in normal method bodies, block arguments, etc. | |
+ */ | |
+public class PassedBlock extends Operand { | |
+ public static final PassedBlock INSTANCE = new PassedBlock(); | |
+ | |
+ private PassedBlock() { | |
+ super(OperandType.PASSED_BLOCK); | |
+ } | |
+ | |
+ @Override | |
+ public void addUsedVariables(List<Variable> l) { | |
+ /* Nothing to do */ | |
+ } | |
+ | |
+ @Override | |
+ public Operand cloneForInlining(CloneInfo ii) { | |
+ return this; | |
+ } | |
+ | |
+ @Override | |
+ public boolean canCopyPropagate() { | |
+ return true; | |
+ } | |
+ | |
+ @Override | |
+ public Object retrieve(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope currDynScope, Object[] temp) { | |
+ return super.retrieve(context, self, currScope, currDynScope, temp); | |
+ } | |
+ | |
+ @Override | |
+ public void visit(IRVisitor visitor) { | |
+ visitor.PassedBlock(this); | |
+ } | |
+} | |
diff --git a/core/src/main/java/org/jruby/ir/persistence/OperandDecoderMap.java b/core/src/main/java/org/jruby/ir/persistence/OperandDecoderMap.java | |
index 7e28a25..323ebae 100644 | |
--- a/core/src/main/java/org/jruby/ir/persistence/OperandDecoderMap.java | |
+++ b/core/src/main/java/org/jruby/ir/persistence/OperandDecoderMap.java | |
@@ -41,12 +41,14 @@ class OperandDecoderMap { | |
case FLOAT: return new org.jruby.ir.operands.Float(d.decodeDouble()); | |
case GLOBAL_VARIABLE: return new GlobalVariable(d.decodeString()); | |
case HASH: return decodeHash(); | |
+ case IMPLICIT_BLOCK: return ImplicitBlock.INSTANCE; | |
case IR_EXCEPTION: return IRException.getExceptionFromOrdinal(d.decodeByte()); | |
case LABEL: return decodeLabel(); | |
case LOCAL_VARIABLE: return d.getCurrentScope().getLocalVariable(d.decodeString(), d.decodeInt()); | |
case NIL: return manager.getNil(); | |
case NTH_REF: return new NthRef(d.decodeInt()); | |
case OBJECT_CLASS: return new ObjectClass(); | |
+ case PASSED_BLOCK: return PassedBlock.INSTANCE; | |
case REGEXP: return decodeRegexp(); | |
case SCOPE_MODULE: return new ScopeModule(d.decodeInt()); | |
case SELF: return Self.SELF; | |
diff --git a/core/src/main/java/org/jruby/ir/persistence/OperandEncoderMap.java b/core/src/main/java/org/jruby/ir/persistence/OperandEncoderMap.java | |
index a0cd323..f2420c4 100644 | |
--- a/core/src/main/java/org/jruby/ir/persistence/OperandEncoderMap.java | |
+++ b/core/src/main/java/org/jruby/ir/persistence/OperandEncoderMap.java | |
@@ -65,6 +65,8 @@ class OperandEncoderMap extends IRVisitor { | |
} | |
} | |
+ @Override public void ImplicitBlock(ImplicitBlock implicitblock) {} // No data | |
+ | |
@Override public void IRException(IRException irexception) { encoder.encode((byte) irexception.getType().ordinal()); } | |
@Override public void Label(Label label) { | |
@@ -85,6 +87,8 @@ class OperandEncoderMap extends IRVisitor { | |
@Override public void ObjectClass(ObjectClass objectclass) {} // No data | |
+ @Override public void PassedBlock(PassedBlock passedBlock) {} // No data | |
+ | |
@Override public void Regexp(Regexp regexp) { | |
encode(regexp.getRegexp()); | |
encoder.encode(regexp.options.isEncodingNone()); | |
diff --git a/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java b/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java | |
index c4a258a..727b950 100644 | |
--- a/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java | |
+++ b/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java | |
@@ -1243,19 +1243,6 @@ public class JVMVisitor extends IRVisitor { | |
} | |
@Override | |
- public void LoadImplicitClosure(LoadImplicitClosureInstr loadimplicitclosureinstr) { | |
- jvmMethod().loadBlock(); | |
- jvmStoreLocal(loadimplicitclosureinstr.getResult()); | |
- } | |
- | |
- @Override | |
- public void LoadFrameClosure(LoadFrameClosureInstr loadframeclosureinstr) { | |
- jvmMethod().loadContext(); | |
- jvmAdapter().invokevirtual(p(ThreadContext.class), "getFrameBlock", sig(Block.class)); | |
- jvmStoreLocal(loadframeclosureinstr.getResult()); | |
- } | |
- | |
- @Override | |
public void Match2Instr(Match2Instr match2instr) { | |
visit(match2instr.getReceiver()); | |
jvmMethod().loadContext(); | |
@@ -2067,6 +2054,12 @@ public class JVMVisitor extends IRVisitor { | |
} | |
@Override | |
+ public void ImplicitBlock(ImplicitBlock implicitblock) { | |
+ jvmMethod().loadContext(); | |
+ jvmAdapter().invokevirtual(p(ThreadContext.class), "getFrameBlock", sig(Block.class)); | |
+ } | |
+ | |
+ @Override | |
public void LocalVariable(LocalVariable localvariable) { | |
// CON FIXME: This isn't as efficient as it could be, but we should not see these in optimized JIT scopes | |
jvmLoadLocal(DYNAMIC_SCOPE); | |
@@ -2099,6 +2092,11 @@ public class JVMVisitor extends IRVisitor { | |
} | |
@Override | |
+ public void PassedBlock(PassedBlock passedblock) { | |
+ jvmMethod().loadBlock(); | |
+ } | |
+ | |
+ @Override | |
public void Rational(Rational rational) { | |
jvmMethod().loadRuntime(); | |
jvmAdapter().ldc(rational.getNumerator()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment