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

Commits on Oct 13, 2015

  1. Copy the full SHA
    fd1a5f5 View commit details
  2. Copy the full SHA
    d83c57a View commit details
  3. [Truffle] Calling a private method with insufficient rights should de…

    …legate to #method_missing.
    eregon committed Oct 13, 2015
    Copy the full SHA
    3aa50dc View commit details
6 changes: 0 additions & 6 deletions spec/truffle/tags/core/basicobject/method_missing_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -25,18 +26,21 @@
import org.jruby.truffle.nodes.cast.BooleanCastNodeGen;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.dispatch.DispatchNode;
import org.jruby.truffle.nodes.dispatch.MissingBehavior;
import org.jruby.truffle.nodes.dispatch.RubyCallNode;
import org.jruby.truffle.nodes.methods.DeclarationContext;
import org.jruby.truffle.nodes.methods.UnsupportedOperationBehavior;
import org.jruby.truffle.nodes.objects.AllocateObjectNode;
import org.jruby.truffle.nodes.objects.AllocateObjectNodeGen;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;

@CoreClass(name = "BasicObject")
public abstract class BasicObjectNodes {
@@ -197,40 +201,39 @@ public Object methodMissingNoName(Object self, NotProvided name, Object[] args,

@Specialization
public Object methodMissingNoBlock(Object self, DynamicObject name, Object[] args, NotProvided block) {
return methodMissingBlock(self, name, args, (DynamicObject) null);
return methodMissing(self, name, args, null);
}

@Specialization(guards = "isRubyProc(block)")
public Object methodMissingBlock(Object self, DynamicObject name, Object[] args, DynamicObject block) {
return methodMissing(self, name, args, block);
}

private Object methodMissing(Object self, DynamicObject name, Object[] args, DynamicObject block) {
CompilerDirectives.transferToInterpreter();

assert block == null || RubyGuards.isRubyProc(block);
@TruffleBoundary
private Object methodMissing(Object self, DynamicObject nameObject, Object[] args, DynamicObject block) {
final String name = nameObject.toString();

// TODO: should not be a call to Java toString(), but rather sth like name_err_mesg_to_str() in MRI error.c
if (lastCallWasVCall()) {
throw new RaiseException(
getContext().getCoreLibrary().nameErrorUndefinedLocalVariableOrMethod(
Layouts.SYMBOL.getString(name),
Layouts.MODULE.getFields(getContext().getCoreLibrary().getLogicalClass(self)).getName(),
this));
if (lastCallWasCallingPrivateMethod(self, name)) {
throw new RaiseException(getContext().getCoreLibrary().privateMethodError(name, self, this));
} else if (lastCallWasVCall()) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedLocalVariableOrMethod(name, self, this));
} else {
throw new RaiseException(getContext().getCoreLibrary().noMethodErrorOnReceiver(Layouts.SYMBOL.getString(name), self, this));
throw new RaiseException(getContext().getCoreLibrary().noMethodErrorOnReceiver(name, self, this));
}
}

/**
* See {@link org.jruby.truffle.nodes.dispatch.DispatchNode#lookup}.
* The only way to fail if method is not null and not undefined is visibility.
*/
private boolean lastCallWasCallingPrivateMethod(Object self, String name) {
final InternalMethod method = ModuleOperations.lookupMethod(getContext().getCoreLibrary().getMetaClass(self), name);
return method != null && !method.isUndefined();
}

private boolean lastCallWasVCall() {
final RubyCallNode callNode = NodeUtil.findParent(Truffle.getRuntime().getCallerFrame().getCallNode(), RubyCallNode.class);

if (callNode == null) {
return false;
}

return callNode.isVCall();

return callNode != null && callNode.isVCall();
}

}
Original file line number Diff line number Diff line change
@@ -975,8 +975,9 @@ public RubyNode coerceToString(RubyNode name) {
return NameToJavaStringNodeGen.create(getContext(), getSourceSection(), name);
}

@TruffleBoundary
@Specialization
public Object methodMissing(DynamicObject module, String name) {
public Object constMissing(DynamicObject module, String name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUninitializedConstant(module, name, this));
}

Original file line number Diff line number Diff line change
@@ -54,34 +54,23 @@ protected InternalMethod lookup(
Object receiver,
String name,
boolean ignoreVisibility) {
assert callerClass == null || RubyGuards.isRubyClass(callerClass);
assert ignoreVisibility || RubyGuards.isRubyClass(callerClass);

InternalMethod method = ModuleOperations.lookupMethod(getContext().getCoreLibrary().getMetaClass(receiver), name);
final InternalMethod method = ModuleOperations.lookupMethod(getContext().getCoreLibrary().getMetaClass(receiver), name);

// If no method was found, use #method_missing

if (method == null) {
return null;
}

// Check for methods that are explicitly undefined

if (method.isUndefined()) {
return null;
}

// Check visibility

if (!ignoreVisibility && !method.isVisibleTo(this, callerClass)) {
final DispatchAction dispatchAction = getHeadNode().getDispatchAction();

if (dispatchAction == DispatchAction.CALL_METHOD) {
throw new RaiseException(getContext().getCoreLibrary().privateMethodError(name, getContext().getCoreLibrary().getLogicalClass(receiver), this));
} else if (dispatchAction == DispatchAction.RESPOND_TO_METHOD) {
return null;
} else {
throw new UnsupportedOperationException();
}
return null;
}

return method;
14 changes: 7 additions & 7 deletions truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java
Original file line number Diff line number Diff line change
@@ -265,7 +265,7 @@ public void initialize() {
for (IRubyObject arg : ((org.jruby.RubyArray) runtime.getObject().getConstant("ARGV")).toJavaArray()) {
assert arg != null;

ArrayOperations.append(coreLibrary.getArgv(), Layouts.STRING.createString(Layouts.CLASS.getInstanceFactory(coreLibrary.getStringClass()), StringOperations.encodeByteList(arg.toString(), UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(coreLibrary.getArgv(), StringOperations.createString(this, StringOperations.encodeByteList(arg.toString(), UTF8Encoding.INSTANCE)));
}

// Set the load path
@@ -284,7 +284,7 @@ public void initialize() {
pathString = SourceLoader.JRUBY_SCHEME + pathString.substring("uri:classloader:".length());
}

ArrayOperations.append(loadPath, Layouts.STRING.createString(coreLibrary.getStringFactory(), StringOperations.encodeByteList(pathString, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(loadPath, StringOperations.createString(this, StringOperations.encodeByteList(pathString, UTF8Encoding.INSTANCE)));
}
}

@@ -305,21 +305,21 @@ public void initialize() {
home = home + "/";

// Libraries copied unmodified from MRI
ArrayOperations.append(loadPath, Layouts.STRING.createString(coreLibrary.getStringFactory(), StringOperations.encodeByteList(home + "lib/ruby/truffle/mri", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(loadPath, StringOperations.createString(this, StringOperations.encodeByteList(home + "lib/ruby/truffle/mri", UTF8Encoding.INSTANCE)));

// Our own implementations
ArrayOperations.append(loadPath, Layouts.STRING.createString(coreLibrary.getStringFactory(), StringOperations.encodeByteList(home + "lib/ruby/truffle/truffle", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(loadPath, StringOperations.createString(this, StringOperations.encodeByteList(home + "lib/ruby/truffle/truffle", UTF8Encoding.INSTANCE)));

// Libraries from RubySL
for (String lib : Arrays.asList("rubysl-strscan", "rubysl-stringio",
"rubysl-complex", "rubysl-date", "rubysl-pathname",
"rubysl-tempfile", "rubysl-socket", "rubysl-securerandom",
"rubysl-timeout", "rubysl-webrick")) {
ArrayOperations.append(loadPath, Layouts.STRING.createString(coreLibrary.getStringFactory(), StringOperations.encodeByteList(home + "lib/ruby/truffle/rubysl/" + lib + "/lib", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(loadPath, StringOperations.createString(this, StringOperations.encodeByteList(home + "lib/ruby/truffle/rubysl/" + lib + "/lib", UTF8Encoding.INSTANCE)));
}

// Shims
ArrayOperations.append(loadPath, Layouts.STRING.createString(coreLibrary.getStringFactory(), StringOperations.encodeByteList(home + "lib/ruby/truffle/shims", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null));
ArrayOperations.append(loadPath, StringOperations.createString(this, StringOperations.encodeByteList(home + "lib/ruby/truffle/shims", UTF8Encoding.INSTANCE)));
}

// TODO (eregon, 10/10/2015): this check could be done when a Symbol is created to be much cheaper
@@ -518,7 +518,7 @@ public DynamicObject toTruffle(org.jruby.RubyArray array) {
}

public DynamicObject toTruffle(org.jruby.RubyString jrubyString) {
final DynamicObject truffleString = Layouts.STRING.createString(coreLibrary.getStringFactory(), jrubyString.getByteList().dup(), StringSupport.CR_UNKNOWN, null);
final DynamicObject truffleString = StringOperations.createString(this, jrubyString.getByteList().dup());

if (jrubyString.isTaint()) {
truffleString.define(Layouts.TAINTED_IDENTIFIER, true, 0);
Loading