Skip to content

Commit

Permalink
Showing 14 changed files with 141 additions and 117 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/language/break_tags.txt
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ fails:The break statement in a captured block when the invocation of the scope c
fails:The break statement in a captured block when the invocation of the scope creating the block is still active raises a LocalJumpError when yielding to the block
fails:The break statement in a captured block from a scope that has returned raises a LocalJumpError when calling the block from a method
fails:The break statement in a captured block from a scope that has returned raises a LocalJumpError when yielding to the block
fails:Executing break from within a block returns from the original invoking method even in case of chained calls
slow:The break statement in a lambda created at the toplevel returns a value when invoking from a method
slow:The break statement in a lambda created at the toplevel returns a value when invoking from a block
slow:The break statement in a lambda created at the toplevel returns a value when invoking from the toplevel
4 changes: 2 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/nodes/ForNode.java
Original file line number Diff line number Diff line change
@@ -15,9 +15,9 @@

public class ForNode extends RubyNode {

@Child private RubyCallNode callNode;
@Child private RubyNode callNode;

public ForNode(RubyContext context, SourceSection sourceSection, RubyCallNode callNode) {
public ForNode(RubyContext context, SourceSection sourceSection, RubyNode callNode) {
super(context, sourceSection);
this.callNode = callNode;
}
Original file line number Diff line number Diff line change
@@ -11,22 +11,29 @@

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.BreakException;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.translator.TranslatorEnvironment.BlockID;

public class BreakNode extends RubyNode {

private final BlockID blockID;

@Child private RubyNode child;

public BreakNode(RubyContext context, SourceSection sourceSection, RubyNode child) {
public BreakNode(RubyContext context, SourceSection sourceSection, BlockID blockID, RubyNode child) {
super(context, sourceSection);
this.blockID = blockID;
this.child = child;
}

@Override
public Object execute(VirtualFrame frame) {
throw new BreakException(child.execute(frame));
throw new BreakException(blockID, child.execute(frame));
}

}
61 changes: 6 additions & 55 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -1337,9 +1337,6 @@ public Object eachIntegerFixnum(VirtualFrame frame, RubyArray array, RubyProc bl
try {
yield(frame, block, store[n]);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1374,9 +1371,6 @@ public Object eachLongFixnum(VirtualFrame frame, RubyArray array, RubyProc block
try {
yield(frame, block, store[n]);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1411,9 +1405,6 @@ public Object eachFloat(VirtualFrame frame, RubyArray array, RubyProc block) {
try {
yield(frame, block, store[n]);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1448,9 +1439,6 @@ public Object eachObject(VirtualFrame frame, RubyArray array, RubyProc block) {
try {
yield(frame, block, store[n]);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1508,9 +1496,6 @@ public Object eachWithIndexInt(VirtualFrame frame, RubyArray array, RubyProc blo
try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1545,9 +1530,6 @@ public Object eachWithIndexLong(VirtualFrame frame, RubyArray array, RubyProc bl
try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1582,9 +1564,6 @@ public Object eachWithIndexDouble(VirtualFrame frame, RubyArray array, RubyProc
try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1619,9 +1598,6 @@ public Object eachWithIndexObject(VirtualFrame frame, RubyArray array, RubyProc
try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -1743,8 +1719,6 @@ public abstract static class InitializeNode extends YieldingCoreMethodNode {
@Child private KernelNodes.RespondToNode respondToToAryNode;
@Child private ArrayBuilderNode arrayBuilder;

private final BranchProfile breakProfile = BranchProfile.create();

public InitializeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
arrayBuilder = new ArrayBuilderNode.UninitializedArrayBuilderNode(context);
@@ -1918,29 +1892,24 @@ public Object initialize(VirtualFrame frame, RubyArray array, int size, Undefine
Object store = arrayBuilder.start();

int count = 0;
int n = 0;
try {
for (int n = 0; n < size; n++) {
for (; n < size; n++) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

try {
arrayBuilder.ensure(store, n + 1);
store = arrayBuilder.append(store, n, yield(frame, block, n));
} catch (BreakException e) {
breakProfile.enter();
array.setStore(arrayBuilder.finish(store, n), n);
return e.getResult();
}

arrayBuilder.ensure(store, n + 1);
store = arrayBuilder.append(store, n, yield(frame, block, n));
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}

array.setStore(arrayBuilder.finish(store, n), n);
}

array.setStore(arrayBuilder.finish(store, size), size);
return array;
}

@@ -2309,9 +2278,6 @@ public Object mapIntegerFixnum(VirtualFrame frame, RubyArray array, RubyProc blo
try {
mappedStore = arrayBuilder.append(mappedStore, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -2347,9 +2313,6 @@ public Object mapLongFixnum(VirtualFrame frame, RubyArray array, RubyProc block)
try {
mappedStore = arrayBuilder.append(mappedStore, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -2385,9 +2348,6 @@ public Object mapFloat(VirtualFrame frame, RubyArray array, RubyProc block) {
try {
mappedStore = arrayBuilder.append(mappedStore, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -2423,9 +2383,6 @@ public Object mapObject(VirtualFrame frame, RubyArray array, RubyProc block) {
try {
mappedStore = arrayBuilder.append(mappedStore, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -2490,9 +2447,6 @@ public Object mapInPlaceFixnumInteger(VirtualFrame frame, RubyArray array, RubyP
try {
writeNode.executeWrite(frame, array, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -2533,9 +2487,6 @@ public Object mapInPlaceObject(VirtualFrame frame, RubyArray array, RubyProc blo
try {
writeNode.executeWrite(frame, array, n, yield(frame, block, store[n]));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
Original file line number Diff line number Diff line change
@@ -60,9 +60,6 @@ public Object downto(VirtualFrame frame, int from, int to, RubyProc block) {
try {
yield(frame, block, i);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -133,9 +130,6 @@ public Object times(VirtualFrame frame, int n, RubyProc block) {
try {
yield(frame, block, i);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -167,9 +161,6 @@ public Object times(VirtualFrame frame, long n, RubyProc block) {
try {
yield(frame, block, i);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -201,9 +192,6 @@ public Object times(VirtualFrame frame, RubyBignum n, RubyProc block) {
try {
yield(frame, block, fixnumOrBignum.fixnumOrBignum(i));
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -276,9 +264,6 @@ public Object upto(VirtualFrame frame, int from, int to, RubyProc block) {
try {
yield(frame, block, i);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -319,9 +304,6 @@ public Object upto(VirtualFrame frame, long from, long to, RubyProc block) {
try {
yield(frame, block, i);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
12 changes: 0 additions & 12 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/RangeNodes.java
Original file line number Diff line number Diff line change
@@ -109,9 +109,6 @@ public Object each(VirtualFrame frame, RubyRange.IntegerFixnumRange range, RubyP
try {
yield(frame, block, n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -146,9 +143,6 @@ public Object each(VirtualFrame frame, RubyRange.LongFixnumRange range, RubyProc
try {
yield(frame, block, n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -311,9 +305,6 @@ public Object step(VirtualFrame frame, RubyRange.IntegerFixnumRange range, int s
try {
yield(frame, block, n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
@@ -346,9 +337,6 @@ public Object step(VirtualFrame frame, RubyRange.LongFixnumRange range, int step
try {
yield(frame, block, n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
Original file line number Diff line number Diff line change
@@ -13,12 +13,14 @@
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.truffle.translator.TranslatorEnvironment.BlockID;

/**
* Create a RubyProc to pass as a block to the called method.
@@ -37,10 +39,11 @@ public class BlockDefinitionNode extends RubyNode {
private final CallTarget callTargetForMethods;

private final boolean requiresDeclarationFrame;
private final BlockID blockID;

public BlockDefinitionNode(RubyContext context, SourceSection sourceSection, SharedMethodInfo sharedMethodInfo,
boolean requiresDeclarationFrame, CallTarget callTargetForBlocks,
CallTarget callTargetForProcs, CallTarget callTargetForMethods) {
CallTarget callTargetForProcs, CallTarget callTargetForMethods, BlockID blockID) {
super(context, sourceSection);
this.sharedMethodInfo = sharedMethodInfo;

@@ -49,7 +52,11 @@ public BlockDefinitionNode(RubyContext context, SourceSection sourceSection, Sha
this.callTargetForMethods = callTargetForMethods;

this.requiresDeclarationFrame = requiresDeclarationFrame;
this.blockID = blockID;
}

public BlockID getBlockID() {
return blockID;
}

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.methods;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.BreakException;
import org.jruby.truffle.translator.TranslatorEnvironment.BlockID;

/**
* Catch a {@code break} jump in a block at the top level and handle it as a return.
*/
public class CatchBreakFromCallNode extends RubyNode {

@Child private RubyNode body;

private final BlockID blockID;

private final BranchProfile breakProfile = BranchProfile.create();
private final ConditionProfile matchingBreakProfile = ConditionProfile.createCountingProfile();

public CatchBreakFromCallNode(RubyContext context, SourceSection sourceSection, RubyNode body, BlockID blockID) {
super(context, sourceSection);
this.body = body;
this.blockID = blockID;
}

@Override
public Object execute(VirtualFrame frame) {
try {
return body.execute(frame);
} catch (BreakException e) {
breakProfile.enter();

if (matchingBreakProfile.profile(e.getBlockID() == blockID)) {
return e.getResult();
} else {
throw e;
}
}
}

}
Original file line number Diff line number Diff line change
@@ -9,19 +9,28 @@
*/
package org.jruby.truffle.runtime.control;

import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.translator.TranslatorEnvironment.BlockID;

import com.oracle.truffle.api.nodes.ControlFlowException;

/**
* Controls a break from a control structure or method.
*/
public final class BreakException extends ControlFlowException {

private final BlockID blockID;
private final Object result;

public BreakException(Object result) {
public BreakException(BlockID blockID, Object result) {
this.blockID = blockID;
this.result = result;
}

public BlockID getBlockID() {
return blockID;
}

public Object getResult() {
return result;
}
Original file line number Diff line number Diff line change
@@ -374,7 +374,7 @@ public RubyNode visitBreakNode(org.jruby.ast.BreakNode node) {
resultNode = node.getValueNode().accept(this);
}

return new BreakNode(context, sourceSection, resultNode);
return new BreakNode(context, sourceSection, environment.getBlockID(), resultNode);
}

@Override
@@ -588,6 +588,11 @@ public RubyNode visitCallNodeExtraArgument(CallNode node, RubyNode extraArgument
node.getName(), receiverTranslated, argumentsAndBlock.getBlock(), argumentsAndBlock.isSplatted(),
privately || ignoreVisibility, isVCall, argumentsAndBlock.getArguments());

if (argumentsAndBlock.getBlock() instanceof BlockDefinitionNode) { // if we have a literal block, break breaks out of this call site
BlockDefinitionNode blockDef = (BlockDefinitionNode) argumentsAndBlock.getBlock();
translated = new CatchBreakFromCallNode(context, sourceSection, translated, blockDef.getBlockID());
}

// return instrumenter.instrumentAsCall(translated, node.getName());
return translated;
}
@@ -829,7 +834,7 @@ private RubyNode openModule(SourceSection sourceSection, RubyNode defineOrGetNod
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, newLexicalScope, Arity.NO_ARGUMENTS, name, false, bodyNode, false);

final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParseEnvironment(),
environment.getParseEnvironment().allocateReturnID(), true, true, sharedMethodInfo, name, false);
environment.getParseEnvironment().allocateReturnID(), true, true, sharedMethodInfo, name, false, null);

final ModuleTranslator classTranslator = new ModuleTranslator(currentNode, context, this, newEnvironment, source);

@@ -1092,7 +1097,7 @@ protected RubyNode translateMethodDefinition(SourceSection sourceSection, RubyNo
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, environment.getLexicalScope(), MethodTranslator.getArity(argsNode), methodName, false, parseTree, false);

final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(
context, environment, environment.getParseEnvironment(), environment.getParseEnvironment().allocateReturnID(), true, true, sharedMethodInfo, methodName, false);
context, environment, environment.getParseEnvironment(), environment.getParseEnvironment().allocateReturnID(), true, true, sharedMethodInfo, methodName, false, null);

// ownScopeForAssignments is the same for the defined method as the current one.

@@ -1277,9 +1282,11 @@ public RubyNode visitForNode(org.jruby.ast.ForNode node) {
final CallNode callNode = new CallNode(node.getPosition(), receiver, "each", null, block);

translatingForStatement = true;
final RubyCallNode translated = (RubyCallNode) callNode.accept(this);
final RubyNode translated = callNode.accept(this);
translatingForStatement = false;

// TODO (eregon, 20 Apr. 2015): We could just get rid of ForNode here since it seems useless.
// isDefined() should work anyway since the callNode has a block and that is always defined as "expression".
return new ForNode(context, translated.getSourceSection(), translated);
}

@@ -1663,7 +1670,8 @@ public RubyNode visitIterNode(org.jruby.ast.IterNode node) {
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, environment.getLexicalScope(), MethodTranslator.getArity(argsNode), currentCallMethodName, true, node, false);

final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(
context, environment, environment.getParseEnvironment(), environment.getReturnID(), hasOwnScope, false, sharedMethodInfo, environment.getNamedMethodName(), true);
context, environment, environment.getParseEnvironment(), environment.getReturnID(), hasOwnScope, false,
sharedMethodInfo, environment.getNamedMethodName(), true, environment.getParseEnvironment().allocateBlockID());
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, true, source);
methodCompiler.translatingForStatement = translatingForStatement;

@@ -2754,7 +2762,8 @@ public RubyNode visitLambdaNode(org.jruby.ast.LambdaNode node) {
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, environment.getLexicalScope(), MethodTranslator.getArity(argsNode), "(lambda)", true, node, false);

final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(
context, environment, environment.getParseEnvironment(), environment.getReturnID(), false, false, sharedMethodInfo, sharedMethodInfo.getName(), true);
context, environment, environment.getParseEnvironment(), environment.getReturnID(), false, false,
sharedMethodInfo, sharedMethodInfo.getName(), true, environment.getParseEnvironment().allocateBlockID());
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, false, source);

final RubyNode definitionNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), sharedMethodInfo.getName(), argsNode, node.getBodyNode(), sharedMethodInfo);
Original file line number Diff line number Diff line change
@@ -16,10 +16,12 @@
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.ast.ArgsNode;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.cast.ArrayCastNodeFactory;
import org.jruby.truffle.nodes.control.BreakNode;
import org.jruby.truffle.nodes.control.IfNode;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.literal.ObjectLiteralNode;
@@ -160,7 +162,6 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa
new CatchBreakAsProcErrorNode(context, sourceSection, body),
NodeUtil.cloneNode(body));
} else {
body = new CatchBreakAsReturnNode(context, sourceSection, body);
body = new CatchReturnNode(context, sourceSection, body, environment.getReturnID());
}

@@ -186,6 +187,7 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa
}

if (isBlock) {
// Blocks
final RubyRootNode newRootNodeForBlocks = rootNode.cloneRubyRootNode();

for (BehaveAsBlockNode behaveAsBlockNode : NodeUtil.findAllNodeInstances(newRootNodeForBlocks, BehaveAsBlockNode.class)) {
@@ -196,6 +198,9 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa
behaveAsProcNode.replace(behaveAsProcNode.getNotAsProc());
}

final CallTarget callTargetAsBlock = Truffle.getRuntime().createCallTarget(newRootNodeForBlocks);

// Procs
final RubyRootNode newRootNodeForProcs = rootNode.cloneRubyRootNode();

for (BehaveAsBlockNode behaveAsBlockNode : NodeUtil.findAllNodeInstances(newRootNodeForProcs, BehaveAsBlockNode.class)) {
@@ -208,8 +213,7 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa

final CallTarget callTargetAsProc = Truffle.getRuntime().createCallTarget(newRootNodeForProcs);

final CallTarget callTargetAsBlock = Truffle.getRuntime().createCallTarget(newRootNodeForBlocks);

// Methods
final RubyRootNode newRootNodeForMethods = rootNode.cloneRubyRootNode();

for (BehaveAsBlockNode behaveAsBlockNode : NodeUtil.findAllNodeInstances(newRootNodeForMethods, BehaveAsBlockNode.class)) {
@@ -231,7 +235,7 @@ public RubyNode compileFunctionNode(SourceSection sourceSection, String methodNa
final CallTarget callTargetAsMethod = Truffle.getRuntime().createCallTarget(newRootNodeWithCatchReturn);

return new BlockDefinitionNode(context, sourceSection, environment.getSharedMethodInfo(),
environment.needsDeclarationFrame(), callTargetAsBlock, callTargetAsProc, callTargetAsMethod);
environment.needsDeclarationFrame(), callTargetAsBlock, callTargetAsProc, callTargetAsMethod, environment.getBlockID());
} else {
return new MethodDefinitionNode(context, sourceSection, methodName, environment.getSharedMethodInfo(),
environment.needsDeclarationFrame(), Truffle.getRuntime().createCallTarget(rootNode));
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@

import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.translator.TranslatorEnvironment.BlockID;

/**
* Translator environment, unique per parse/translation.
@@ -47,4 +48,8 @@ public long allocateReturnID() {
return allocated;
}

public BlockID allocateBlockID() {
return new BlockID();
}

}
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ public RubyNode parse(RubyContext context, org.jruby.ast.Node parseTree, org.jru
final SharedMethodInfo sharedMethod = new SharedMethodInfo(null, lexicalScope, Arity.NO_ARGUMENTS, "(unknown)", false, parseTree, false);

final TranslatorEnvironment environment = new TranslatorEnvironment(
context, environmentForFrame(context, null), parseEnvironment, parseEnvironment.allocateReturnID(), true, true, sharedMethod, sharedMethod.getName(), false);
context, environmentForFrame(context, null), parseEnvironment, parseEnvironment.allocateReturnID(), true, true, sharedMethod, sharedMethod.getName(), false, null);

// Translate to Ruby Truffle nodes

@@ -132,7 +132,7 @@ public RubyRootNode parse(Node currentNode, RubyContext context, Source source,
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, context.getRootLexicalScope(), Arity.NO_ARGUMENTS, "<main>", false, rootNode, false);

final TranslatorEnvironment environment = new TranslatorEnvironment(context, environmentForFrame(context, parentFrame),
parseEnvironment, parseEnvironment.allocateReturnID(), ownScopeForAssignments, false, sharedMethodInfo, sharedMethodInfo.getName(), false);
parseEnvironment, parseEnvironment.allocateReturnID(), ownScopeForAssignments, false, sharedMethodInfo, sharedMethodInfo.getName(), false, null);

// Get the DATA constant

@@ -233,8 +233,8 @@ private TranslatorEnvironment environmentForFrame(RubyContext context, Materiali
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, context.getRootLexicalScope(), Arity.NO_ARGUMENTS, "(unknown)", false, null, false);
final MaterializedFrame parent = RubyArguments.getDeclarationFrame(frame.getArguments());
// TODO(CS): how do we know if the frame is a block or not?
return new TranslatorEnvironment(context, environmentForFrame(context, parent), frame.getFrameDescriptor(),
parseEnvironment, parseEnvironment.allocateReturnID(), true, true, sharedMethodInfo, sharedMethodInfo.getName(), false);
return new TranslatorEnvironment(context, environmentForFrame(context, parent), parseEnvironment,
parseEnvironment.allocateReturnID(), true, true, sharedMethodInfo, sharedMethodInfo.getName(), false, null, frame.getFrameDescriptor());
}
}

Original file line number Diff line number Diff line change
@@ -29,6 +29,9 @@

public class TranslatorEnvironment {

public static class BlockID {
};

private final RubyContext context;

private final ParseEnvironment parseEnvironment;
@@ -39,6 +42,7 @@ public class TranslatorEnvironment {

private final long returnID;
private final boolean isBlock;
private final BlockID blockID;

private final boolean ownScopeForAssignments;
private final boolean neverAssignInParentScope;
@@ -54,8 +58,10 @@ public class TranslatorEnvironment {

public boolean hasRestParameter = false;

public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, FrameDescriptor frameDescriptor, ParseEnvironment parseEnvironment, long returnID, boolean ownScopeForAssignments,
boolean neverAssignInParentScope, SharedMethodInfo sharedMethodInfo, String namedMethodName, boolean isBlock) {
public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, ParseEnvironment parseEnvironment,
long returnID, boolean ownScopeForAssignments, boolean neverAssignInParentScope,
SharedMethodInfo sharedMethodInfo, String namedMethodName, boolean isBlock, BlockID blockID,
FrameDescriptor frameDescriptor) {
this.context = context;
this.parent = parent;
this.frameDescriptor = frameDescriptor;
@@ -65,18 +71,16 @@ public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent,
this.neverAssignInParentScope = neverAssignInParentScope;
this.sharedMethodInfo = sharedMethodInfo;
this.namedMethodName = namedMethodName;
assert isBlock == (blockID != null);
this.isBlock = isBlock;
this.blockID = blockID;
}

public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, ParseEnvironment parseEnvironment, long returnID, boolean ownScopeForAssignments, boolean neverAssignInParentScope,
SharedMethodInfo methodIdentifier, String namedMethodName, boolean isBlock) {
this(context, parent, new FrameDescriptor(context.getCoreLibrary().getNilObject()), parseEnvironment, returnID, ownScopeForAssignments, neverAssignInParentScope, methodIdentifier,
namedMethodName, isBlock);
}

public static TranslatorEnvironment newRootEnvironment(RubyContext context, FrameDescriptor frameDescriptor, ParseEnvironment parseEnvironment, long returnID, boolean ownScopeForAssignments,
boolean neverAssignInParentScope, SharedMethodInfo sharedMethodInfo, String namedMethodName, boolean isBlock) {
return new TranslatorEnvironment(context, null, frameDescriptor, parseEnvironment, returnID, ownScopeForAssignments, neverAssignInParentScope, sharedMethodInfo, namedMethodName, isBlock);
public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, ParseEnvironment parseEnvironment,
long returnID, boolean ownScopeForAssignments, boolean neverAssignInParentScope,
SharedMethodInfo methodIdentifier, String namedMethodName, boolean isBlock, BlockID blockID) {
this(context, parent, parseEnvironment, returnID, ownScopeForAssignments, neverAssignInParentScope, methodIdentifier, namedMethodName, isBlock, blockID,
new FrameDescriptor(context.getCoreLibrary().getNilObject()));
}

public LexicalScope getLexicalScope() {
@@ -220,4 +224,8 @@ public String getNamedMethodName() {
public boolean isBlock() {
return isBlock;
}

public BlockID getBlockID() {
return blockID;
}
}

0 comments on commit 434c8a2

Please sign in to comment.