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: a3fecb78bd20
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e4d16ac8afc3
Choose a head ref
  • 9 commits
  • 15 files changed
  • 1 contributor

Commits on Dec 17, 2014

  1. Re-apply

    enebo committed Dec 17, 2014
    Copy the full SHA
    7c0595b View commit details
  2. Copy the full SHA
    06ad06f View commit details
  3. evalSimple path no longer has duplicated scope (messiness to be clean…

    …ed up after evalWithBinding
    
    removes its additionalScope).
    Reinstated NoVars assertion because we no longer erroneously ask 'phantom' scope for a block
    value which is never there...ooooooo spooky
    SClasses should not need to get closure
    enebo committed Dec 17, 2014
    Copy the full SHA
    73df3d2 View commit details
  4. Still a bit messy but all extra scope removal is done with known extr…

    …a depth calcs removed
    enebo committed Dec 17, 2014
    Copy the full SHA
    4fccdd4 View commit details
  5. Still a bit messy but all extra scope removal is done with known extr…

    …a depth calcs removed
    enebo committed Dec 17, 2014
    Copy the full SHA
    695baa1 View commit details
  6. Copy the full SHA
    e8b9780 View commit details
  7. End of eval changes for now. Later this will be revisted once we swit…

    …ch to only using StaticScope for lvars
    enebo committed Dec 17, 2014
    Copy the full SHA
    8e70622 View commit details
  8. Fix #2301

    enebo committed Dec 17, 2014
    Copy the full SHA
    b5b7305 View commit details
  9. I see no reason for setting parent frame visibility to public. Nothin…

    …g triggered so removing
    enebo committed Dec 17, 2014
    Copy the full SHA
    e4d16ac View commit details
