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

Commits on Feb 23, 2016

  1. Copy the full SHA
    81b8889 View commit details
  2. Copy the full SHA
    a22364a View commit details
  3. 3
    Copy the full SHA
    870a9e9 View commit details
  4. Copy the full SHA
    0a37335 View commit details
  5. Copy the full SHA
    489f45d View commit details
  6. Copy the full SHA
    cc14e9a View commit details
  7. 2
    Copy the full SHA
    e498859 View commit details
Showing with 180 additions and 107 deletions.
  1. +3 −2 truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
  2. +4 −0 truffle/src/main/java/org/jruby/truffle/core/string/CoreStrings.java
  3. +7 −9 truffle/src/main/java/org/jruby/truffle/language/locals/DeclarationFlipFlopStateNode.java
  4. +5 −6 truffle/src/main/java/org/jruby/truffle/language/locals/FlipFlopNode.java
  5. +0 −4 truffle/src/main/java/org/jruby/truffle/language/locals/FlipFlopStateNode.java
  6. +1 −2 truffle/src/main/java/org/jruby/truffle/language/locals/LocalFlipFlopStateNode.java
  7. +16 −0 truffle/src/main/java/org/jruby/truffle/language/locals/LocalVariableType.java
  8. +39 −27 truffle/src/main/java/org/jruby/truffle/language/locals/ReadDeclarationVariableNode.java
  9. +36 −21 truffle/src/main/java/org/jruby/truffle/language/locals/ReadLocalVariableNode.java
  10. +15 −8 truffle/src/main/java/org/jruby/truffle/language/locals/WriteDeclarationVariableNode.java
  11. +15 −5 truffle/src/main/java/org/jruby/truffle/language/locals/WriteLocalVariableNode.java
  12. +7 −6 truffle/src/main/java/org/jruby/truffle/language/translator/BodyTranslator.java
  13. +13 −12 truffle/src/main/java/org/jruby/truffle/language/translator/LoadArgumentsTranslator.java
  14. +3 −2 truffle/src/main/java/org/jruby/truffle/language/translator/MethodTranslator.java
  15. +1 −1 truffle/src/main/java/org/jruby/truffle/language/translator/TranslatorDriver.java
  16. +15 −2 truffle/src/main/java/org/jruby/truffle/language/translator/TranslatorEnvironment.java
