From d807cb25e3418f7874bcff5bf274ba123b4b1071 Mon Sep 17 00:00:00 2001 From: Subramanya Sastry Date: Sat, 28 Nov 2015 22:21:14 -0600 Subject: [PATCH] Added one more instruction towards IR-instr based block invocation * Hooked up with interpreter. --- .../src/main/java/org/jruby/ir/IRVisitor.java | 1 + .../src/main/java/org/jruby/ir/Operation.java | 3 +- .../UpdateBlockExecutionStateInstr.java | 43 +++++++++++++++++++ .../ir/interpreter/InterpreterEngine.java | 10 +++++ .../jruby/ir/runtime/IRRuntimeHelpers.java | 9 ++++ .../main/java/org/jruby/runtime/Block.java | 5 +++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/jruby/ir/instructions/UpdateBlockExecutionStateInstr.java diff --git a/core/src/main/java/org/jruby/ir/IRVisitor.java b/core/src/main/java/org/jruby/ir/IRVisitor.java index 9c0cd9d2af2..ef72f09c72d 100644 --- a/core/src/main/java/org/jruby/ir/IRVisitor.java +++ b/core/src/main/java/org/jruby/ir/IRVisitor.java @@ -125,6 +125,7 @@ private void error(Object object) { public void ToAryInstr(ToAryInstr toaryinstr) { error(toaryinstr); } public void UndefMethodInstr(UndefMethodInstr undefmethodinstr) { error(undefmethodinstr); } public void UnresolvedSuperInstr(UnresolvedSuperInstr unresolvedsuperinstr) { error(unresolvedsuperinstr); } + public void UpdateBlockExecutionStateInstr (UpdateBlockExecutionStateInstr instr) { error(instr); } public void YieldInstr(YieldInstr yieldinstr) { error(yieldinstr); } public void ZeroOperandArgNoBlockCallInstr(ZeroOperandArgNoBlockCallInstr zeroOperandArgNoBlockCallInstr) { error(zeroOperandArgNoBlockCallInstr); } public void ZSuperInstr(ZSuperInstr zsuperinstr) { error(zsuperinstr); } diff --git a/core/src/main/java/org/jruby/ir/Operation.java b/core/src/main/java/org/jruby/ir/Operation.java index ba6162801b2..8368ff93550 100644 --- a/core/src/main/java/org/jruby/ir/Operation.java +++ b/core/src/main/java/org/jruby/ir/Operation.java @@ -213,7 +213,8 @@ public enum Operation { POP_BINDING(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect), SAVE_BINDING_VIZ(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect), RESTORE_BINDING_VIZ(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect), - TOGGLE_BACKTRACE(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect); + TOGGLE_BACKTRACE(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect), + UPDATE_BLOCK_STATE(OpFlags.f_is_book_keeping_op | OpFlags.f_has_side_effect); public final OpClass opClass; private int flags; diff --git a/core/src/main/java/org/jruby/ir/instructions/UpdateBlockExecutionStateInstr.java b/core/src/main/java/org/jruby/ir/instructions/UpdateBlockExecutionStateInstr.java new file mode 100644 index 00000000000..ac08a3a0756 --- /dev/null +++ b/core/src/main/java/org/jruby/ir/instructions/UpdateBlockExecutionStateInstr.java @@ -0,0 +1,43 @@ +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.persistence.IRReaderDecoder; +import org.jruby.ir.persistence.IRWriterEncoder; +import org.jruby.ir.transformations.inlining.CloneInfo; +import org.jruby.ir.transformations.inlining.SimpleCloneInfo; + +/* Generic placeholder instruction for miscellaneous stuff that + * needs to be done before a block's coded is executed. + * Eventually, this should hopefully get folded away into other things. + */ +public class UpdateBlockExecutionStateInstr extends OneOperandInstr implements FixedArityInstr { + public UpdateBlockExecutionStateInstr(Operand self) { + super(Operation.UPDATE_BLOCK_STATE, self); + } + + public Operand getSelf() { + return getOperand1(); + } + + @Override + public Instr clone(CloneInfo ii) { + return ii instanceof SimpleCloneInfo ? this : NopInstr.NOP; // FIXME: Is this correct? + } + + public static UpdateBlockExecutionStateInstr decode(IRReaderDecoder d) { + return new UpdateBlockExecutionStateInstr(d.decodeVariable()); + } + + @Override + public void encode(IRWriterEncoder e) { + super.encode(e); + e.encode(getSelf()); + } + + @Override + public void visit(IRVisitor visitor) { + visitor.UpdateBlockExecutionStateInstr(this); + } +} diff --git a/core/src/main/java/org/jruby/ir/interpreter/InterpreterEngine.java b/core/src/main/java/org/jruby/ir/interpreter/InterpreterEngine.java index 78eade2ee4f..473cdfcd9b5 100644 --- a/core/src/main/java/org/jruby/ir/interpreter/InterpreterEngine.java +++ b/core/src/main/java/org/jruby/ir/interpreter/InterpreterEngine.java @@ -58,6 +58,7 @@ import org.jruby.ir.runtime.IRRuntimeHelpers; import org.jruby.parser.StaticScope; import org.jruby.EvalType; +import org.jruby.runtime.Binding; import org.jruby.runtime.Block; import org.jruby.runtime.DynamicScope; import org.jruby.runtime.Frame; @@ -186,6 +187,15 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel context.pushScope(currDynScope); } else if (operation == Operation.PUSH_BLOCK_BINDING) { currDynScope = getBlockScope(context, block, interpreterContext); + } else if (operation == Operation.UPDATE_BLOCK_STATE) { + if (self == null || block.getEvalType() == EvalType.BINDING_EVAL) { + // Update self to the binding's self + Binding b = block.getBinding(); + self = b.getSelf(); + b.getFrame().setSelf(self); + } + // Clear block's eval type + block.setEvalType(EvalType.NONE); } else { processBookKeepingOp(context, block, instr, operation, name, args, self, blockArg, implClass, currDynScope, temp, currScope); } diff --git a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java index 00b20263e55..75d5685a3a9 100644 --- a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java +++ b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java @@ -14,6 +14,7 @@ import org.jruby.internal.runtime.methods.InterpretedIRMethod; import org.jruby.internal.runtime.methods.MixedModeIRMethod; import org.jruby.internal.runtime.methods.UndefinedMethod; +import org.jruby.ir.IRFlags; import org.jruby.ir.IRManager; import org.jruby.ir.IRMetaClassBody; import org.jruby.ir.IRScope; @@ -450,6 +451,14 @@ public static IRubyObject yield(ThreadContext context, Object blk, Object yieldA return (unwrapArray && (yieldVal instanceof RubyArray)) ? b.yieldArray(context, yieldVal, null) : b.yield(context, yieldVal); } + private boolean blockHasExplicitCallProtocol(Block block) { + if (block.getBody() instanceof IRBlockBody) { + return ((IRBlockBody)block.getBody()).getScope().getFlags().contains(IRFlags.HAS_EXPLICIT_CALL_PROTOCOL); + } else { + return false; + } + } + public static IRubyObject yieldSpecific(ThreadContext context, Object blk) { if (blk instanceof RubyProc) blk = ((RubyProc)blk).getBlock(); if (blk instanceof RubyNil) blk = Block.NULL_BLOCK; diff --git a/core/src/main/java/org/jruby/runtime/Block.java b/core/src/main/java/org/jruby/runtime/Block.java index ccb9513a612..8bac9eb90f9 100644 --- a/core/src/main/java/org/jruby/runtime/Block.java +++ b/core/src/main/java/org/jruby/runtime/Block.java @@ -108,6 +108,11 @@ public DynamicScope allocScope(DynamicScope parentScope) { return newScope; } + public EvalType getEvalType() { + // SSS FIXME: This is smelly + return body instanceof IRBlockBody ? ((IRBlockBody)body).getEvalType() : null; + } + public void setEvalType(EvalType evalType) { body.setEvalType(evalType); }