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

Commits on Jul 28, 2015

  1. Copy the full SHA
    c6e1f58 View commit details
  2. [Truffle] Fixed visibility check for methods looked up by respond_to?.

    When looking up a method with `respond_to?`, the caller is `respond_to?` itself, which will be able to see all methods on the receiver.  What we really want to check is the caller of `respond_to?` so we need to look up at the caller frame.
    nirvdrum committed Jul 28, 2015
    2
    Copy the full SHA
    2758b78 View commit details
  3. 2
    Copy the full SHA
    42979c5 View commit details
9 changes: 0 additions & 9 deletions spec/truffle/tags/core/kernel/respond_to_missing_tags.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
fails:Kernel#respond_to_missing? is called with a 2nd argument of false when #respond_to? is
fails:Kernel#respond_to_missing? is called a 2nd argument of false when #respond_to? is called with only 1 argument
fails:Kernel#respond_to_missing? is called with true as the second argument when #respond_to? is
fails:Kernel#respond_to_missing? is called when #respond_to? would return false
fails:Kernel#respond_to_missing? causes #respond_to? to return true if called and not returning false
fails:Kernel#respond_to_missing? causes #respond_to? to return false if called and returning false
fails:Kernel#respond_to_missing? causes #respond_to? to return false if called and returning nil
fails:Kernel#respond_to_missing? is called when obj responds to the given protected method, include_private = false
fails:Kernel#respond_to_missing? is called when obj responds to the given private method, include_private = false
fails:Kernel#respond_to_missing? is called for missing class methods
1 change: 0 additions & 1 deletion spec/truffle/tags/core/kernel/respond_to_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
fails:Kernel#respond_to? returns false if the given method was undefined
fails:Kernel#respond_to? returns false if obj responds to the given protected method
fails:Kernel#respond_to? returns false if obj responds to the given protected method (include_private = false)
Original file line number Diff line number Diff line change
@@ -1604,6 +1604,7 @@ public abstract static class RespondToNode extends CoreMethodNode {

@Child private DoesRespondDispatchHeadNode dispatch;
@Child private DoesRespondDispatchHeadNode dispatchIgnoreVisibility;
@Child private CallDispatchHeadNode respondToMissingNode;
private final ConditionProfile ignoreVisibilityProfile = ConditionProfile.createBinaryProfile();

public RespondToNode(RubyContext context, SourceSection sourceSection) {
@@ -1627,22 +1628,46 @@ public RubyNode coerceToBoolean(RubyNode includeProtectedAndPrivate) {

@Specialization(guards = "isRubyString(name)")
public boolean doesRespondToString(VirtualFrame frame, Object object, RubyBasicObject name, boolean includeProtectedAndPrivate) {
final boolean ret;

if (ignoreVisibilityProfile.profile(includeProtectedAndPrivate)) {
return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
ret = dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
} else {
return dispatch.doesRespondTo(frame, name, object);
ret = dispatch.doesRespondTo(frame, name, object);
}

if (ret) {
return true;
} else {
return respondToMissing(frame, object, name, includeProtectedAndPrivate);
}
}

@Specialization(guards = "isRubySymbol(name)")
public boolean doesRespondToSymbol(VirtualFrame frame, Object object, RubyBasicObject name, boolean includeProtectedAndPrivate) {
final boolean ret;

if (ignoreVisibilityProfile.profile(includeProtectedAndPrivate)) {
return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
ret = dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
} else {
ret = dispatch.doesRespondTo(frame, name, object);
}

if (ret) {
return true;
} else {
return dispatch.doesRespondTo(frame, name, object);
return respondToMissing(frame, object, name, includeProtectedAndPrivate);
}
}

private boolean respondToMissing(VirtualFrame frame, Object object, RubyBasicObject name, boolean includeProtectedAndPrivate) {
if (respondToMissingNode == null) {
CompilerDirectives.transferToInterpreter();
respondToMissingNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
}

return respondToMissingNode.callBoolean(frame, object, "respond_to_missing?", null, name, includeProtectedAndPrivate);
}
}

@CoreMethod(names = "respond_to_missing?", required = 2)
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.interop.messages.Argument;
@@ -170,7 +173,16 @@ private DispatchNode doRubyBasicObject(
Object receiverObject,
Object methodName,
Object argumentsObjects) {
final RubyBasicObject callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));
final RubyBasicObject callerClass;

if (ignoreVisibility) {
callerClass = null;
} else if (getDispatchAction() == DispatchAction.RESPOND_TO_METHOD) {
final Frame callerFrame = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_ONLY, false);
callerClass = getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(callerFrame.getArguments()));
} else {
callerClass = getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));
}

final InternalMethod method = lookup(callerClass, receiverObject, toString(methodName), ignoreVisibility);