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

Commits on Nov 26, 2015

  1. [Truffle] Remember the Proc for a define_method, as it may access the…

    … block declaration frame.
    eregon committed Nov 26, 2015
    Copy the full SHA
    094556d View commit details
  2. add a spec that an object captured by a block, itself captured by #de…

    …fine_method is reachable
    eregon committed Nov 26, 2015
    Copy the full SHA
    6e536d8 View commit details
4 changes: 4 additions & 0 deletions spec/ruby/core/objectspace/each_object_spec.rb
Original file line number Diff line number Diff line change
@@ -81,6 +81,10 @@ class ObjectSpaceSpecEachOtherObject; end
ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_block_implicit)
end

it "finds an object stored in a local variable captured in by a method defined with a block" do
ObjectSpaceFixtures.to_be_found_symbols.should include(:captured_by_define_method)
end

it "finds an object stored in a local variable captured in a Proc#binding" do
binding = Proc.new {
local_in_proc_binding = ObjectSpaceFixtures::ObjectToBeFound.new(:local_in_proc_binding)
5 changes: 5 additions & 0 deletions spec/ruby/core/objectspace/fixtures.rb
Original file line number Diff line number Diff line change
@@ -60,6 +60,11 @@ def self.wait_for_weakref_cleared(weakref)
end
end

o = ObjectToBeFound.new(:captured_by_define_method)
define_method :capturing_method do
o
end

SECOND_LEVEL_CONSTANT = ObjectToBeFound.new(:second_level_constant)

end
Original file line number Diff line number Diff line change
@@ -1107,7 +1107,7 @@ private DynamicObject defineMethod(DynamicObject module, String name, DynamicObj
final RubyRootNode newRootNode = new RubyRootNode(getContext(), info.getSourceSection(), rootNode.getFrameDescriptor(), info, newBody);
final CallTarget newCallTarget = Truffle.getRuntime().createCallTarget(newRootNode);

final InternalMethod method = new InternalMethod(info, name, module, Visibility.PUBLIC, newCallTarget);
final InternalMethod method = InternalMethod.fromProc(info, name, module, Visibility.PUBLIC, proc, newCallTarget);
return addMethod(module, name, method);
}

Original file line number Diff line number Diff line change
@@ -635,6 +635,12 @@ public Set<DynamicObject> getAdjacentObjects() {
}
}

for (InternalMethod method : methods.values()) {
if (method.getProc() != null) {
adjacent.add(method.getProc());
}
}

return adjacent;
}

Original file line number Diff line number Diff line change
@@ -36,22 +36,29 @@ public class InternalMethod implements ObjectGraphNode {
private final DynamicObject declaringModule;
private final Visibility visibility;
private final boolean undefined;
private final DynamicObject proc; // only if method is created from a Proc

private final CallTarget callTarget;

public static InternalMethod fromProc(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, DynamicObject proc, CallTarget callTarget) {
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, false, proc, callTarget);
}

public InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, false, callTarget);
this(sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget);
}

private InternalMethod(SharedMethodInfo sharedMethodInfo, String name, DynamicObject declaringModule,
Visibility visibility, boolean undefined, CallTarget callTarget) {
Visibility visibility, boolean undefined, DynamicObject proc, CallTarget callTarget) {
assert RubyGuards.isRubyModule(declaringModule);
this.sharedMethodInfo = sharedMethodInfo;
this.declaringModule = declaringModule;
this.name = name;
this.visibility = visibility;
this.undefined = undefined;
this.proc = proc;
this.callTarget = callTarget;
}

@@ -75,6 +82,10 @@ public boolean isUndefined() {
return undefined;
}

public DynamicObject getProc() {
return proc;
}

public CallTarget getCallTarget(){
return callTarget;
}
@@ -85,28 +96,28 @@ public InternalMethod withDeclaringModule(DynamicObject newDeclaringModule) {
if (newDeclaringModule == declaringModule) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, name, newDeclaringModule, visibility, undefined, callTarget);
return new InternalMethod(sharedMethodInfo, name, newDeclaringModule, visibility, undefined, proc, callTarget);
}
}

public InternalMethod withName(String newName) {
if (newName.equals(name)) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, newName, declaringModule, visibility, undefined, callTarget);
return new InternalMethod(sharedMethodInfo, newName, declaringModule, visibility, undefined, proc, callTarget);
}
}

public InternalMethod withVisibility(Visibility newVisibility) {
if (newVisibility == visibility) {
return this;
} else {
return new InternalMethod(sharedMethodInfo, name, declaringModule, newVisibility, undefined, callTarget);
return new InternalMethod(sharedMethodInfo, name, declaringModule, newVisibility, undefined, proc, callTarget);
}
}

public InternalMethod undefined() {
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, true, callTarget);
return new InternalMethod(sharedMethodInfo, name, declaringModule, visibility, true, proc, callTarget);
}

public boolean isVisibleTo(Node currentNode, DynamicObject callerClass) {