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

Commits on May 29, 2015

  1. Copy the full SHA
    ba06032 View commit details
  2. Copy the full SHA
    3ee92de View commit details
14 changes: 12 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyGuards.java
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@

import com.oracle.truffle.api.interop.TruffleObject;
import org.jruby.truffle.nodes.core.BigDecimalNodes;
import org.jruby.truffle.nodes.core.MethodNodes;
import org.jruby.truffle.nodes.core.UnboundMethodNodes;
import org.jruby.truffle.runtime.ThreadLocalObject;
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.core.*;
@@ -86,11 +88,19 @@ public static boolean isRubySymbol(Object value) {
}

public static boolean isRubyMethod(Object value) {
return value instanceof RubyMethod;
return (value instanceof RubyBasicObject) && isRubyMethod((RubyBasicObject) value);
}

public static boolean isRubyMethod(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == MethodNodes.METHOD_TYPE;
}

public static boolean isRubyUnboundMethod(Object value) {
return value instanceof RubyUnboundMethod;
return (value instanceof RubyBasicObject) && isRubyUnboundMethod((RubyBasicObject) value);
}

public static boolean isRubyUnboundMethod(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == UnboundMethodNodes.UNBOUND_METHOD_TYPE;
}

public static boolean isRubyBasicObject(Object value) {
Original file line number Diff line number Diff line change
@@ -1043,16 +1043,16 @@ public MethodNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public RubyMethod method(Object object, RubySymbol name) {
public RubyBasicObject method(Object object, RubySymbol name) {
return method(object, name.toString());
}

@Specialization
public RubyMethod method(Object object, RubyString name) {
public RubyBasicObject method(Object object, RubyString name) {
return method(object, name.toString());
}

private RubyMethod method(Object object, String name) {
private RubyBasicObject method(Object object, String name) {
CompilerDirectives.transferToInterpreter();

// TODO(CS, 11-Jan-15) cache this lookup
@@ -1065,7 +1065,7 @@ private RubyMethod method(Object object, String name) {
name, getContext().getCoreLibrary().getLogicalClass(object), this));
}

return new RubyMethod(getContext().getCoreLibrary().getMethodClass(), object, method);
return MethodNodes.createMethod(getContext().getCoreLibrary().getMethodClass(), object, method);
}

}
111 changes: 79 additions & 32 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/MethodNodes.java
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.*;
import com.oracle.truffle.api.source.NullSourceSection;
import com.oracle.truffle.api.source.SourceSection;

@@ -29,10 +30,54 @@
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.object.BasicObjectType;

import java.util.EnumSet;

@CoreClass(name = "Method")
public abstract class MethodNodes {

public static class MethodType extends BasicObjectType {

}

public static final MethodType METHOD_TYPE = new MethodType();

private static final HiddenKey RECEIVER_IDENTIFIER = new HiddenKey("receiver");
public static final Property RECEIVER_PROPERTY;

private static final HiddenKey METHOD_IDENTIFIER = new HiddenKey("method");
public static final Property METHOD_PROPERTY;

private static final DynamicObjectFactory METHOD_FACTORY;

static {
final Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();

RECEIVER_PROPERTY = Property.create(RECEIVER_IDENTIFIER, allocator.locationForType(Object.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);
METHOD_PROPERTY = Property.create(METHOD_IDENTIFIER, allocator.locationForType(InternalMethod.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);

final Shape shape = RubyBasicObject.LAYOUT.createShape(METHOD_TYPE)
.addProperty(RECEIVER_PROPERTY)
.addProperty(METHOD_PROPERTY);

METHOD_FACTORY = shape.createFactory();
}

public static RubyBasicObject createMethod(RubyClass rubyClass, Object receiver, InternalMethod method) {
return new RubyBasicObject(rubyClass, METHOD_FACTORY.newInstance(receiver, method));
}

public static Object getReceiver(RubyBasicObject method) {
assert method.getDynamicObject().getShape().hasProperty(RECEIVER_IDENTIFIER);
return RECEIVER_PROPERTY.get(method.getDynamicObject(), true);
}

public static InternalMethod getMethod(RubyBasicObject method) {
assert method.getDynamicObject().getShape().hasProperty(METHOD_IDENTIFIER);
return (InternalMethod) METHOD_PROPERTY.get(method.getDynamicObject(), true);
}

@CoreMethod(names = { "==", "eql?" }, required = 1)
public abstract static class EqualNode extends CoreMethodArrayArgumentsNode {

@@ -50,13 +95,13 @@ protected boolean areSame(VirtualFrame frame, Object left, Object right) {
return referenceEqualNode.executeReferenceEqual(frame, left, right);
}

@Specialization
public boolean equal(VirtualFrame frame, RubyMethod a, RubyMethod b) {
return areSame(frame, a.getReceiver(), b.getReceiver()) && a.getMethod() == b.getMethod();
@Specialization(guards = "isRubyMethod(b)")
public boolean equal(VirtualFrame frame, RubyBasicObject a, RubyBasicObject b) {
return areSame(frame, getReceiver(a), getReceiver(b)) && getMethod(a) == getMethod(b);
}

@Specialization(guards = "!isRubyMethod(b)")
public boolean equal(RubyMethod a, Object b) {
public boolean equal(RubyBasicObject a, Object b) {
return false;
}

@@ -70,8 +115,8 @@ public ArityNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public int arity(RubyMethod method) {
return method.getMethod().getSharedMethodInfo().getArity().getArityNumber();
public int arity(RubyBasicObject method) {
return getMethod(method).getSharedMethodInfo().getArity().getArityNumber();
}

}
@@ -87,21 +132,21 @@ public CallNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public Object call(VirtualFrame frame, RubyMethod method, Object[] arguments, UndefinedPlaceholder block) {
public Object call(VirtualFrame frame, RubyBasicObject method, Object[] arguments, UndefinedPlaceholder block) {
return doCall(frame, method, arguments, null);
}

@Specialization
public Object doCall(VirtualFrame frame, RubyMethod method, Object[] arguments, RubyProc block) {
public Object doCall(VirtualFrame frame, RubyBasicObject method, Object[] arguments, RubyProc block) {
// TODO(CS 11-Jan-15) should use a cache and DirectCallNode here so that we can inline - but it's
// incompatible with our current dispatch chain.

final InternalMethod internalMethod = method.getMethod();
final InternalMethod internalMethod = getMethod(method);

return callNode.call(frame, method.getMethod().getCallTarget(), RubyArguments.pack(
return callNode.call(frame, getMethod(method).getCallTarget(), RubyArguments.pack(
internalMethod,
internalMethod.getDeclarationFrame(),
method.getReceiver(),
getReceiver(method),
block,
arguments));
}
@@ -116,10 +161,10 @@ public NameNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public RubySymbol name(RubyMethod method) {
public RubySymbol name(RubyBasicObject method) {
CompilerDirectives.transferToInterpreter();

return getContext().getSymbol(method.getMethod().getName());
return getContext().getSymbol(getMethod(method).getName());
}

}
@@ -132,8 +177,8 @@ public OwnerNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public RubyModule owner(RubyMethod method) {
return method.getMethod().getDeclaringModule();
public RubyModule owner(RubyBasicObject method) {
return getMethod(method).getDeclaringModule();
}

}
@@ -147,8 +192,8 @@ public ParametersNode(RubyContext context, SourceSection sourceSection) {

@TruffleBoundary
@Specialization
public RubyArray parameters(RubyMethod method) {
final ArgsNode argsNode = method.getMethod().getSharedMethodInfo().getParseTree().findFirstChild(ArgsNode.class);
public RubyArray parameters(RubyBasicObject method) {
final ArgsNode argsNode = getMethod(method).getSharedMethodInfo().getParseTree().findFirstChild(ArgsNode.class);

final ArgumentDescriptor[] argsDesc = Helpers.argsNodeToArgumentDescriptors(argsNode);

@@ -166,8 +211,8 @@ public ReceiverNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public Object receiver(RubyMethod method) {
return method.getReceiver();
public Object receiver(RubyBasicObject method) {
return getReceiver(method);
}

}
@@ -180,10 +225,10 @@ public SourceLocationNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public Object sourceLocation(RubyMethod method) {
public Object sourceLocation(RubyBasicObject method) {
CompilerDirectives.transferToInterpreter();

SourceSection sourceSection = method.getMethod().getSharedMethodInfo().getSourceSection();
SourceSection sourceSection = getMethod(method).getSharedMethodInfo().getSourceSection();

if (sourceSection instanceof NullSourceSection) {
return nil();
@@ -207,11 +252,11 @@ public UnbindNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public RubyUnboundMethod unbind(VirtualFrame frame, RubyMethod method) {
public RubyBasicObject unbind(VirtualFrame frame, RubyBasicObject method) {
CompilerDirectives.transferToInterpreter();

RubyClass receiverClass = classNode.executeGetClass(frame, method.getReceiver());
return new RubyUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), receiverClass, method.getMethod());
RubyClass receiverClass = classNode.executeGetClass(frame, getReceiver(method));
return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), receiverClass, getMethod(method));
}

}
@@ -224,17 +269,19 @@ public ToProcNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public RubyProc toProc(RubyMethod method) {
public RubyProc toProc(RubyBasicObject methodObject) {
final InternalMethod method = getMethod(methodObject);

return new RubyProc(
getContext().getCoreLibrary().getProcClass(),
RubyProc.Type.LAMBDA,
method.getMethod().getSharedMethodInfo(),
method.getMethod().getCallTarget(),
method.getMethod().getCallTarget(),
method.getMethod().getCallTarget(),
method.getMethod().getDeclarationFrame(),
method.getMethod(),
method.getReceiver(),
method.getSharedMethodInfo(),
method.getCallTarget(),
method.getCallTarget(),
method.getCallTarget(),
method.getDeclarationFrame(),
method,
getReceiver(methodObject),
null);
}

22 changes: 11 additions & 11 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -1014,25 +1014,25 @@ public RubySymbol defineMethod(RubyModule module, String name, RubyProc proc, Un
}

@TruffleBoundary
@Specialization
public RubySymbol defineMethod(RubyModule module, String name, RubyMethod method, UndefinedPlaceholder block) {
module.addMethod(this, method.getMethod().withName(name));
@Specialization(guards = "isRubyMethod(method)")
public RubySymbol defineMethod(RubyModule module, String name, RubyBasicObject method, UndefinedPlaceholder block) {
module.addMethod(this, MethodNodes.getMethod(method).withName(name));
return getContext().getSymbolTable().getSymbol(name);
}

@Specialization
public RubySymbol defineMethod(VirtualFrame frame, RubyModule module, String name, RubyUnboundMethod method, UndefinedPlaceholder block) {
@Specialization(guards = "isRubyUnboundMethod(method)")
public RubySymbol defineMethod(VirtualFrame frame, RubyModule module, String name, RubyBasicObject method, UndefinedPlaceholder block) {
CompilerDirectives.transferToInterpreter();

RubyModule origin = method.getOrigin();
RubyModule origin = UnboundMethodNodes.getOrigin(method);
if (!ModuleOperations.canBindMethodTo(origin, module)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("bind argument must be a subclass of " + origin.getName(), this));
}

// TODO CS 5-Apr-15 TypeError if the method came from a singleton

return addMethod(module, name, method.getMethod());
return addMethod(module, name, UnboundMethodNodes.getMethod(method));
}

private RubySymbol defineMethod(RubyModule module, String name, RubyProc proc) {
@@ -1488,7 +1488,7 @@ public RubyNode coerceToString(RubyNode name) {
}

@Specialization
public RubyUnboundMethod publicInstanceMethod(RubyModule module, String name) {
public RubyBasicObject publicInstanceMethod(RubyModule module, String name) {
CompilerDirectives.transferToInterpreter();

// TODO(CS, 11-Jan-15) cache this lookup
@@ -1502,7 +1502,7 @@ public RubyUnboundMethod publicInstanceMethod(RubyModule module, String name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateMethod(name, module, this));
}

return new RubyUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
}

}
@@ -1592,7 +1592,7 @@ public RubyNode coerceToString(RubyNode name) {
}

@Specialization
public RubyUnboundMethod instanceMethod(RubyModule module, String name) {
public RubyBasicObject instanceMethod(RubyModule module, String name) {
CompilerDirectives.transferToInterpreter();

// TODO(CS, 11-Jan-15) cache this lookup
@@ -1603,7 +1603,7 @@ public RubyUnboundMethod instanceMethod(RubyModule module, String name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedMethod(name, module, this));
}

return new RubyUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
}

}
Loading