14 changes: 3 additions & 11 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -1688,7 +1688,7 @@ public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Bl
* with this implementation.
*/
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, IRubyObject[] args, Block block, EvalType evalType) {
context.preExecuteUnder(under, block);
context.preExecuteUnder(this, under, block);

IRubyObject savedBindingSelf = block.getBinding().getSelf();
IRubyObject savedFrameSelf = block.getBinding().getFrame().getSelf();
@@ -1730,7 +1730,7 @@ private Block setupBlock(Block block, EvalType evalType) {
* with this implementation.
*/
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, Block block, EvalType evalType) {
context.preExecuteUnder(under, block);
context.preExecuteUnder(this, under, block);

IRubyObject savedBindingSelf = block.getBinding().getSelf();
IRubyObject savedFrameSelf = block.getBinding().getFrame().getSelf();
@@ -1871,15 +1871,7 @@ protected RubyModule getInstanceEvalClass() {
* using the module under as the context.
*/
public IRubyObject evalUnder(final ThreadContext context, RubyModule under, RubyString src, String file, int line, EvalType evalType) {
Visibility savedVisibility = context.getCurrentVisibility();
context.setCurrentVisibility(PUBLIC);
context.preExecuteUnder(under, Block.NULL_BLOCK);
try {
return Interpreter.evalSimple(context, this, src, file, line, evalType);
} finally {
context.postExecuteUnder();
context.setCurrentVisibility(savedVisibility);
}
return Interpreter.evalSimple(context, under, this, src, file, line, evalType);
}

/**
5 changes: 1 addition & 4 deletions core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
@@ -1009,10 +1009,7 @@ private static IRubyObject evalCommon(ThreadContext context, IRubyObject recv, I
// filename given, but no line, start from the beginning.
binding.setLine(0);
}
} else if (bindingGiven) {
// binding given, use binding's file and line-number
} else {
// no binding given, use (eval) and start from first line.
} else if (!bindingGiven) { // no binding given, use (eval) and start from first line.
binding.setFile("(eval)");
binding.setLine(0);
}
95 changes: 95 additions & 0 deletions core/src/main/java/org/jruby/ir/IRBindingEvalScript.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.jruby.ir;

import org.jruby.EvalType;
import org.jruby.ir.operands.ClosureLocalVariable;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.parser.StaticScope;

/**
* Explicit Binding Evals must allow preserving values between evals. They do this is a special hidden scope.
*/
public class IRBindingEvalScript extends IREvalScript {
private IRScope nearestNonEvalScope;
private int nearestNonEvalScopeDepth;

public IRBindingEvalScript(IRManager manager, IRScope lexicalParent, String fileName, int lineNumber, StaticScope staticScope, EvalType evalType) {
super(manager, lexicalParent, fileName, lineNumber, staticScope, evalType);

int n = 0;
IRScope s = lexicalParent;
while (s instanceof IRBindingEvalScript) {
n++;
s = s.getLexicalParent();
}

this.nearestNonEvalScope = s;
this.nearestNonEvalScopeDepth = n;
this.nearestNonEvalScope.initEvalScopeVariableAllocator(false);

if (!getManager().isDryRun() && staticScope != null) {
// SSS FIXME: This is awkward!
if (evalType == EvalType.MODULE_EVAL) {
staticScope.setScopeType(getScopeType());
} else {
staticScope.setScopeType(this.nearestNonEvalScope.getScopeType());
}
}

}

@Override
public LocalVariable lookupExistingLVar(String name) {
return nearestNonEvalScope.evalScopeVars.get(name);
}

@Override
protected LocalVariable findExistingLocalVariable(String name, int scopeDepth) {
// Look in the nearest non-eval scope's shared eval scope vars first.
// If you dont find anything there, look in the nearest non-eval scope's regular vars.
LocalVariable lvar = lookupExistingLVar(name);
if (lvar != null || scopeDepth == 0) return lvar;
else return nearestNonEvalScope.findExistingLocalVariable(name, scopeDepth-nearestNonEvalScopeDepth-1);
}

@Override
public LocalVariable getLocalVariable(String name, int scopeDepth) {
// Reduce lookup depth by 1 since the AST seems to be adding
// an additional static/dynamic scope for which there is no
// corresponding IRScope.
//
// FIXME: Investigate if this is something left behind from
// 1.8 mode support. Or if we need to introduce the additional
// IRScope object.
int lookupDepth = isModuleOrInstanceEval() ? scopeDepth - 1 : scopeDepth;
LocalVariable lvar = findExistingLocalVariable(name, lookupDepth);
if (lvar == null) lvar = getNewLocalVariable(name, lookupDepth);
// Create a copy of the variable usable at the right depth
if (lvar.getScopeDepth() != scopeDepth) lvar = lvar.cloneForDepth(scopeDepth);

return lvar;
}

@Override
public LocalVariable getNewLocalVariable(String name, int depth) {
assert depth == nearestNonEvalScopeDepth: "Local variable depth in IREvalScript:getNewLocalVariable for " + name + " must be " + nearestNonEvalScopeDepth + ". Got " + depth;
LocalVariable lvar = new ClosureLocalVariable(this, name, 0, nearestNonEvalScope.evalScopeVars.size());
nearestNonEvalScope.evalScopeVars.put(name, lvar);
// CON: unsure how to get static scope to reflect this name as in IRClosure and IRMethod
return lvar;
}

@Override
public LocalVariable getNewFlipStateVariable() {
String flipVarName = "%flip_" + allocateNextPrefixedName("%flip");
LocalVariable v = lookupExistingLVar(flipVarName);
if (v == null) {
v = getNewLocalVariable(flipVarName, 0);
}
return v;
}

@Override
public int getUsedVariablesCount() {
return nearestNonEvalScope.evalScopeVars.size()+ getPrefixCountSize("%flip");
}
}
52 changes: 25 additions & 27 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -309,26 +309,19 @@ public void addInstrAtBeginning(IRScope s, Instr i) {
}
}

// FIXME: This all seems wrong to me. IRClosures can receive explicit closures why are we searching only methods
// and by-passing closures
private Operand getImplicitBlockArg(IRScope s) {
int n = 0;
while (s != null && s instanceof IRClosure) {
// We have this oddity of an extra inserted scope for instance/class/module evals
if (s instanceof IREvalScript && ((IREvalScript)s).isModuleOrInstanceEval()) {
n++;
}
while (s instanceof IRClosure || s instanceof IRMetaClassBody) {
n++;
s = s.getLexicalParent();
}

if (s != null) {
LocalVariable v = null;
if (s instanceof IRMethod || s instanceof IRMetaClassBody) {
v = s.getLocalVariable(Variable.BLOCK, 0);
}
LocalVariable v = s instanceof IRMethod ? s.getLocalVariable(Variable.BLOCK, 0) : null;

if (v != null) {
return n == 0 ? v : v.cloneForDepth(n);
}
if (v != null) return n == 0 ? v : v.cloneForDepth(n);
}

return manager.getNil();
@@ -1116,9 +1109,9 @@ public Operand buildClass(ClassNode classNode, IRScope s) {
String className = cpath.getName();
Operand container = getContainerFromCPath(cpath, s);
IRClassBody body = new IRClassBody(manager, s, className, classNode.getPosition().getLine(), classNode.getScope());
Variable tmpVar = addResultInstr(s, new DefineClassInstr(s.createTemporaryVariable(), body, container, superClass));
Variable classVar = addResultInstr(s, new DefineClassInstr(s.createTemporaryVariable(), body, container, superClass));

return buildModuleOrClassBody(s, tmpVar, body, classNode.getBodyNode(), classNode.getPosition().getLine());
return buildModuleOrClassBody(s, classVar, body, classNode.getBodyNode(), classNode.getPosition().getLine());
}

// class Foo; class << self; end; end
@@ -1127,9 +1120,9 @@ public Operand buildClass(ClassNode classNode, IRScope s) {
public Operand buildSClass(SClassNode sclassNode, IRScope s) {
Operand receiver = build(sclassNode.getReceiverNode(), s);
IRModuleBody body = new IRMetaClassBody(manager, s, manager.getMetaClassName(), sclassNode.getPosition().getLine(), sclassNode.getScope());
Variable tmpVar = addResultInstr(s, new DefineMetaClassInstr(s.createTemporaryVariable(), receiver, body));
Variable sClassVar = addResultInstr(s, new DefineMetaClassInstr(s.createTemporaryVariable(), receiver, body));

return buildModuleOrClassBody(s, tmpVar, body, sclassNode.getBodyNode(), sclassNode.getPosition().getLine());
return buildModuleOrClassBody(s, sClassVar, body, sclassNode.getBodyNode(), sclassNode.getPosition().getLine());
}

// @@c
@@ -2627,9 +2620,9 @@ public Operand buildModule(ModuleNode moduleNode, IRScope s) {
String moduleName = cpath.getName();
Operand container = getContainerFromCPath(cpath, s);
IRModuleBody body = new IRModuleBody(manager, s, moduleName, moduleNode.getPosition().getLine(), moduleNode.getScope());
Variable tmpVar = addResultInstr(s, new DefineModuleInstr(s.createTemporaryVariable(), body, container));
Variable moduleVar = addResultInstr(s, new DefineModuleInstr(s.createTemporaryVariable(), body, container));

return buildModuleOrClassBody(s, tmpVar, body, moduleNode.getBodyNode(), moduleNode.getPosition().getLine());
return buildModuleOrClassBody(s, moduleVar, body, moduleNode.getBodyNode(), moduleNode.getPosition().getLine());
}

public Operand buildMultipleAsgn(MultipleAsgnNode multipleAsgnNode, IRScope s) {
@@ -3207,7 +3200,17 @@ public Operand buildReturn(ReturnNode returnNode, IRScope s) {

public IREvalScript buildEvalRoot(StaticScope staticScope, IRScope containingScope, String file, int lineNumber, RootNode rootNode, EvalType evalType) {
// Top-level script!
IREvalScript script = new IREvalScript(manager, containingScope, file, lineNumber, staticScope, evalType);
IREvalScript script;

if (evalType == EvalType.BINDING_EVAL) {
script = new IRBindingEvalScript(manager, containingScope, file, lineNumber, staticScope, evalType);
} else {
script = new IREvalScript(manager, containingScope, file, lineNumber, staticScope, evalType);
}

// We link IRScope to StaticScope because we may add additional variables (like %block). During execution
// we end up growing dynamicscope potentially based on any changes made.
staticScope.setIRScope(script);

// Debug info: record line number
addInstr(script, new LineNumberInstr(script, lineNumber));
@@ -3501,20 +3504,15 @@ private Operand[] adjustVariableDepth(Operand[] args, int depthFromSuper) {
return newArgs;
}

private Operand buildModuleOrClassBody(IRScope parent, Variable tmpVar, IRModuleBody body, Node bodyNode, int linenumber) {
Variable processBodyResult = addResultInstr(parent, new ProcessModuleBodyInstr(parent.createTemporaryVariable(), tmpVar, getImplicitBlockArg(parent)));
private Operand buildModuleOrClassBody(IRScope parent, Variable moduleVar, IRModuleBody body, Node bodyNode, int linenumber) {
Variable processBodyResult = addResultInstr(parent, new ProcessModuleBodyInstr(parent.createTemporaryVariable(), moduleVar));
IRBuilder bodyBuilder = newIRBuilder(manager);

if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
bodyBuilder.addInstr(body, new TraceInstr(RubyEvent.CLASS, null, body.getFileName(), linenumber));
}

bodyBuilder.addInstr(body, new ReceiveSelfInstr(body.getSelf())); // %self

if (body instanceof IRMetaClassBody) {
bodyBuilder.addInstr(body, new ReceiveClosureInstr((Variable)getImplicitBlockArg(body))); // %closure - SClass
}

bodyBuilder.addInstr(body, new ReceiveSelfInstr(body.getSelf())); // %self
bodyBuilder.addInstr(body, new CopyInstr(body.getCurrentScopeVariable(), new CurrentScope(0))); // %scope
bodyBuilder.addInstr(body, new CopyInstr(body.getCurrentModuleVariable(), new ScopeModule(0))); // %module
// Create a new nested builder to ensure this gets its own IR builder state
Loading