Original file line number Diff line number Diff line change
@@ -76,6 +76,7 @@
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.dispatch.MissingBehavior;
import org.jruby.truffle.language.locals.LocalVariableType;
import org.jruby.truffle.language.locals.ReadDeclarationVariableNode;
import org.jruby.truffle.language.methods.Arity;
import org.jruby.truffle.language.methods.DeclarationContext;
@@ -2243,7 +2244,7 @@ public MaxBlock(RubyContext context) {
sharedMethodInfo = new SharedMethodInfo(sourceSection, null, Arity.NO_ARGUMENTS, "max", false, null, false, false, false);

callTarget = Truffle.getRuntime().createCallTarget(new RubyRootNode(context, sourceSection, null, sharedMethodInfo, ArrayNodesFactory.MaxBlockNodeFactory.create(context, sourceSection, new RubyNode[]{
new ReadDeclarationVariableNode(context, sourceSection, 1, frameSlot),
new ReadDeclarationVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, 1, frameSlot),
new ReadPreArgumentNode(context, sourceSection, 0, MissingArgumentBehaviour.RUNTIME_ERROR)
}), false));
}
@@ -2361,7 +2362,7 @@ public MinBlock(RubyContext context) {
sharedMethodInfo = new SharedMethodInfo(sourceSection, null, Arity.NO_ARGUMENTS, "min", false, null, false, false, false);

callTarget = Truffle.getRuntime().createCallTarget(new RubyRootNode(context, sourceSection, null, sharedMethodInfo, ArrayNodesFactory.MinBlockNodeFactory.create(context, sourceSection, new RubyNode[]{
new ReadDeclarationVariableNode(context, sourceSection, 1, frameSlot),
new ReadDeclarationVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, 1, frameSlot),
new ReadPreArgumentNode(context, sourceSection, 0, MissingArgumentBehaviour.RUNTIME_ERROR)
}), false));
}
Original file line number Diff line number Diff line change
@@ -17,7 +17,9 @@ public class CoreStrings {
public final CoreString CLASS_VARIABLE;
public final CoreString EXPRESSION;
public final CoreString FALSE;
public final CoreString GLOBAL_VARIABLE;
public final CoreString INSTANCE_VARIABLE;
public final CoreString LOCAL_VARIABLE;
public final CoreString NIL;
public final CoreString SELF;
public final CoreString TRUE;
@@ -27,7 +29,9 @@ public CoreStrings(RubyContext context) {
CLASS_VARIABLE = new CoreString(context, "class variable");
EXPRESSION = new CoreString(context, "expression");
FALSE = new CoreString(context, "false");
GLOBAL_VARIABLE = new CoreString(context, "global-variable");
INSTANCE_VARIABLE = new CoreString(context, "instance-variable");
LOCAL_VARIABLE = new CoreString(context, "local-variable");
NIL = new CoreString(context, "nil");
SELF = new CoreString(context, "self");
TRUE = new CoreString(context, "true");
Original file line number Diff line number Diff line change
@@ -18,31 +18,29 @@

public class DeclarationFlipFlopStateNode extends FlipFlopStateNode {

private final int level;
private final int frameLevel;
private final FrameSlot frameSlot;

public DeclarationFlipFlopStateNode(SourceSection sourceSection, int level,
FrameSlot frameSlot) {
super(sourceSection);
this.level = level;
public DeclarationFlipFlopStateNode(int frameLevel, FrameSlot frameSlot) {
this.frameLevel = frameLevel;
this.frameSlot = frameSlot;
}

@Override
public boolean getState(VirtualFrame frame) {
final MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, level);
final MaterializedFrame declarationFrame = RubyArguments.getDeclarationFrame(frame, frameLevel);

try {
return levelFrame.getBoolean(frameSlot);
return declarationFrame.getBoolean(frameSlot);
} catch (FrameSlotTypeException e) {
throw new IllegalStateException();
}
}

@Override
public void setState(VirtualFrame frame, boolean state) {
final MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, level);
levelFrame.setBoolean(frameSlot, state);
final MaterializedFrame declarationFrame = RubyArguments.getDeclarationFrame(frame, frameLevel);
declarationFrame.setBoolean(frameSlot, state);
}

}
Original file line number Diff line number Diff line change
@@ -18,20 +18,19 @@

public class FlipFlopNode extends RubyNode {

private final boolean exclusive;

@Child private BooleanCastNode begin;
@Child private BooleanCastNode end;
@Child private FlipFlopStateNode stateNode;

private final boolean exclusive;

public FlipFlopNode(RubyContext context, SourceSection sourceSection,
RubyNode begin, RubyNode end, FlipFlopStateNode stateNode,
boolean exclusive) {
public FlipFlopNode(boolean exclusive, SourceSection sourceSection, RubyNode begin, RubyNode end,
FlipFlopStateNode stateNode, RubyContext context) {
super(context, sourceSection);
this.exclusive = exclusive;
this.begin = BooleanCastNodeGen.create(context, sourceSection, begin);
this.end = BooleanCastNodeGen.create(context, sourceSection, end);
this.stateNode = stateNode;
this.exclusive = exclusive;
}

@Override
Original file line number Diff line number Diff line change
@@ -15,10 +15,6 @@

public abstract class FlipFlopStateNode extends Node {

public FlipFlopStateNode(SourceSection sourceSection) {
super(sourceSection);
}

public abstract boolean getState(VirtualFrame frame);

public abstract void setState(VirtualFrame frame, boolean state);
Original file line number Diff line number Diff line change
@@ -18,8 +18,7 @@ public class LocalFlipFlopStateNode extends FlipFlopStateNode {

private final FrameSlot frameSlot;

public LocalFlipFlopStateNode(SourceSection sourceSection, FrameSlot frameSlot) {
super(sourceSection);
public LocalFlipFlopStateNode(FrameSlot frameSlot) {
this.frameSlot = frameSlot;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2016 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.language.locals;

public enum LocalVariableType {
FRAME_LOCAL,
FRAME_LOCAL_GLOBAL,
ALWAYS_DEFINED_GLOBAL
}
Original file line number Diff line number Diff line change
@@ -11,59 +11,71 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.translator.ReadLocalNode;
import org.jruby.truffle.language.translator.Translator;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class ReadDeclarationVariableNode extends ReadLocalNode {

private final LocalVariableType type;
private final int frameDepth;
private final FrameSlot frameSlot;

@Child private ReadFrameSlotNode readFrameSlotNode;

public ReadDeclarationVariableNode(RubyContext context, SourceSection sourceSection,
int frameDepth, FrameSlot slot) {
public ReadDeclarationVariableNode(RubyContext context, SourceSection sourceSection, LocalVariableType type,
int frameDepth, FrameSlot frameSlot) {
super(context, sourceSection);
readFrameSlotNode = ReadFrameSlotNodeGen.create(slot);
this.type = type;
this.frameDepth = frameDepth;
this.frameSlot = frameSlot;
}

@Override
public Object execute(VirtualFrame frame) {
return readFrameSlotNode.executeRead(RubyArguments.getDeclarationFrame(frame, frameDepth));
}

@Override
public RubyNode makeWriteNode(RubyNode rhs) {
return new WriteDeclarationVariableNode(getContext(), getSourceSection(),
rhs, frameDepth, readFrameSlotNode.getFrameSlot());
checkReadFrameSlotNode();
final MaterializedFrame declarationFrame = RubyArguments.getDeclarationFrame(frame, frameDepth);
return readFrameSlotNode.executeRead(declarationFrame);
}

public static final Set<String> ALWAYS_DEFINED_GLOBALS = new HashSet<>(Collections.singletonList("$~"));

@Override
public Object isDefined(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();
switch (type) {
case FRAME_LOCAL:
return coreStrings().LOCAL_VARIABLE.createInstance();

case FRAME_LOCAL_GLOBAL:
checkReadFrameSlotNode();

if (readFrameSlotNode.executeRead(frame) != nil()) {
return coreStrings().GLOBAL_VARIABLE.createInstance();
} else {
return nil();
}

case ALWAYS_DEFINED_GLOBAL:
return coreStrings().GLOBAL_VARIABLE.createInstance();

if (Translator.FRAME_LOCAL_GLOBAL_VARIABLES.contains(readFrameSlotNode.getFrameSlot().getIdentifier())) {
if (ALWAYS_DEFINED_GLOBALS.contains(readFrameSlotNode.getFrameSlot().getIdentifier())
|| readFrameSlotNode.executeRead(RubyArguments.getDeclarationFrame(frame, frameDepth)) != nil()) {
return create7BitString("global-variable", UTF8Encoding.INSTANCE);
} else {
return nil();
}
} else {
return create7BitString("local-variable", UTF8Encoding.INSTANCE);
default:
throw new UnsupportedOperationException("didn't expect local type " + type);
}
}

private void checkReadFrameSlotNode() {
if (readFrameSlotNode == null) {
CompilerDirectives.transferToInterpreter();
readFrameSlotNode = insert(ReadFrameSlotNodeGen.create(frameSlot));
}
}

@Override
public RubyNode makeWriteNode(RubyNode rhs) {
return new WriteDeclarationVariableNode(getContext(), getSourceSection(), frameSlot, frameDepth, rhs);
}

}
Original file line number Diff line number Diff line change
@@ -13,47 +13,62 @@
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.translator.ReadLocalNode;
import org.jruby.truffle.language.translator.Translator;

public class ReadLocalVariableNode extends ReadLocalNode {

private final LocalVariableType type;
private final FrameSlot frameSlot;

@Child private ReadFrameSlotNode readFrameSlotNode;

public ReadLocalVariableNode(RubyContext context, SourceSection sourceSection,
FrameSlot slot) {
public ReadLocalVariableNode(RubyContext context, SourceSection sourceSection, LocalVariableType type, FrameSlot frameSlot) {
super(context, sourceSection);
readFrameSlotNode = ReadFrameSlotNodeGen.create(slot);
this.type = type;
this.frameSlot = frameSlot;
}

@Override
public Object execute(VirtualFrame frame) {
checkReadFrameSlotNode();
return readFrameSlotNode.executeRead(frame);
}

@Override
public RubyNode makeWriteNode(RubyNode rhs) {
return new WriteLocalVariableNode(getContext(), getSourceSection(), rhs,
readFrameSlotNode.getFrameSlot());
public Object isDefined(VirtualFrame frame) {
switch (type) {
case FRAME_LOCAL:
return coreStrings().LOCAL_VARIABLE.createInstance();

case FRAME_LOCAL_GLOBAL:
checkReadFrameSlotNode();

if (readFrameSlotNode.executeRead(frame) != nil()) {
return coreStrings().GLOBAL_VARIABLE.createInstance();
} else {
return nil();
}

case ALWAYS_DEFINED_GLOBAL:
return coreStrings().GLOBAL_VARIABLE.createInstance();

default:
throw new UnsupportedOperationException("didn't expect local type " + type);
}
}

@Override
public Object isDefined(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();

if (Translator.FRAME_LOCAL_GLOBAL_VARIABLES.contains(readFrameSlotNode.getFrameSlot().getIdentifier())) {
if (Translator.ALWAYS_DEFINED_GLOBALS.contains(readFrameSlotNode.getFrameSlot().getIdentifier())
|| readFrameSlotNode.executeRead(frame) != nil()) {
return create7BitString("global-variable", UTF8Encoding.INSTANCE);
} else {
return nil();
}
} else {
return create7BitString("local-variable", UTF8Encoding.INSTANCE);
private void checkReadFrameSlotNode() {
if (readFrameSlotNode == null) {
CompilerDirectives.transferToInterpreter();
readFrameSlotNode = insert(ReadFrameSlotNodeGen.create(frameSlot));
}
}

@Override
public RubyNode makeWriteNode(RubyNode rhs) {
return new WriteLocalVariableNode(getContext(), getSourceSection(), frameSlot, rhs);
}

}
Original file line number Diff line number Diff line change
@@ -9,39 +9,46 @@
*/
package org.jruby.truffle.language.locals;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.arguments.RubyArguments;

public class WriteDeclarationVariableNode extends RubyNode {

private final int frameDepth;
private final FrameSlot frameSlot;

@Child private RubyNode valueNode;
@Child private WriteFrameSlotNode writeFrameSlotNode;

private final int frameDepth;

public WriteDeclarationVariableNode(RubyContext context, SourceSection sourceSection,
RubyNode valueNode, int frameDepth, FrameSlot frameSlot) {
FrameSlot frameSlot, int frameDepth, RubyNode valueNode) {
super(context, sourceSection);
this.valueNode = valueNode;
writeFrameSlotNode = WriteFrameSlotNodeGen.create(frameSlot);
this.frameDepth = frameDepth;
this.frameSlot = frameSlot;
this.valueNode = valueNode;
}

@Override
public Object execute(VirtualFrame frame) {
if (writeFrameSlotNode == null) {
CompilerDirectives.transferToInterpreter();
writeFrameSlotNode = insert(WriteFrameSlotNodeGen.create(frameSlot));
}

final MaterializedFrame declarationFrame = RubyArguments.getDeclarationFrame(frame, frameDepth);
return writeFrameSlotNode.executeWrite(declarationFrame, valueNode.execute(frame));
final Object value = valueNode.execute(frame);
return writeFrameSlotNode.executeWrite(declarationFrame, value);
}

@Override
public Object isDefined(VirtualFrame frame) {
return create7BitString("assignment", UTF8Encoding.INSTANCE);
return coreStrings().ASSIGNMENT.createInstance();
}

}
Original file line number Diff line number Diff line change
@@ -9,32 +9,42 @@
*/
package org.jruby.truffle.language.locals;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

public class WriteLocalVariableNode extends RubyNode {

private final FrameSlot frameSlot;

@Child private RubyNode valueNode;
@Child private WriteFrameSlotNode writeFrameSlotNode;

public WriteLocalVariableNode(RubyContext context, SourceSection sourceSection, RubyNode valueNode, FrameSlot frameSlot) {
public WriteLocalVariableNode(RubyContext context, SourceSection sourceSection,
FrameSlot frameSlot, RubyNode valueNode) {
super(context, sourceSection);
this.frameSlot = frameSlot;
this.valueNode = valueNode;
writeFrameSlotNode = WriteFrameSlotNodeGen.create(frameSlot);

}

@Override
public Object execute(VirtualFrame frame) {
return writeFrameSlotNode.executeWrite(frame, valueNode.execute(frame));
if (writeFrameSlotNode == null) {
CompilerDirectives.transferToInterpreter();
writeFrameSlotNode = insert(WriteFrameSlotNodeGen.create(frameSlot));
}

final Object value = valueNode.execute(frame);
return writeFrameSlotNode.executeWrite(frame, value);
}

@Override
public Object isDefined(VirtualFrame frame) {
return create7BitString("assignment", UTF8Encoding.INSTANCE);
return coreStrings().ASSIGNMENT.createInstance();
}

}
Original file line number Diff line number Diff line change
@@ -134,6 +134,7 @@
import org.jruby.truffle.language.locals.FlipFlopStateNode;
import org.jruby.truffle.language.locals.InitFlipFlopSlotNode;
import org.jruby.truffle.language.locals.LocalFlipFlopStateNode;
import org.jruby.truffle.language.locals.LocalVariableType;
import org.jruby.truffle.language.locals.ReadLocalVariableNode;
import org.jruby.truffle.language.locals.WriteLocalVariableNode;
import org.jruby.truffle.language.methods.AddMethodNodeGen;
@@ -327,7 +328,7 @@ public RubyNode visitAttrAssignNode(org.jruby.ast.AttrAssignNode node) {
final org.jruby.ast.Node valueNode = argChildNodes.remove(argChildNodes.size() - 1);

// Evaluate the value and store it in a local variable
writeValue = new WriteLocalVariableNode(context, sourceSection, valueNode.accept(this), frameSlot);
writeValue = new WriteLocalVariableNode(context, sourceSection, frameSlot, valueNode.accept(this));

// Recreate the arguments array, reading that local instead of including the RHS for the last argument
argChildNodes.add(new ReadLocalDummyNode(node.getPosition(), sourceSection, frameSlot));
@@ -372,7 +373,7 @@ public RubyNode visitAttrAssignNode(org.jruby.ast.AttrAssignNode node) {
boolean isAccessorOnSelf = (node.getReceiverNode() instanceof org.jruby.ast.SelfNode);
final RubyNode actualCall = translateCallNode(callNode, isAccessorOnSelf, false);

final RubyNode ret = sequence(context, sourceSection, Arrays.asList(writeValue, actualCall, new ReadLocalVariableNode(context, sourceSection, frameSlot)));
final RubyNode ret = sequence(context, sourceSection, Arrays.asList(writeValue, actualCall, new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, frameSlot)));

return addNewlineIfNeeded(node, ret);
}
@@ -1396,7 +1397,7 @@ public RubyNode visitFlipNode(org.jruby.ast.FlipNode node) {

final FlipFlopStateNode stateNode = createFlipFlopState(sourceSection, 0);

final RubyNode ret = new FlipFlopNode(context, sourceSection, begin, end, stateNode, node.isExclusive());
final RubyNode ret = new FlipFlopNode(node.isExclusive(), sourceSection, begin, end, stateNode, context);
return addNewlineIfNeeded(node, ret);
}

@@ -1405,9 +1406,9 @@ protected FlipFlopStateNode createFlipFlopState(SourceSection sourceSection, int
environment.getFlipFlopStates().add(frameSlot);

if (depth == 0) {
return new LocalFlipFlopStateNode(sourceSection, frameSlot);
return new LocalFlipFlopStateNode(frameSlot);
} else {
return new DeclarationFlipFlopStateNode(sourceSection, depth, frameSlot);
return new DeclarationFlipFlopStateNode(depth, frameSlot);
}
}

@@ -3125,7 +3126,7 @@ protected String getIdentifier() {
public RubyNode visitOther(org.jruby.ast.Node node) {
if (node instanceof ReadLocalDummyNode) {
final ReadLocalDummyNode readLocal = (ReadLocalDummyNode) node;
final RubyNode ret = new ReadLocalVariableNode(context, readLocal.getSourceSection(), readLocal.getFrameSlot());
final RubyNode ret = new ReadLocalVariableNode(context, readLocal.getSourceSection(), LocalVariableType.FRAME_LOCAL, readLocal.getFrameSlot());
return addNewlineIfNeeded(node, ret);
} else {
throw new UnsupportedOperationException();
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
import org.jruby.truffle.language.control.IfElseNode;
import org.jruby.truffle.language.control.IfNode;
import org.jruby.truffle.language.literal.NilLiteralNode;
import org.jruby.truffle.language.locals.LocalVariableType;
import org.jruby.truffle.language.locals.ReadLocalVariableNode;
import org.jruby.truffle.language.locals.WriteLocalVariableNode;

@@ -257,7 +258,7 @@ public RubyNode visitKeywordRestArgNode(org.jruby.ast.KeywordRestArgNode node) {
final RubyNode readNode = new ReadKeywordRestArgumentNode(context, sourceSection, required, excludedKeywords.toArray(new String[excludedKeywords.size()]));
final FrameSlot slot = methodBodyTranslator.getEnvironment().getFrameDescriptor().findOrAddFrameSlot(node.getName());

return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

@Override
@@ -293,7 +294,7 @@ public RubyNode visitKeywordArgNode(org.jruby.ast.KeywordArgNode node) {

final RubyNode readNode = new ReadKeywordArgumentNode(context, sourceSection, required, name, defaultValue);

return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

@Override
@@ -302,7 +303,7 @@ public RubyNode visitArgumentNode(org.jruby.ast.ArgumentNode node) {

final RubyNode readNode = readArgument(sourceSection);
final FrameSlot slot = methodBodyTranslator.getEnvironment().getFrameDescriptor().findFrameSlot(node.getName());
return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

private RubyNode readArgument(SourceSection sourceSection) {
@@ -338,7 +339,7 @@ public RubyNode visitRestArgNode(org.jruby.ast.RestArgNode node) {
}

final FrameSlot slot = methodBodyTranslator.getEnvironment().getFrameDescriptor().findFrameSlot(node.getName());
return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

@Override
@@ -347,7 +348,7 @@ public RubyNode visitBlockArgNode(org.jruby.ast.BlockArgNode node) {

final RubyNode readNode = new ReadBlockNode(context, sourceSection, context.getCoreLibrary().getNilObject());
final FrameSlot slot = methodBodyTranslator.getEnvironment().getFrameDescriptor().findFrameSlot(node.getName());
return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

@Override
@@ -394,7 +395,7 @@ private RubyNode translateLocalAssignment(ISourcePosition sourcePosition, String
// Just consider the circular case for now as that's all that's speced

if (calledName.equals(name)) {
defaultValue = new ReadLocalVariableNode(context, sourceSection, slot);
defaultValue = new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, slot);
} else {
defaultValue = valueNode.accept(this);
}
@@ -439,7 +440,7 @@ private RubyNode translateLocalAssignment(ISourcePosition sourcePosition, String
readNode = ArraySliceNodeGen.create(context, sourceSection, index, indexFromEnd, loadArray(sourceSection));
}

return new WriteLocalVariableNode(context, sourceSection, readNode, slot);
return new WriteLocalVariableNode(context, sourceSection, slot, readNode);
}

@Override
@@ -582,12 +583,12 @@ public RubyNode visitMultipleAsgnNode(MultipleAsgnNode node) {
final RubyNode nil = sequence(context, sourceSection, nilSequence);

return sequence(context, sourceSection, Arrays.asList(new WriteLocalVariableNode(context, sourceSection,
SplatCastNodeGen.create(context, sourceSection, SplatCastNode.NilBehavior.ARRAY_WITH_NIL, true,
readArgument(sourceSection)), arraySlot), new IfElseNode(context, sourceSection,
new IsNilNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, arraySlot)),
arraySlot, SplatCastNodeGen.create(context, sourceSection, SplatCastNode.NilBehavior.ARRAY_WITH_NIL, true,
readArgument(sourceSection))), new IfElseNode(context, sourceSection,
new IsNilNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, arraySlot)),
nil,
new IfElseNode(context, sourceSection,
new ArrayIsAtLeastAsLargeAsNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, arraySlot), node.getPreCount() + node.getPostCount()),
new ArrayIsAtLeastAsLargeAsNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, arraySlot), node.getPreCount() + node.getPostCount()),
notNilAtLeastAsLarge,
notNilSmaller))));
}
@@ -611,7 +612,7 @@ protected boolean useArray() {
}

protected RubyNode loadArray(SourceSection sourceSection) {
return new ReadLocalVariableNode(context, sourceSection, arraySlotStack.peek().getArraySlot());
return new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, arraySlotStack.peek().getArraySlot());
}

@Override
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@
import org.jruby.truffle.language.control.SequenceNode;
import org.jruby.truffle.language.dispatch.RespondToNode;
import org.jruby.truffle.language.locals.FlipFlopStateNode;
import org.jruby.truffle.language.locals.LocalVariableType;
import org.jruby.truffle.language.locals.ReadLocalVariableNode;
import org.jruby.truffle.language.locals.WriteLocalVariableNode;
import org.jruby.truffle.language.methods.Arity;
@@ -99,15 +100,15 @@ public BlockDefinitionNode compileBlockNode(SourceSection sourceSection, String
final RubyNode castArrayNode = ArrayCastNodeGen.create(context, sourceSection, readArrayNode);

final FrameSlot arraySlot = environment.declareVar(environment.allocateLocalTemp("destructure"));
final RubyNode writeArrayNode = new WriteLocalVariableNode(context, sourceSection, castArrayNode, arraySlot);
final RubyNode writeArrayNode = new WriteLocalVariableNode(context, sourceSection, arraySlot, castArrayNode);

final LoadArgumentsTranslator destructureArgumentsTranslator = new LoadArgumentsTranslator(currentNode, context, source, isProc, this);
destructureArgumentsTranslator.pushArraySlot(arraySlot);
final RubyNode newDestructureArguments = argsNode.accept(destructureArgumentsTranslator);

final RubyNode shouldDestructure = new ShouldDestructureNode(context, sourceSection, new RespondToNode(context, sourceSection, readArrayNode, "to_ary"));

final RubyNode arrayWasNotNil = sequence(context, sourceSection, Arrays.asList(writeArrayNode, new NotNode(context, sourceSection, new IsNilNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, arraySlot)))));
final RubyNode arrayWasNotNil = sequence(context, sourceSection, Arrays.asList(writeArrayNode, new NotNode(context, sourceSection, new IsNilNode(context, sourceSection, new ReadLocalVariableNode(context, sourceSection, LocalVariableType.FRAME_LOCAL, arraySlot)))));

final RubyNode shouldDestructureAndArrayWasNotNil = new AndNode(context, sourceSection,
shouldDestructure,
Original file line number Diff line number Diff line change
@@ -171,7 +171,7 @@ private RubyRootNode parse(Node currentNode, RubyContext context, Source source,
final String name = argumentNames[n];
final RubyNode readNode = new ReadPreArgumentNode(context, sourceSection, n, MissingArgumentBehaviour.NIL);
final FrameSlot slot = environment.getFrameDescriptor().findFrameSlot(name);
sequence.add(new WriteLocalVariableNode(context, sourceSection, readNode, slot));
sequence.add(new WriteLocalVariableNode(context, sourceSection, slot, readNode));
}

sequence.add(truffleNode);
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import org.jruby.truffle.language.LexicalScope;
import org.jruby.truffle.language.control.BreakID;
import org.jruby.truffle.language.control.ReturnID;
import org.jruby.truffle.language.locals.LocalVariableType;
import org.jruby.truffle.language.locals.ReadDeclarationVariableNode;
import org.jruby.truffle.language.locals.ReadLocalVariableNode;
import org.jruby.truffle.language.methods.SharedMethodInfo;
@@ -146,10 +147,22 @@ public ReadLocalNode findLocalVarNode(String name, SourceSection sourceSection)
level++;
FrameSlot slot = current.getFrameDescriptor().findFrameSlot(name);
if (slot != null) {
final LocalVariableType type;

if (Translator.FRAME_LOCAL_GLOBAL_VARIABLES.contains(name)) {
if (Translator.ALWAYS_DEFINED_GLOBALS.contains(name)) {
type = LocalVariableType.ALWAYS_DEFINED_GLOBAL;
} else {
type = LocalVariableType.FRAME_LOCAL_GLOBAL;
}
} else {
type = LocalVariableType.FRAME_LOCAL;
}

if (level == 0) {
return new ReadLocalVariableNode(context, sourceSection, slot);
return new ReadLocalVariableNode(context, sourceSection, type, slot);
} else {
return new ReadDeclarationVariableNode(context, sourceSection, level, slot);
return new ReadDeclarationVariableNode(context, sourceSection, type, level, slot);
}
}