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

Commits on Sep 24, 2015

  1. Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    571c33f View commit details
  2. [Truffle] Make sure to not cache a nonexistent variable.

    * Variables can only be added to a FrameDescriptor,
      so we do not need to depend on the frame Assumption if we found a slot.
    eregon committed Sep 24, 2015
    Copy the full SHA
    a30da98 View commit details
Showing with 41 additions and 8 deletions.
  1. +32 −0 spec/ruby/core/binding/local_variable_get_spec.rb
  2. +9 −8 truffle/src/main/java/org/jruby/truffle/nodes/core/BindingNodes.java
32 changes: 32 additions & 0 deletions spec/ruby/core/binding/local_variable_get_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "2.1" do
describe "Binding#local_variable_get" do
it "reads local variables captured in the binding" do
a = 42
bind = binding
bind.local_variable_get(:a).should == 42
end

it "raises a NameError for missing variables" do
bind = BindingSpecs::Demo.new(1).get_empty_binding

lambda {
bind.local_variable_get(:no_such_variable)
}.should raise_error(NameError)
end

it "reads variables added later to the binding" do
bind = BindingSpecs::Demo.new(1).get_empty_binding

lambda {
bind.local_variable_get(:a)
}.should raise_error(NameError)

bind.local_variable_set(:a, 42)

bind.local_variable_get(:a).should == 42
end
end
end
Original file line number Diff line number Diff line change
@@ -70,6 +70,10 @@ public FrameSlotAndDepth(FrameSlot slot, int depth) {
this.slot = slot;
this.depth = depth;
}

public FrameSlot getSlot() {
return slot;
}
}

public static FrameSlotAndDepth findFrameSlotOrNull(DynamicObject binding, DynamicObject symbol) {
@@ -137,19 +141,16 @@ public LocalVariableGetNode(RubyContext context, SourceSection sourceSection) {
"symbol == cachedSymbol",
"!isLastLine(cachedSymbol)",
"compatibleFrames(binding, cachedBinding)",
}, limit = "getCacheLimit()")
"cachedFrameSlot != null"
},
limit = "getCacheLimit()")
public Object localVariableGetCached(DynamicObject binding, DynamicObject symbol,
@Cached("symbol") DynamicObject cachedSymbol,
@Cached("binding") DynamicObject cachedBinding,
@Cached("findFrameSlotOrNull(binding, symbol)") FrameSlotAndDepth cachedFrameSlot,
@Cached("createReadNode(cachedFrameSlot)") ReadFrameSlotNode readLocalVariableNode) {
if (cachedFrameSlot == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(Layouts.SYMBOL.getString(symbol), binding, this));
} else {
final MaterializedFrame frame = RubyArguments.getDeclarationFrame(Layouts.BINDING.getFrame(binding), cachedFrameSlot.depth);
return readLocalVariableNode.executeRead(frame);
}
final MaterializedFrame frame = RubyArguments.getDeclarationFrame(Layouts.BINDING.getFrame(binding), cachedFrameSlot.depth);
return readLocalVariableNode.executeRead(frame);
}

@TruffleBoundary