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

Commits on Nov 25, 2015

  1. Copy the full SHA
    69223cd View commit details
  2. Copy the full SHA
    39e1ae9 View commit details
  3. Copy the full SHA
    f8dd00c View commit details
  4. Copy the full SHA
    a68e53d View commit details
Showing with 168 additions and 100 deletions.
  1. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/cast/NumericToFloatNode.java
  2. +21 −22 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  3. +6 −6 truffle/src/main/java/org/jruby/truffle/nodes/core/MathNodes.java
  4. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
  5. +4 −4 truffle/src/main/java/org/jruby/truffle/nodes/core/UnboundMethodNodes.java
  6. +3 −0 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedDispatchNode.java
  7. +10 −8 ...nodes/dispatch/{CachedBoxedMethodMissingDispatchNode.java → CachedMethodMissingDispatchNode.java}
  8. +11 −9 ...nodes/dispatch/{CachedBoxedReturnMissingDispatchNode.java → CachedReturnMissingDispatchNode.java}
  9. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UncachedDispatchNode.java
  10. +7 −7 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UnresolvedDispatchNode.java
  11. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/exceptions/RescueAnyNode.java
  12. +8 −9 truffle/src/main/java/org/jruby/truffle/nodes/methods/LookupMethodNode.java
  13. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/objects/MetaClassNode.java
  14. +78 −0 truffle/src/main/java/org/jruby/truffle/nodes/objects/MetaClassWithShapeCacheNode.java
  15. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/VMPrimitiveNodes.java
  16. +10 −26 truffle/src/main/java/org/jruby/truffle/nodes/supercall/LookupSuperMethodNode.java
  17. +1 −0 truffle/src/main/java/org/jruby/truffle/runtime/layouts/BasicObjectLayout.java
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ protected double fallback(Object value) {
}

protected boolean isNumeric(VirtualFrame frame, Object value) {
return isANode.executeIsA(frame, value, getContext().getCoreLibrary().getNumericClass());
return isANode.executeIsA(value, getContext().getCoreLibrary().getNumericClass());
}

}
43 changes: 21 additions & 22 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -1083,7 +1083,7 @@ public IsANode(RubyContext context, SourceSection sourceSection) {
metaClassNode = MetaClassNodeGen.create(context, sourceSection, null);
}

public abstract boolean executeIsA(VirtualFrame frame, Object self, DynamicObject rubyClass);
public abstract boolean executeIsA(Object self, DynamicObject rubyClass);

@Specialization(guards = { "isNil(nil)", "!isRubyModule(nil)" })
public boolean isANil(DynamicObject self, Object nil) {
@@ -1092,12 +1092,11 @@ public boolean isANil(DynamicObject self, Object nil) {

@Specialization(
limit = "getCacheLimit()",
guards = { "isRubyModule(module)", "getMetaClass(frame, self) == cachedMetaClass", "module == cachedModule" },
guards = { "isRubyModule(module)", "getMetaClass(self) == cachedMetaClass", "module == cachedModule" },
assumptions = "getUnmodifiedAssumption(cachedModule)")
public boolean isACached(VirtualFrame frame,
Object self,
public boolean isACached(Object self,
DynamicObject module,
@Cached("getMetaClass(frame, self)") DynamicObject cachedMetaClass,
@Cached("getMetaClass(self)") DynamicObject cachedMetaClass,
@Cached("module") DynamicObject cachedModule,
@Cached("isA(cachedMetaClass, cachedModule)") boolean result) {
return result;
@@ -1108,12 +1107,12 @@ public Assumption getUnmodifiedAssumption(DynamicObject module) {
}

@Specialization(guards = "isRubyModule(module)")
public boolean isAUncached(VirtualFrame frame, Object self, DynamicObject module) {
return isA(getMetaClass(frame, self), module);
public boolean isAUncached(Object self, DynamicObject module) {
return isA(getMetaClass(self), module);
}

@Specialization(guards = "!isRubyModule(module)")
public boolean isATypeError(VirtualFrame frame, Object self, Object module) {
public boolean isATypeError(Object self, Object module) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("class or module required", this));
}
@@ -1123,8 +1122,8 @@ protected boolean isA(DynamicObject metaClass, DynamicObject module) {
return ModuleOperations.assignableTo(metaClass, module);
}

protected DynamicObject getMetaClass(VirtualFrame frame, Object object) {
return metaClassNode.executeMetaClass(frame, object);
protected DynamicObject getMetaClass(Object object) {
return metaClassNode.executeMetaClass(object);
}

protected int getCacheLimit() {
@@ -1226,13 +1225,13 @@ public RubyNode coerceToString(RubyNode name) {
@Specialization
public DynamicObject method(VirtualFrame frame, Object self, DynamicObject name) {
final String normalizedName = nameToJavaStringNode.executeToJavaString(frame, name);
InternalMethod method = lookupMethodNode.executeLookupMethod(frame, self, normalizedName);
InternalMethod method = lookupMethodNode.executeLookupMethod(self, normalizedName);

if (method == null) {
CompilerDirectives.transferToInterpreter();

if (respondToMissingNode.callBoolean(frame, self, "respond_to_missing?", null, name, true)) {
final InternalMethod methodMissing = lookupMethodNode.executeLookupMethod(frame, self, "method_missing").withName(normalizedName);
final InternalMethod methodMissing = lookupMethodNode.executeLookupMethod(self, "method_missing").withName(normalizedName);
final SharedMethodInfo info = methodMissing.getSharedMethodInfo().withName(normalizedName);

final RubyNode newBody = new CallMethodMissingWithStaticName(getContext(), info.getSourceSection(), name);
@@ -1292,9 +1291,9 @@ public RubyNode coerceToBoolean(RubyNode regular) {
}

@Specialization(guards = "regular")
public DynamicObject methodsRegular(VirtualFrame frame, Object self, boolean regular,
public DynamicObject methodsRegular(Object self, boolean regular,
@Cached("createMetaClassNode()") MetaClassNode metaClassNode) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);
final DynamicObject metaClass = metaClassNode.executeMetaClass(self);

CompilerDirectives.transferToInterpreter();
Object[] objects = Layouts.MODULE.getFields(metaClass).filterMethodsOnObject(getContext(), regular, MethodFilter.PUBLIC_PROTECTED).toArray();
@@ -1350,8 +1349,8 @@ public RubyNode coerceToBoolean(RubyNode includeAncestors) {
}

@Specialization
public DynamicObject privateMethods(VirtualFrame frame, Object self, boolean includeAncestors) {
DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);
public DynamicObject privateMethods(Object self, boolean includeAncestors) {
DynamicObject metaClass = metaClassNode.executeMetaClass(self);

CompilerDirectives.transferToInterpreter();
Object[] objects = Layouts.MODULE.getFields(metaClass).filterMethodsOnObject(getContext(), includeAncestors, MethodFilter.PRIVATE).toArray();
@@ -1397,8 +1396,8 @@ public RubyNode coerceToBoolean(RubyNode includeAncestors) {
}

@Specialization
public DynamicObject protectedMethods(VirtualFrame frame, Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);
public DynamicObject protectedMethods(Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(self);

CompilerDirectives.transferToInterpreter();
Object[] objects = Layouts.MODULE.getFields(metaClass).filterMethodsOnObject(getContext(), includeAncestors, MethodFilter.PROTECTED).toArray();
@@ -1427,8 +1426,8 @@ public RubyNode coerceToBoolean(RubyNode includeAncestors) {
}

@Specialization
public DynamicObject publicMethods(VirtualFrame frame, Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);
public DynamicObject publicMethods(Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(self);

CompilerDirectives.transferToInterpreter();
Object[] objects = Layouts.MODULE.getFields(metaClass).filterMethodsOnObject(getContext(), includeAncestors, MethodFilter.PUBLIC).toArray();
@@ -1761,8 +1760,8 @@ public RubyNode coerceToBoolean(RubyNode includeAncestors) {
}

@Specialization
public DynamicObject singletonMethods(VirtualFrame frame, Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);
public DynamicObject singletonMethods(Object self, boolean includeAncestors) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(self);

if (!Layouts.CLASS.getIsSingleton(metaClass)) {
return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), null, 0);
Original file line number Diff line number Diff line change
@@ -363,7 +363,7 @@ public DynamicObject frexp(double a) {

@Fallback
public DynamicObject frexp(VirtualFrame frame, Object a) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass())) {
return frexp(floatNode.callFloat(frame, a, "to_f", null));
} else {
CompilerDirectives.transferToInterpreter();
@@ -521,7 +521,7 @@ public double function(double a, double b) {

@Fallback
public double function(VirtualFrame frame, Object a, Object b) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass())) {
return function(
floatANode.callFloat(frame, a, "to_f", null),
integerBNode.callLongFixnum(frame, b, "to_int", null));
@@ -578,7 +578,7 @@ public DynamicObject lgamma(double a) {

@Fallback
public DynamicObject lgamma(VirtualFrame frame, Object a) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass())) {
return lgamma(floatNode.callFloat(frame, a, "to_f", null));
} else {
CompilerDirectives.transferToInterpreter();
@@ -617,7 +617,7 @@ public double function(double a, NotProvided b) {

@Specialization
public double function(VirtualFrame frame, Object a, NotProvided b) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass())) {
return doFunction(floatANode.callFloat(frame, a, "to_f", null));
} else {
CompilerDirectives.transferToInterpreter();
@@ -795,7 +795,7 @@ public double function(double a) {

@Fallback
public double function(VirtualFrame frame, Object a) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass())) {
return doFunction(floatNode.callFloat(frame, a, "to_f", null));
} else {
CompilerDirectives.transferToInterpreter();
@@ -906,7 +906,7 @@ public double function(double a, double b) {

@Fallback
public double function(VirtualFrame frame, Object a, Object b) {
if (isANode.executeIsA(frame, a, getContext().getCoreLibrary().getNumericClass()) && isANode.executeIsA(frame, b, getContext().getCoreLibrary().getNumericClass())) {
if (isANode.executeIsA(a, getContext().getCoreLibrary().getNumericClass()) && isANode.executeIsA(b, getContext().getCoreLibrary().getNumericClass())) {
return doFunction(
floatANode.callFloat(frame, a, "to_f", null),
floatBNode.callFloat(frame, b, "to_f", null));
Original file line number Diff line number Diff line change
@@ -102,8 +102,8 @@ public boolean containsInstance(DynamicObject module, DynamicObject instance) {
}

@Specialization(guards = "!isDynamicObject(instance)")
public boolean containsInstance(VirtualFrame frame, DynamicObject module, Object instance) {
return includes(metaClassNode.executeMetaClass(frame, instance), module);
public boolean containsInstance(DynamicObject module, Object instance) {
return includes(metaClassNode.executeMetaClass(instance), module);
}

@TruffleBoundary
Original file line number Diff line number Diff line change
@@ -81,8 +81,8 @@ public BindNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public DynamicObject bind(VirtualFrame frame, DynamicObject unboundMethod, Object object) {
final DynamicObject objectMetaClass = metaClass(frame, object);
public DynamicObject bind(DynamicObject unboundMethod, Object object) {
final DynamicObject objectMetaClass = metaClass(object);

if (!canBindMethodToModuleNode.executeCanBindMethodToModule(Layouts.UNBOUND_METHOD.getMethod(unboundMethod), objectMetaClass)) {
CompilerDirectives.transferToInterpreter();
@@ -99,8 +99,8 @@ public DynamicObject bind(VirtualFrame frame, DynamicObject unboundMethod, Objec
return Layouts.METHOD.createMethod(getContext().getCoreLibrary().getMethodFactory(), object, Layouts.UNBOUND_METHOD.getMethod(unboundMethod));
}

protected DynamicObject metaClass(VirtualFrame frame, Object object) {
return metaClassNode.executeMetaClass(frame, object);
protected DynamicObject metaClass(Object object) {
return metaClassNode.executeMetaClass(object);
}

}
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
public class CachedBoxedDispatchNode extends CachedDispatchNode {

private final Shape expectedShape;
private final Assumption validShape;
private final Assumption unmodifiedAssumption;

private final InternalMethod method;
@@ -39,6 +40,7 @@ public CachedBoxedDispatchNode(
super(context, cachedName, next, dispatchAction);

this.expectedShape = expectedShape;
this.validShape = expectedShape.getValidAssumption();
this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption();
this.next = next;
this.method = method;
@@ -72,6 +74,7 @@ public Object executeDispatch(
// Check the class has not been modified

try {
validShape.check();
unmodifiedAssumption.check();
} catch (InvalidAssumptionException e) {
return resetAndDispatch(
Original file line number Diff line number Diff line change
@@ -15,33 +15,36 @@
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;

import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNode;
import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;

public class CachedBoxedMethodMissingDispatchNode extends CachedDispatchNode {
public class CachedMethodMissingDispatchNode extends CachedDispatchNode {

private final Shape expectedShape;
private final DynamicObject expectedClass;
private final Assumption unmodifiedAssumption;
private final InternalMethod method;

@Child private MetaClassWithShapeCacheNode metaClassNode;
@Child private DirectCallNode callNode;

public CachedBoxedMethodMissingDispatchNode(
public CachedMethodMissingDispatchNode(
RubyContext context,
Object cachedName,
DispatchNode next,
Shape expectedShape,
DynamicObject expectedClass,
InternalMethod method,
DispatchAction dispatchAction) {
super(context, cachedName, next, dispatchAction);

this.expectedShape = expectedShape;
this.expectedClass = expectedClass;
this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption();
this.method = method;
this.metaClassNode = MetaClassWithShapeCacheNodeGen.create(context, getSourceSection(), null);
this.callNode = Truffle.getRuntime().createDirectCallNode(method.getCallTarget());

/*
@@ -65,8 +68,7 @@ public CachedBoxedMethodMissingDispatchNode(
@Override
protected boolean guard(Object methodName, Object receiver) {
return guardName(methodName) &&
(receiver instanceof DynamicObject) &&
((DynamicObject) receiver).getShape() == expectedShape;
metaClassNode.executeMetaClass(receiver) == expectedClass;
}

@Override
Original file line number Diff line number Diff line change
@@ -13,34 +13,36 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;

import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNode;
import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

public class CachedBoxedReturnMissingDispatchNode extends CachedDispatchNode {
public class CachedReturnMissingDispatchNode extends CachedDispatchNode {

private final Shape expectedShape;
private final DynamicObject expectedClass;
private final Assumption unmodifiedAssumption;

public CachedBoxedReturnMissingDispatchNode(
@Child private MetaClassWithShapeCacheNode metaClassNode;

public CachedReturnMissingDispatchNode(
RubyContext context,
Object cachedName,
DispatchNode next,
Shape expectedShape,
DynamicObject expectedClass,
DispatchAction dispatchAction) {
super(context, cachedName, next, dispatchAction);

this.expectedShape = expectedShape;
this.expectedClass = expectedClass;
this.unmodifiedAssumption = Layouts.MODULE.getFields(expectedClass).getUnmodifiedAssumption();
this.next = next;
this.metaClassNode = MetaClassWithShapeCacheNodeGen.create(context, getSourceSection(), null);
}

@Override
protected boolean guard(Object methodName, Object receiver) {
return guardName(methodName) &&
(receiver instanceof DynamicObject) &&
((DynamicObject) receiver).getShape() == expectedShape;
metaClassNode.executeMetaClass(receiver) == expectedClass;
}

@Override
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ public Object executeDispatch(
Object[] argumentsObjects) {
final DispatchAction dispatchAction = getDispatchAction();

final DynamicObject callerClass = ignoreVisibility ? null : metaClassNode.executeMetaClass(frame, RubyArguments.getSelf(frame.getArguments()));
final DynamicObject callerClass = ignoreVisibility ? null : metaClassNode.executeMetaClass(RubyArguments.getSelf(frame.getArguments()));

final InternalMethod method = lookup(callerClass, receiverObject, toJavaStringNode.executeJavaString(frame, name), ignoreVisibility);

Original file line number Diff line number Diff line change
@@ -160,6 +160,9 @@ private DispatchNode doDynamicObject(
callerClass = getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));
}

// Make sure to have an up-to-date Shape.
((DynamicObject) receiverObject).updateShape();

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

if (method == null) {
@@ -194,13 +197,10 @@ private DispatchNode createMethodMissingNode(
DispatchNode first,
Object methodName,
Object receiverObject) {
// TODO (eregon, 26 Aug. 2015): should handle primitive types as well
final Shape shape = (receiverObject instanceof DynamicObject) ? ((DynamicObject) receiverObject).getShape() : null;

switch (missingBehavior) {
case RETURN_MISSING: {
return new CachedBoxedReturnMissingDispatchNode(getContext(), methodName, first, shape,
getContext().getCoreLibrary().getMetaClass(receiverObject), getDispatchAction());
return new CachedReturnMissingDispatchNode(getContext(), methodName, first, getContext().getCoreLibrary().getMetaClass(receiverObject),
getDispatchAction());
}

case CALL_METHOD_MISSING: {
@@ -211,8 +211,8 @@ private DispatchNode createMethodMissingNode(
receiverObject.toString() + " didn't have a #method_missing", this));
}

return new CachedBoxedMethodMissingDispatchNode(getContext(), methodName, first, shape,
getContext().getCoreLibrary().getMetaClass(receiverObject), method, getDispatchAction());
return new CachedMethodMissingDispatchNode(getContext(), methodName, first, getContext().getCoreLibrary().getMetaClass(receiverObject),
method, getDispatchAction());
}

default: {
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ public RescueAnyNode(RubyContext context, SourceSection sourceSection, RubyNode

@Override
public boolean canHandle(VirtualFrame frame, DynamicObject exception) {
return isANode.executeIsA(frame, exception, getContext().getCoreLibrary().getStandardErrorClass());
return isANode.executeIsA(exception, getContext().getCoreLibrary().getStandardErrorClass());
}

}
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
@@ -40,17 +39,17 @@ public LookupMethodNode(RubyContext context, SourceSection sourceSection) {
metaClassNode = MetaClassNodeGen.create(context, sourceSection, null);
}

public abstract InternalMethod executeLookupMethod(VirtualFrame frame, Object self, String name);
public abstract InternalMethod executeLookupMethod(Object self, String name);

@Specialization(
guards = {
"metaClass(frame, self) == selfMetaClass",
"metaClass(self) == selfMetaClass",
"name == cachedName"
},
assumptions = "getUnmodifiedAssumption(selfMetaClass)",
limit = "getCacheLimit()")
protected InternalMethod lookupMethodCached(VirtualFrame frame, Object self, String name,
@Cached("metaClass(frame, self)") DynamicObject selfMetaClass,
protected InternalMethod lookupMethodCached(Object self, String name,
@Cached("metaClass(self)") DynamicObject selfMetaClass,
@Cached("name") String cachedName,
@Cached("doLookup(selfMetaClass, name)") InternalMethod method) {
return method;
@@ -61,13 +60,13 @@ public Assumption getUnmodifiedAssumption(DynamicObject module) {
}

@Specialization
protected InternalMethod lookupMethodUncached(VirtualFrame frame, Object self, String name) {
final DynamicObject selfMetaClass = metaClass(frame, self);
protected InternalMethod lookupMethodUncached(Object self, String name) {
final DynamicObject selfMetaClass = metaClass(self);
return doLookup(selfMetaClass, name);
}

protected DynamicObject metaClass(VirtualFrame frame, Object object) {
return metaClassNode.executeMetaClass(frame, object);
protected DynamicObject metaClass(Object object) {
return metaClassNode.executeMetaClass(object);
}

protected InternalMethod doLookup(DynamicObject selfMetaClass, String name) {
Original file line number Diff line number Diff line change
@@ -11,9 +11,9 @@

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -28,7 +28,7 @@ public MetaClassNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract DynamicObject executeMetaClass(VirtualFrame frame, Object value);
public abstract DynamicObject executeMetaClass(Object value);

@Specialization(guards = "value")
protected DynamicObject singletonClassTrue(boolean value) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

/**
* Reads the internal metaclass of an object.
*/
@NodeChild(value="object", type=RubyNode.class)
public abstract class MetaClassWithShapeCacheNode extends RubyNode {

public MetaClassWithShapeCacheNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract DynamicObject executeMetaClass(Object value);

@Specialization(guards = "value")
protected DynamicObject singletonClassTrue(boolean value) {
return getContext().getCoreLibrary().getTrueClass();
}

@Specialization(guards = "!value")
protected DynamicObject singletonClassFalse(boolean value) {
return getContext().getCoreLibrary().getFalseClass();
}

@Specialization
protected DynamicObject singletonClass(int value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
protected DynamicObject singletonClass(long value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
protected DynamicObject singletonClass(double value) {
return getContext().getCoreLibrary().getFloatClass();
}

@Specialization(guards = "object.getShape() == cachedShape",
assumptions = "cachedShape.getValidAssumption()",
limit = "1")
protected DynamicObject cachedSingletonClass(DynamicObject object,
@Cached("object.getShape()") Shape cachedShape,
@Cached("getMetaClass(cachedShape)") DynamicObject metaClass) {
return metaClass;
}

@Specialization
protected DynamicObject singletonClass(DynamicObject object) {
return Layouts.BASIC_OBJECT.getMetaClass(object);
}

protected static DynamicObject getMetaClass(Shape shape) {
return Layouts.BASIC_OBJECT.getMetaClass(shape.getObjectType());
}

}
Original file line number Diff line number Diff line change
@@ -239,8 +239,8 @@ public VMObjectKindOfPrimitiveNode(RubyContext context, SourceSection sourceSect
}

@Specialization(guards = "isRubyModule(rubyClass)")
public boolean vmObjectKindOf(VirtualFrame frame, Object object, DynamicObject rubyClass) {
return isANode.executeIsA(frame, object, rubyClass);
public boolean vmObjectKindOf(Object object, DynamicObject rubyClass) {
return isANode.executeIsA(object, rubyClass);
}

}
Original file line number Diff line number Diff line change
@@ -15,12 +15,12 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.MetaClassNode;
import org.jruby.truffle.nodes.objects.MetaClassNodeGen;
import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNode;
import org.jruby.truffle.nodes.objects.MetaClassWithShapeCacheNodeGen;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
@@ -34,11 +34,11 @@
@NodeChild("self")
public abstract class LookupSuperMethodNode extends RubyNode {

@Child MetaClassNode metaClassNode;
@Child MetaClassWithShapeCacheNode metaClassNode;

public LookupSuperMethodNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
metaClassNode = MetaClassNodeGen.create(context, sourceSection, null);
metaClassNode = MetaClassWithShapeCacheNodeGen.create(context, sourceSection, null);
}

public abstract InternalMethod executeLookupSuperMethod(VirtualFrame frame, Object self);
@@ -51,37 +51,21 @@ public LookupSuperMethodNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = {
"getCurrentMethod(frame) == currentMethod",
"self.getShape() == cachedShape"
"metaClass(self) == selfMetaClass"
},
assumptions = "getUnmodifiedAssumption(selfMetaClass)",
limit = "getCacheLimit()")
protected InternalMethod lookupSuperMethodCachedDynamicObject(VirtualFrame frame, DynamicObject self,
@Cached("getCurrentMethod(frame)") InternalMethod currentMethod,
@Cached("self.getShape()") Shape cachedShape,
@Cached("metaClass(frame, self)") DynamicObject selfMetaClass,
@Cached("doLookup(currentMethod, selfMetaClass)") InternalMethod superMethod) {
return superMethod;
}

@Specialization(guards = {
"getCurrentMethod(frame) == currentMethod",
"!isDynamicObject(self)",
"self.getClass() == cachedClass"
},
assumptions = "getUnmodifiedAssumption(selfMetaClass)",
limit = "getCacheLimit()")
protected InternalMethod lookupSuperMethodCachedPrimitive(VirtualFrame frame, Object self,
@Cached("getCurrentMethod(frame)") InternalMethod currentMethod,
@Cached("self.getClass()") Class<?> cachedClass,
@Cached("metaClass(frame, self)") DynamicObject selfMetaClass,
@Cached("metaClass(self)") DynamicObject selfMetaClass,
@Cached("doLookup(currentMethod, selfMetaClass)") InternalMethod superMethod) {
return superMethod;
}

@Specialization
protected InternalMethod lookupSuperMethodUncached(VirtualFrame frame, Object self) {
final InternalMethod currentMethod = getCurrentMethod(frame);
final DynamicObject selfMetaClass = metaClass(frame, self);
final DynamicObject selfMetaClass = metaClass(self);
return doLookup(currentMethod, selfMetaClass);
}

@@ -93,8 +77,8 @@ protected InternalMethod getCurrentMethod(VirtualFrame frame) {
return RubyArguments.getMethod(frame.getArguments());
}

protected DynamicObject metaClass(VirtualFrame frame, Object object) {
return metaClassNode.executeMetaClass(frame, object);
protected DynamicObject metaClass(Object object) {
return metaClassNode.executeMetaClass(object);
}

protected InternalMethod doLookup(InternalMethod currentMethod, DynamicObject selfMetaClass) {
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ DynamicObjectFactory createBasicObjectShape(@Nullable DynamicObject logicalClass
void setLogicalClass(DynamicObject object, DynamicObject value);

DynamicObjectFactory setMetaClass(DynamicObjectFactory factory, DynamicObject value);
DynamicObject getMetaClass(ObjectType objectType);
DynamicObject getMetaClass(DynamicObject object);
void setMetaClass(DynamicObject object, DynamicObject value);
}