Skip to content

Commit

Permalink
Showing 51 changed files with 740 additions and 1,149 deletions.
10 changes: 4 additions & 6 deletions core/src/main/java/org/jruby/truffle/nodes/RubyCallNode.java
Original file line number Diff line number Diff line change
@@ -184,23 +184,21 @@ public Object isDefined(VirtualFrame frame) {
return getContext().getCoreLibrary().getNilObject();
}

final RubyBasicObject receiverBasicObject = context.getCoreLibrary().box(receiverObject);

// TODO(CS): this lookup should be cached

final RubyMethod method = ModuleOperations.lookupMethod(receiverBasicObject.getMetaClass(), methodName);
final RubyMethod method = ModuleOperations.lookupMethod(context.getCoreLibrary().getMetaClass(receiverObject), methodName);

final RubyBasicObject self = context.getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments()));
final Object self = RubyArguments.getSelf(frame.getArguments());

if (method == null) {
final Object r = respondToMissing.call(frame, receiverBasicObject, "respond_to_missing?", null, context.makeString(methodName));
final Object r = respondToMissing.call(frame, receiverObject, "respond_to_missing?", null, context.makeString(methodName));

if (r != Dispatch.MISSING && !respondToMissingCast.executeBoolean(frame, r)) {
return getContext().getCoreLibrary().getNilObject();
}
} else if (method.isUndefined()) {
return getContext().getCoreLibrary().getNilObject();
} else if (!ignoreVisibility && !method.isVisibleTo(this, self.getMetaClass())) {
} else if (!ignoreVisibility && !method.isVisibleTo(this, context.getCoreLibrary().getMetaClass(self))) {
return getContext().getCoreLibrary().getNilObject();
}

51 changes: 50 additions & 1 deletion core/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -218,7 +218,56 @@ public static void notDesignedForCompilation() {
CompilerAsserts.neverPartOfCompilation();
}

public static boolean isNil(RubyObject o) {
public static boolean isNil(Object o) {
return o instanceof RubyNilClass;
}

public static boolean isTrue(boolean b) {
return b;
}

public static boolean isModule(RubyBasicObject o) {
return o instanceof RubyModule;
}

public static boolean isArray(Object o) {
return o instanceof RubyArray;
}

public static boolean isFixnum(Object o) {
return o instanceof Integer || o instanceof Long;
}

public static boolean isBignum(Object o) {
return o instanceof BigInteger;
}

public static boolean isFloat(Object o) {
return o instanceof Double;
}

public static boolean isFirstFixnum(Object o) {
return o instanceof Integer || o instanceof Long;
}

public static boolean isFirstBignum(Object o) {
return o instanceof BigInteger;
}

public static boolean isFirstFloat(Object o) {
return o instanceof Double;
}

public static boolean isSecondFixnum(Object a, Object b) {
return b instanceof Integer || b instanceof Long;
}

public static boolean isSecondBignum(Object a, Object b) {
return b instanceof BigInteger;
}

public static boolean isSecondFloat(Object a, Object b) {
return b instanceof Double;
}

}
36 changes: 0 additions & 36 deletions core/src/main/java/org/jruby/truffle/nodes/RubyTypes.java
Original file line number Diff line number Diff line change
@@ -42,15 +42,11 @@
RubyRange.LongFixnumRange.class, //
RubyRange.ObjectRange.class, //
RubyArray.class, //
RubyBignum.class, //
RubyBinding.class, //
RubyClass.class, //
RubyException.class, //
RubyFiber.class, //
RubyFile.class, //
RubyFixnum.IntegerFixnum.class, //
RubyFixnum.LongFixnum.class, //
RubyFloat.class, //
RubyHash.class, //
RubyMatchData.class, //
RubyModule.class, //
@@ -63,8 +59,6 @@
RubySymbol.class, //
RubyThread.class, //
RubyTime.class, //
RubyTrueClass.class, //
RubyFalseClass.class, //
RubiniusChannel.class, //
RubiniusByteArray.class, //
RubyEncodingConverter.class, //
@@ -74,34 +68,4 @@

public class RubyTypes {

@ImplicitCast
public boolean unboxBoolean(RubyTrueClass value) {
return true;
}

@ImplicitCast
public boolean unboxBoolean(RubyFalseClass value) {
return false;
}

@ImplicitCast
public int unboxIntegerFixnum(RubyFixnum.IntegerFixnum value) {
return value.getValue();
}

@ImplicitCast
public long unboxLongFixnum(RubyFixnum.LongFixnum value) {
return value.getValue();
}

@ImplicitCast
public BigInteger unboxBignum(RubyBignum value) {
return value.getValue();
}

@ImplicitCast
public double unboxFloat(RubyFloat value) {
return value.getValue();
}

}
36 changes: 32 additions & 4 deletions core/src/main/java/org/jruby/truffle/nodes/cast/ArrayCastNode.java
Original file line number Diff line number Diff line change
@@ -19,8 +19,11 @@
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyNilClass;

import java.math.BigInteger;

@NodeChild("child")
public abstract class ArrayCastNode extends RubyNode {

@@ -39,17 +42,42 @@ public ArrayCastNode(ArrayCastNode prev) {
protected abstract RubyNode getChild();

@Specialization
public RubyArray doArray(RubyArray array) {
public RubyNilClass cast(boolean value) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization
public RubyNilClass cast(int value) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization
public RubyNilClass cast(long value) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization
public RubyNilClass cast(double value) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization
public RubyNilClass cast(BigInteger value) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization
public RubyArray cast(RubyArray array) {
return array;
}

@Specialization
public RubyNilClass doNil(RubyNilClass nil) {
public RubyNilClass cast(RubyNilClass nil) {
return nil;
}

@Specialization
public Object doObject(VirtualFrame frame, Object object) {
@Specialization(guards = {"!isNil", "!isArray"})
public Object cast(VirtualFrame frame, RubyBasicObject object) {
notDesignedForCompilation();

final Object result = toArrayNode.call(frame, object, "to_ary", null, new Object[]{});
Original file line number Diff line number Diff line change
@@ -39,11 +39,6 @@ public boolean doNil(@SuppressWarnings("unused") RubyNilClass nil) {
return false;
}

@Specialization
public boolean doFalse(@SuppressWarnings("unused") RubyFalseClass falseObject) {
return false;
}

@Specialization
public boolean doBoolean(boolean value) {
return value;
@@ -75,8 +70,7 @@ public boolean doBasicObject(RubyBasicObject object) {
}

protected boolean neitherNilNorFalse(RubyBasicObject object) {
return object != getContext().getCoreLibrary().getNilObject() &&
object != getContext().getCoreLibrary().getFalseObject();
return object != getContext().getCoreLibrary().getNilObject();
}

@Override
81 changes: 0 additions & 81 deletions core/src/main/java/org/jruby/truffle/nodes/cast/BoxingNode.java

This file was deleted.

49 changes: 25 additions & 24 deletions core/src/main/java/org/jruby/truffle/nodes/cast/SplatCastNode.java
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyNilClass;

/**
* Splat as used to cast a value to an array if it isn't already, as in {@code *value}.
@@ -50,43 +51,43 @@ public SplatCastNode(SplatCastNode prev) {
protected abstract RubyNode getChild();

@Specialization
public RubyArray doArray(RubyArray array) {
return array;
public RubyArray splat(RubyNilClass nil) {
switch (nilBehavior) {
case EMPTY_ARRAY:
return new RubyArray(getContext().getCoreLibrary().getArrayClass());

case ARRAY_WITH_NIL:
return RubyArray.fromObject(getContext().getCoreLibrary().getArrayClass(), getContext().getCoreLibrary().getNilObject());

default: {
CompilerAsserts.neverPartOfCompilation();
throw new UnsupportedOperationException();
}
}
}

@Specialization
public RubyArray doObject(VirtualFrame frame, Object object) {
notDesignedForCompilation();

if (object == getContext().getCoreLibrary().getNilObject()) {
switch (nilBehavior) {
case EMPTY_ARRAY:
return new RubyArray(getContext().getCoreLibrary().getArrayClass());
public RubyArray splat(RubyArray array) {
return array;
}

case ARRAY_WITH_NIL:
return RubyArray.fromObject(getContext().getCoreLibrary().getArrayClass(), getContext().getCoreLibrary().getNilObject());
@Specialization(guards = {"!isNil", "!isArray"})
public RubyArray splat(VirtualFrame frame, Object object) {
notDesignedForCompilation();

default: {
CompilerAsserts.neverPartOfCompilation();
throw new UnsupportedOperationException();
}
}
} else if (object instanceof RubyArray) {
return (RubyArray) object;
} else {
if (toA.doesRespondTo(frame, "to_a", object)) {
final Object array = toA.call(frame, object, "to_a", null);

if (array instanceof RubyArray) {
return (RubyArray) array;
}

// TODO(CS): surely this is an error? to_a returned something that was not an array

return RubyArray.fromObject(getContext().getCoreLibrary().getArrayClass(), object);
} else {
return RubyArray.fromObject(getContext().getCoreLibrary().getArrayClass(), object);
}
}

@Override
public void executeVoid(VirtualFrame frame) {
getChild().executeVoid(frame);
}

}
49 changes: 0 additions & 49 deletions core/src/main/java/org/jruby/truffle/nodes/cast/UnboxingNode.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -16,8 +16,6 @@
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.UnboxingNodeFactory;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
@@ -103,39 +101,28 @@ public ReferenceEqualNode(ReferenceEqualNode prev) {
// The @CreateCast is not applied when using this, so the caller needs to unbox itself.
protected abstract boolean executeEqualWithUnboxed(VirtualFrame frame, Object a, Object b);

@CreateCast("arguments") public RubyNode[] createCast(RubyNode[] arguments) {
return new RubyNode[]{
UnboxingNodeFactory.create(getContext(), getSourceSection(), arguments[0]),
UnboxingNodeFactory.create(getContext(), getSourceSection(), arguments[1])
};
}

@Specialization public boolean equal(boolean a, boolean b) { return a == b; }
@Specialization public boolean equal(int a, int b) { return a == b; }
@Specialization public boolean equal(long a, long b) { return a == b; }
@Specialization public boolean equal(double a, double b) { return a == b; }
@Specialization public boolean equal(BigInteger a, BigInteger b) { return a == b; } // On purpose, Bignum are not #equal?

@Specialization public boolean equal(RubyBasicObject a, RubyBasicObject b) {
assert !(a instanceof Unboxable) && !(b instanceof Unboxable);
return a == b;
}

@Specialization(guards = {"isNotRubyBasicObject(arguments[0])", "isNotRubyBasicObject(arguments[1])", "notSameClass"})
public boolean equal(Object a, Object b) {
assert !(a instanceof Unboxable) && !(b instanceof Unboxable);
return false;
}

@Specialization(guards = "isNotRubyBasicObject(arguments[0])")
public boolean equal(Object a, RubyBasicObject b) {
assert !(b instanceof Unboxable);
return false;
}

@Specialization(guards = "isNotRubyBasicObject(arguments[1])")
public boolean equal(RubyBasicObject a, Object b) {
assert !(a instanceof Unboxable);
return false;
}

@@ -183,30 +170,19 @@ public InstanceEvalNode(InstanceEvalNode prev) {
}

@Specialization
public Object instanceEval(VirtualFrame frame, RubyBasicObject receiver, RubyString string, UndefinedPlaceholder block) {
public Object instanceEval(VirtualFrame frame, Object receiver, RubyString string, UndefinedPlaceholder block) {
notDesignedForCompilation();

return getContext().eval(string.toString(), receiver, this);
}

@Specialization
public Object instanceEval(VirtualFrame frame, RubyBasicObject receiver, UndefinedPlaceholder string, RubyProc block) {
public Object instanceEval(VirtualFrame frame, Object receiver, UndefinedPlaceholder string, RubyProc block) {
notDesignedForCompilation();

if (receiver instanceof RubyFixnum || receiver instanceof RubySymbol) {
throw new RaiseException(getContext().getCoreLibrary().typeError("no class to make alias", this));
}

return yield.dispatchWithModifiedSelf(frame, block, receiver);
}

@Specialization
public Object instanceEval(VirtualFrame frame, Object self, UndefinedPlaceholder string, RubyProc block) {
notDesignedForCompilation();

return instanceEval(frame, getContext().getCoreLibrary().box(self), string, block);
}

}

@CoreMethod(names = "method_missing", needsBlock = true, argumentsAsArray = true, visibility = Visibility.PRIVATE)
10 changes: 5 additions & 5 deletions core/src/main/java/org/jruby/truffle/nodes/core/BignumNodes.java
Original file line number Diff line number Diff line change
@@ -145,7 +145,7 @@ public double mul(BigInteger a, double b) {

@Specialization
public Object mul(BigInteger a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.multiply(a, b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.multiply(a, b));
}

}
@@ -215,7 +215,7 @@ public double div(BigInteger a, double b) {

@Specialization
public Object div(BigInteger a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.divide(a, b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.divide(a, b));
}

}
@@ -233,17 +233,17 @@ public ModNode(ModNode prev) {

@Specialization
public Object mod(BigInteger a, int b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.mod(a, BigInteger.valueOf(b)));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.mod(a, BigInteger.valueOf(b)));
}

@Specialization
public Object mod(BigInteger a, long b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.mod(a, BigInteger.valueOf(b)));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.mod(a, BigInteger.valueOf(b)));
}

@Specialization
public Object mod(BigInteger a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.mod(a, b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.mod(a, b));
}

}
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ public boolean orXor(RubyNilClass other) {
}

@Specialization(guards = "!isNil")
public boolean orXor(RubyObject other) {
public boolean orXor(RubyBasicObject other) {
return true;
}

Original file line number Diff line number Diff line change
@@ -16,8 +16,8 @@
import org.jruby.truffle.nodes.control.PassthroughNode;
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.CoreLibrary;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyFixnum;
import org.jruby.truffle.runtime.core.RubyRange;

public class FixnumLowerNode extends PassthroughNode {
@@ -194,7 +194,7 @@ public UndefinedPlaceholder executeUndefinedPlaceholder(VirtualFrame frame) thro
}

private static boolean canLower(long value) {
return RubyFixnum.fitsIntoInteger(value);
return CoreLibrary.fitsIntoInteger(value);
}

private static int lower(long value) {
16 changes: 8 additions & 8 deletions core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
Original file line number Diff line number Diff line change
@@ -250,7 +250,7 @@ public double mul(int a, double b) {

@Specialization
public Object mul(int a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.multiply(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.multiply(BigInteger.valueOf(a), b));
}

@Specialization(rewriteOn = ArithmeticException.class)
@@ -575,7 +575,7 @@ public Object mod(long a, BigInteger b) {

public Object mod(BigInteger a, BigInteger b) {
notDesignedForCompilation();
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.mod(a, b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.mod(a, b));
}
}

@@ -990,7 +990,7 @@ public long bitAnd(int a, long b) {

@Specialization
public Object bitAnd(int a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.and(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.and(BigInteger.valueOf(a), b));
}

@Specialization
@@ -1005,7 +1005,7 @@ public long bitAnd(long a, long b) {

@Specialization
public Object bitAnd(long a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.and(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.and(BigInteger.valueOf(a), b));
}
}

@@ -1032,7 +1032,7 @@ public long bitOr(int a, long b) {

@Specialization
public Object bitOr(int a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.or(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.or(BigInteger.valueOf(a), b));
}

@Specialization
@@ -1047,7 +1047,7 @@ public long bitOr(long a, long b) {

@Specialization
public Object bitOr(long a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.or(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.or(BigInteger.valueOf(a), b));
}
}

@@ -1074,7 +1074,7 @@ public long bitXOr(int a, long b) {

@Specialization
public Object bitXOr(int a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.xor(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.xor(BigInteger.valueOf(a), b));
}

@Specialization
@@ -1089,7 +1089,7 @@ public long bitXOr(long a, long b) {

@Specialization
public Object bitXOr(long a, BigInteger b) {
return RubyFixnum.fixnumOrBignum(SlowPathBigInteger.xor(BigInteger.valueOf(a), b));
return CoreLibrary.fixnumOrBignum(SlowPathBigInteger.xor(BigInteger.valueOf(a), b));
}
}

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

import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.jruby.truffle.runtime.core.RubyFixnum;
import org.jruby.truffle.runtime.core.CoreLibrary;
import org.jruby.truffle.runtime.util.SlowPathBigInteger;

import java.math.BigDecimal;
@@ -27,7 +27,7 @@ public class FixnumOrBignumNode extends Node {
private final BranchProfile checkLongProfile = new BranchProfile();

public Object fixnumOrBignum(BigInteger value) {
if (value.compareTo(RubyFixnum.MIN_VALUE_BIG) >= 0 && value.compareTo(RubyFixnum.MAX_VALUE_BIG) <= 0) {
if (value.compareTo(CoreLibrary.MIN_VALUE_BIG) >= 0 && value.compareTo(CoreLibrary.MAX_VALUE_BIG) <= 0) {
lowerProfile.enter();

final long longValue = value.longValue();
65 changes: 42 additions & 23 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -51,8 +51,6 @@ public abstract class KernelNodes {
@CoreMethod(names = "===", required = 1)
public abstract static class SameOrEqualNode extends CoreMethodNode {

@Child protected UnboxingNode unboxLeftNode;
@Child protected UnboxingNode unboxRightNode;
@Child protected BasicObjectNodes.ReferenceEqualNode referenceEqualNode;
@Child protected DispatchHeadNode equalNode;

@@ -64,22 +62,6 @@ public SameOrEqualNode(SameOrEqualNode prev) {
super(prev);
}

protected Object unboxLeft(VirtualFrame frame, Object value) {
if (unboxLeftNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
unboxLeftNode = insert(UnboxingNodeFactory.create(getContext(), getSourceSection(), null));
}
return unboxLeftNode.executeUnbox(frame, value);
}

protected Object unboxRight(VirtualFrame frame, Object value) {
if (unboxRightNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
unboxRightNode = insert(UnboxingNodeFactory.create(getContext(), getSourceSection(), null));
}
return unboxRightNode.executeUnbox(frame, value);
}

protected boolean areSame(VirtualFrame frame, Object left, Object right) {
if (referenceEqualNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -100,7 +82,7 @@ protected boolean areEqual(VirtualFrame frame, Object left, Object right) {

@Specialization
public boolean sameOrEqual(VirtualFrame frame, Object a, Object b) {
if (areSame(frame, unboxLeft(frame, a), unboxRight(frame, b)))
if (areSame(frame, a, b))
return true;
return areEqual(frame, a, b);
}
@@ -877,7 +859,7 @@ public InstanceOfNode(InstanceOfNode prev) {
@Specialization
public boolean instanceOf(Object self, RubyClass rubyClass) {
// TODO(CS): fast path
return getContext().getCoreLibrary().box(self).getLogicalClass() == rubyClass;
return getContext().getCoreLibrary().getLogicalClass(self) == rubyClass;
}

}
@@ -1048,6 +1030,8 @@ public IsANode(IsANode prev) {
super(prev);
}

public abstract boolean executeBoolean(Object self, RubyClass rubyClass);

@Specialization
public boolean isA(@SuppressWarnings("unused") RubyBasicObject self, @SuppressWarnings("unused") RubyNilClass nil) {
return false;
@@ -1057,7 +1041,8 @@ public boolean isA(@SuppressWarnings("unused") RubyBasicObject self, @SuppressWa
@Specialization
public boolean isA(Object self, RubyClass rubyClass) {
// TODO(CS): fast path
return ModuleOperations.assignableTo(getContext().getCoreLibrary().box(self).getMetaClass(), rubyClass);
notDesignedForCompilation();
return ModuleOperations.assignableTo(getContext().getCoreLibrary().getMetaClass(self), rubyClass);
}

}
@@ -1619,11 +1604,45 @@ public SingletonClassMethodNode(SingletonClassMethodNode prev) {
super(prev);
}

@Specialization(guards = "isTrue")
public RubyClass singletonClassTrue(boolean self) {
return getContext().getCoreLibrary().getTrueClass();
}

@Specialization(guards = "!isTrue")
public RubyClass singletonClassFalse(boolean self) {
return getContext().getCoreLibrary().getFalseClass();
}

@Specialization
public RubyClass singletonClass(int self) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
public RubyClass singletonClass(long self) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
public RubyClass singletonClass(double self) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
public RubyClass singletonClass(BigInteger self) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
public RubyClass singletonClass(Object self) {
public RubyClass singletonClass(RubyBasicObject self) {
notDesignedForCompilation();

return getContext().getCoreLibrary().box(self).getSingletonClass(this);
return self.getSingletonClass(this);
}

}
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ public RubyArray valuesAt(RubyMatchData matchData, Object[] args) {
final int[] indicies = new int[args.length];

for (int n = 0; n < args.length; n++) {
indicies[n] = RubyFixnum.toInt(args[n]);
indicies[n] = CoreLibrary.toInt(args[n]);
}

return RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), matchData.valuesAt(indicies));
100 changes: 42 additions & 58 deletions core/src/main/java/org/jruby/truffle/nodes/core/MathNodes.java
Original file line number Diff line number Diff line change
@@ -16,15 +16,13 @@
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.dsl.*;
import org.jruby.RubyMath;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.nodes.cast.BoxingNodeFactory;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.UseMethodMissingException;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.util.SlowPathBigInteger;

@CoreClass(name = "Math")
@@ -366,18 +364,18 @@ protected double doFunction(double a) {
@CoreMethod(names = "frexp", isModuleFunction = true, required = 1)
public abstract static class FrExpNode extends CoreMethodNode {

@Child protected BoxingNode box;
@Child protected KernelNodes.IsANode isANode;
@Child protected DispatchHeadNode floatNode;

public FrExpNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
box = BoxingNodeFactory.create(context, sourceSection, null);
isANode = KernelNodesFactory.IsANodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
floatNode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
}

public FrExpNode(FrExpNode prev) {
super(prev);
box = prev.box;
isANode = prev.isANode;
floatNode = prev.floatNode;
}

@@ -423,22 +421,20 @@ public RubyArray frexp(double a) {

@Fallback
public RubyArray frexp(VirtualFrame frame, Object a) {
final RubyBasicObject boxed = box.box(a);

if (boxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass())) {
try {
return frexp(floatNode.callFloat(frame, boxed, "to_f", null));
return frexp(floatNode.callFloat(frame, a, "to_f", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
@@ -524,20 +520,20 @@ protected double doFunction(double a, double b) {
@CoreMethod(names = "ldexp", isModuleFunction = true, required = 2)
public abstract static class LdexpNode extends CoreMethodNode {

@Child protected BoxingNode box;
@Child protected KernelNodes.IsANode isANode;
@Child protected DispatchHeadNode floatANode;
@Child protected DispatchHeadNode integerBNode;

protected LdexpNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
box = BoxingNodeFactory.create(context, sourceSection, null);
isANode = KernelNodesFactory.IsANodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
floatANode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
integerBNode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
}

protected LdexpNode(LdexpNode prev) {
super(prev);
box = prev.box;
isANode = prev.isANode;
floatANode = prev.floatANode;
integerBNode = prev.integerBNode;
}
@@ -609,25 +605,22 @@ public double function(double a, double b) {

@Fallback
public double function(VirtualFrame frame, Object a, Object b) {
final RubyBasicObject aBoxed = box.box(a);
final RubyBasicObject bBoxed = box.box(b);

if (aBoxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass())) {
try {
return function(
floatANode.callFloat(frame, aBoxed, "to_f", null),
integerBNode.callLongFixnum(frame, bBoxed, "to_int", null));
floatANode.callFloat(frame, a, "to_f", null),
integerBNode.callLongFixnum(frame, b, "to_int", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
aBoxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getIntegerClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
aBoxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
@@ -640,18 +633,18 @@ public double function(VirtualFrame frame, Object a, Object b) {
@CoreMethod(names = "lgamma", isModuleFunction = true, required = 1)
public abstract static class LGammaNode extends CoreMethodNode {

@Child protected BoxingNode box;
@Child protected KernelNodes.IsANode isANode;
@Child protected DispatchHeadNode floatNode;

public LGammaNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
box = BoxingNodeFactory.create(context, sourceSection, null);
isANode = KernelNodesFactory.IsANodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
floatNode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
}

public LGammaNode(LGammaNode prev) {
super(prev);
box = prev.box;
isANode = prev.isANode;
floatNode = prev.floatNode;
}

@@ -686,22 +679,20 @@ public RubyArray lgamma(double a) {

@Fallback
public RubyArray lgamma(VirtualFrame frame, Object a) {
final RubyBasicObject boxed = box.box(a);

if (boxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass())) {
try {
return lgamma(floatNode.callFloat(frame, boxed, "to_f", null));
return lgamma(floatNode.callFloat(frame, a, "to_f", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
@@ -742,23 +733,21 @@ public double function(double a, UndefinedPlaceholder b) {

@Specialization
public double function(VirtualFrame frame, Object a, UndefinedPlaceholder b) {
final RubyBasicObject boxed = box.box(a);

if (boxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass())) {
try {
return doFunction(
floatANode.callFloat(frame, boxed, "to_f", null));
floatANode.callFloat(frame, a, "to_f", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
@@ -925,18 +914,18 @@ protected double doFunction(double a) {

protected abstract static class SimpleMonadicMathFunction extends CoreMethodNode {

@Child protected BoxingNode box;
@Child protected KernelNodes.IsANode isANode;
@Child protected DispatchHeadNode floatNode;

protected SimpleMonadicMathFunction(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
box = BoxingNodeFactory.create(context, sourceSection, null);
isANode = KernelNodesFactory.IsANodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
floatNode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
}

protected SimpleMonadicMathFunction(SimpleMonadicMathFunction prev) {
super(prev);
box = prev.box;
isANode = prev.isANode;
floatNode = prev.floatNode;
}

@@ -968,22 +957,20 @@ public double function(double a) {

@Fallback
public double function(VirtualFrame frame, Object a) {
final RubyBasicObject boxed = box.box(a);

if (boxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass())) {
try {
return doFunction(floatNode.callFloat(frame, boxed, "to_f", null));
return doFunction(floatNode.callFloat(frame, a, "to_f", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
boxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
@@ -993,20 +980,20 @@ public double function(VirtualFrame frame, Object a) {

protected abstract static class SimpleDyadicMathFunction extends CoreMethodNode {

@Child protected BoxingNode box;
@Child protected KernelNodes.IsANode isANode;
@Child protected DispatchHeadNode floatANode;
@Child protected DispatchHeadNode floatBNode;

protected SimpleDyadicMathFunction(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
box = BoxingNodeFactory.create(context, sourceSection, null);
isANode = KernelNodesFactory.IsANodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
floatANode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
floatBNode = new DispatchHeadNode(context, Dispatch.MissingBehavior.RETURN_MISSING);
}

protected SimpleDyadicMathFunction(SimpleDyadicMathFunction prev) {
super(prev);
box = prev.box;
isANode = prev.isANode;
floatANode = prev.floatANode;
floatBNode = prev.floatBNode;
}
@@ -1099,25 +1086,22 @@ public double function(double a, double b) {

@Fallback
public double function(VirtualFrame frame, Object a, Object b) {
final RubyBasicObject aBoxed = box.box(a);
final RubyBasicObject bBoxed = box.box(b);

if (aBoxed.isNumeric() && bBoxed.isNumeric()) {
if (isANode.executeBoolean(a, getContext().getCoreLibrary().getNumericClass()) && isANode.executeBoolean(b, getContext().getCoreLibrary().getNumericClass())) {
try {
return doFunction(
floatANode.callFloat(frame, aBoxed, "to_f", null),
floatBNode.callFloat(frame, bBoxed, "to_f", null));
floatANode.callFloat(frame, a, "to_f", null),
floatBNode.callFloat(frame, b, "to_f", null));
} catch (UseMethodMissingException e) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
aBoxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(
aBoxed.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(a).getName(),
getContext().getCoreLibrary().getFloatClass().getName(),
this));
}
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ public boolean containsInstance(RubyModule module, RubyBasicObject instance) {
public boolean containsInstance(RubyModule module, Object instance) {
notDesignedForCompilation();

return ModuleOperations.includesModule(getContext().getCoreLibrary().box(instance).getMetaClass(), module);
return ModuleOperations.includesModule(getContext().getCoreLibrary().getMetaClass(instance), module);
}
}

Original file line number Diff line number Diff line change
@@ -141,7 +141,7 @@ public boolean orXor(RubyNilClass other) {
}

@Specialization(guards = "!isNil")
public boolean orXor(RubyObject other) {
public boolean orXor(RubyBasicObject other) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -277,7 +277,7 @@ public RubyArray bytes(RubyString string) {
final int[] store = new int[bytes.length];

for (int n = 0; n < store.length; n++) {
store[n] = RubyFixnum.toUnsignedInt(bytes[n]);
store[n] = CoreLibrary.toUnsignedInt(bytes[n]);
}

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store, bytes.length);
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ public boolean and(RubyNilClass other) {
}

@Specialization(guards = "!isNil")
public boolean and(RubyObject other) {
public boolean and(RubyBasicObject other) {
return true;
}
}
@@ -83,7 +83,7 @@ public boolean xor(RubyNilClass other) {
}

@Specialization(guards = "!isNil")
public boolean xor(RubyObject other) {
public boolean xor(RubyBasicObject other) {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -95,17 +95,14 @@ public double callFloat(

CompilerDirectives.transferToInterpreter();

final RubyBasicObject receiverBoxed = context.getCoreLibrary().box(receiverObject);
final RubyBasicObject valueBoxed = context.getCoreLibrary().box(value);

final String message = String.format("%s (%s#%s gives %s)",
context.getCoreLibrary().getFloatClass().getName(),
receiverBoxed.getLogicalClass().getName(),
context.getCoreLibrary().getLogicalClass(receiverObject).getName(),
methodName,
valueBoxed.getLogicalClass().getName());
context.getCoreLibrary().getLogicalClass(value).getName());

throw new RaiseException(context.getCoreLibrary().typeErrorCantConvertTo(
receiverBoxed.getLogicalClass().getName(),
context.getCoreLibrary().getLogicalClass(receiverObject).getName(),
message,
this));
}
@@ -132,17 +129,14 @@ public long callLongFixnum(

CompilerDirectives.transferToInterpreter();

final RubyBasicObject receiverBoxed = context.getCoreLibrary().box(receiverObject);
final RubyBasicObject valueBoxed = context.getCoreLibrary().box(value);

final String message = String.format("%s (%s#%s gives %s)",
context.getCoreLibrary().getFloatClass().getName(),
receiverBoxed.getLogicalClass().getName(),
context.getCoreLibrary().getLogicalClass(receiverObject).getName(),
methodName,
valueBoxed.getLogicalClass().getName());
context.getCoreLibrary().getLogicalClass(value).getName());

throw new RaiseException(context.getCoreLibrary().typeErrorCantConvertTo(
receiverBoxed.getLogicalClass().getName(),
context.getCoreLibrary().getLogicalClass(receiverObject).getName(),
message,
this));
}
Original file line number Diff line number Diff line change
@@ -77,11 +77,11 @@ protected RubyConstant lookupConstant(
@CompilerDirectives.SlowPath
protected RubyMethod lookup(
RubyClass callerClass,
RubyBasicObject receiver,
Object receiver,
String name,
boolean ignoreVisibility,
Dispatch.DispatchAction dispatchAction) {
RubyMethod method = ModuleOperations.lookupMethod(receiver.getMetaClass(), name);
RubyMethod method = ModuleOperations.lookupMethod(getContext().getCoreLibrary().getMetaClass(receiver), name);

// If no method was found, use #method_missing

@@ -145,7 +145,7 @@ protected boolean actionIsReadConstant(
VirtualFrame frame,
Object methodReceiverObject,
LexicalScope lexicalScope,
RubyBasicObject receiverObject,
Object receiverObject,
Object methodName,
Object blockObject,
Object argumentsObjects,
@@ -157,7 +157,7 @@ protected boolean actionIsCallOrRespondToMethod(
VirtualFrame frame,
Object methodReceiverObject,
LexicalScope lexicalScope,
RubyBasicObject receiverObject,
Object receiverObject,
Object methodName,
Object blockObject,
Object argumentsObjects,
Original file line number Diff line number Diff line change
@@ -15,8 +15,6 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.nodes.cast.BoxingNodeFactory;
import org.jruby.truffle.nodes.conversion.ToJavaStringNode;
import org.jruby.truffle.nodes.conversion.ToJavaStringNodeFactory;
import org.jruby.truffle.nodes.conversion.ToSymbolNode;
@@ -34,7 +32,6 @@ public abstract class UncachedDispatchNode extends DispatchNode {
private final boolean ignoreVisibility;

@Child protected IndirectCallNode callNode;
@Child protected BoxingNode box;
@Child protected ToSymbolNode toSymbolNode;
@Child protected ToJavaStringNode toJavaStringNode;

@@ -45,7 +42,6 @@ public UncachedDispatchNode(RubyContext context, boolean ignoreVisibility) {
super(context);
this.ignoreVisibility = ignoreVisibility;
callNode = Truffle.getRuntime().createIndirectCallNode();
box = BoxingNodeFactory.create(context, null, null);
toSymbolNode = ToSymbolNodeFactory.create(context, null, null);
toJavaStringNode = ToJavaStringNodeFactory.create(context, null, null);
}
@@ -54,7 +50,6 @@ public UncachedDispatchNode(UncachedDispatchNode prev) {
super(prev);
ignoreVisibility = prev.ignoreVisibility;
callNode = prev.callNode;
box = prev.box;
toSymbolNode = prev.toSymbolNode;
toJavaStringNode = prev.toJavaStringNode;
}
@@ -78,7 +73,7 @@ public Object dispatchReadConstant(

constantMissingProfile.enter();

final RubyClass callerClass = ignoreVisibility ? null : box.box(RubyArguments.getSelf(frame.getArguments())).getMetaClass();
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

final RubyMethod missingMethod = lookup(callerClass, receiverObject, "const_missing", ignoreVisibility,
dispatchAction);
@@ -105,12 +100,12 @@ public Object dispatch(
VirtualFrame frame,
Object methodReceiverObject,
LexicalScope lexicalScope,
RubyBasicObject receiverObject,
Object receiverObject,
Object methodName,
Object blockObject,
Object argumentsObjects,
Dispatch.DispatchAction dispatchAction) {
final RubyClass callerClass = ignoreVisibility ? null : box.box(RubyArguments.getSelf(frame.getArguments())).getMetaClass();
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

final RubyMethod method = lookup(callerClass, receiverObject, toJavaStringNode.executeJavaString(frame, methodName),
ignoreVisibility, dispatchAction);
@@ -173,26 +168,5 @@ public Object dispatch(
}
}

@Specialization
public Object dispatch(
VirtualFrame frame,
Object methodReceiverObject,
LexicalScope lexicalScope,
Object receiverObject,
Object methodName,
Object blockObject,
Object argumentsObjects,
Dispatch.DispatchAction dispatchAction) {
return dispatch(
frame,
methodReceiverObject,
lexicalScope,
box.box(receiverObject),
methodName,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true, true),
dispatchAction);
}


}
Original file line number Diff line number Diff line change
@@ -99,16 +99,15 @@ private Object doUnboxedObject(
Object argumentsObjects,
Dispatch.DispatchAction dispatchAction,
Object methodReceiverObject) {
final RubyBasicObject boxedReceiverObject = getContext().getCoreLibrary().box(receiverObject);
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments())).getMetaClass();
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD || dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
final RubyMethod method = lookup(callerClass, boxedReceiverObject, methodName.toString(), ignoreVisibility,
final RubyMethod method = lookup(callerClass, receiverObject, methodName.toString(), ignoreVisibility,
dispatchAction);

if (method == null) {
final DispatchNode newDispatch = createMethodMissingNode(methodName, boxedReceiverObject, dispatchAction);
return newDispatch.executeDispatch(frame, methodReceiverObject, lexicalScope, boxedReceiverObject,
final DispatchNode newDispatch = createMethodMissingNode(methodName, receiverObject, dispatchAction);
return newDispatch.executeDispatch(frame, methodReceiverObject, lexicalScope, receiverObject,
methodName, blockObject, argumentsObjects, dispatchAction);
}

@@ -117,14 +116,14 @@ private Object doUnboxedObject(
getContext().getCoreLibrary().getFalseClass().getUnmodifiedAssumption();

final RubyMethod falseMethod =
lookup(callerClass, getContext().getCoreLibrary().box(false), methodName.toString(),
lookup(callerClass, false, methodName.toString(),
ignoreVisibility, dispatchAction);

final Assumption trueUnmodifiedAssumption =
getContext().getCoreLibrary().getTrueClass().getUnmodifiedAssumption();

final RubyMethod trueMethod =
lookup(callerClass, getContext().getCoreLibrary().box(true), methodName.toString(),
lookup(callerClass, true, methodName.toString(),
ignoreVisibility, dispatchAction);

if ((falseMethod == null) && (trueMethod == null)) {
@@ -144,7 +143,7 @@ private Object doUnboxedObject(
} else {
final CachedUnboxedDispatchNode newDispatch = CachedUnboxedDispatchNodeFactory.create(getContext(),
methodName, first, receiverObject.getClass(),
boxedReceiverObject.getLogicalClass().getUnmodifiedAssumption(), null, method, indirect, null, null, null, null,
getContext().getCoreLibrary().getLogicalClass(receiverObject).getUnmodifiedAssumption(), null, method, indirect, null, null, null, null,
null, null, null);

first.replace(newDispatch);
@@ -167,16 +166,15 @@ private Object doRubyBasicObject(
Object argumentsObjects,
Dispatch.DispatchAction dispatchAction,
Object methodReceiverObject) {
final RubyBasicObject boxedReceiverObject = getContext().getCoreLibrary().box(receiverObject);
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments())).getMetaClass();
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD || dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
final RubyMethod method = lookup(callerClass, boxedReceiverObject, methodName.toString(), ignoreVisibility,
final RubyMethod method = lookup(callerClass, receiverObject, methodName.toString(), ignoreVisibility,
dispatchAction);

if (method == null) {
final DispatchNode newDispatch = createMethodMissingNode(methodName, boxedReceiverObject, dispatchAction);
return newDispatch.executeDispatch(frame, methodReceiverObject, lexicalScope, boxedReceiverObject,
final DispatchNode newDispatch = createMethodMissingNode(methodName, receiverObject, dispatchAction);
return newDispatch.executeDispatch(frame, methodReceiverObject, lexicalScope, receiverObject,
methodName, blockObject, argumentsObjects, dispatchAction);
}

@@ -187,15 +185,15 @@ private Object doRubyBasicObject(
null, null, null, null, null, null);
} else {
newDispatch = CachedBoxedDispatchNodeFactory.create(getContext(), methodName, first,
boxedReceiverObject.getMetaClass(), null, method, indirect, null, null, null, null, null, null, null);
getContext().getCoreLibrary().getMetaClass(receiverObject), null, method, indirect, null, null, null, null, null, null, null);
}

first.replace(newDispatch);
return newDispatch.executeDispatch(frame, methodReceiverObject, lexicalScope, receiverObject,
methodName, blockObject, argumentsObjects, dispatchAction);

} else if (dispatchAction == Dispatch.DispatchAction.READ_CONSTANT) {
final RubyModule module = (RubyModule) boxedReceiverObject;
final RubyModule module = (RubyModule) receiverObject;
final RubyConstant constant = lookupConstant(lexicalScope, module, methodName.toString(),
ignoreVisibility, dispatchAction);

@@ -257,14 +255,14 @@ private DispatchNode createConstantMissingNode(

private DispatchNode createMethodMissingNode(
Object methodName,
RubyBasicObject receiverObject,
Object receiverObject,
Dispatch.DispatchAction dispatchAction) {
final DispatchNode first = getHeadNode().getFirstDispatchNode();

switch (missingBehavior) {
case RETURN_MISSING: {
return first.replace(CachedBoxedReturnMissingDispatchNodeFactory.create(getContext(), methodName, first,
receiverObject.getMetaClass(), indirect, null, null, null, null, null, null, null));
getContext().getCoreLibrary().getMetaClass(receiverObject), indirect, null, null, null, null, null, null, null));
}

case CALL_METHOD_MISSING: {
@@ -281,7 +279,7 @@ private DispatchNode createMethodMissingNode(
}

return first.replace(CachedBoxedMethodMissingDispatchNodeFactory.create(getContext(), methodName, first,
receiverObject.getMetaClass(), method, Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT.load(), null, null, null, null, null, null, null));
getContext().getCoreLibrary().getMetaClass(receiverObject), method, Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT.load(), null, null, null, null, null, null, null));
}

default: {
72 changes: 54 additions & 18 deletions core/src/main/java/org/jruby/truffle/nodes/methods/AliasNode.java
Original file line number Diff line number Diff line change
@@ -10,45 +10,81 @@
package org.jruby.truffle.nodes.methods;

import com.oracle.truffle.api.*;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;

public class AliasNode extends RubyNode {
import java.math.BigInteger;

@NodeChild(value="module", type=RubyNode.class)
public abstract class AliasNode extends RubyNode {

@Child protected RubyNode module;
final String newName;
final String oldName;

public AliasNode(RubyContext context, SourceSection sourceSection, RubyNode module, String newName, String oldName) {
public AliasNode(RubyContext context, SourceSection sourceSection, String newName, String oldName) {
super(context, sourceSection);
this.module = module;
this.newName = newName;
this.oldName = oldName;
}

@Override
public void executeVoid(VirtualFrame frame) {
notDesignedForCompilation();
public AliasNode(AliasNode prev) {
super(prev);
newName = prev.newName;
oldName = prev.oldName;
}

public Object noClass() {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorNoClassToMakeAlias(this));
}

@Specialization
public Object alias(boolean value) {
return noClass();
}

@Specialization
public Object alias(int value) {
return noClass();
}

final Object object = module.execute(frame);
@Specialization
public Object alias(long value) {
return noClass();
}

@Specialization
public Object alias(double value) {
return noClass();
}

if (object instanceof RubyModule) {
// Module definition or class_eval
((RubyModule) object).alias(this, newName, oldName);
} else {
// instance_eval?
((RubyBasicObject) object).getSingletonClass(this).alias(this, newName, oldName);
}
@Specialization
public Object alias(BigInteger value) {
return noClass();
}

@Override
public Object execute(VirtualFrame frame) {
executeVoid(frame);
return getContext().getCoreLibrary().getNilObject();
@Specialization
public Object alias(RubyModule module) {
notDesignedForCompilation();

module.alias(this, newName, oldName);
return null;
}

@Specialization(guards = "!isModule")
public Object alias(RubyBasicObject object) {
notDesignedForCompilation();

object.getSingletonClass(this).alias(this, newName, oldName);
return null;
}

}
Original file line number Diff line number Diff line change
@@ -127,7 +127,7 @@ public RubyBasicObject translate(Throwable throwable) {
DebugOperations.panic(getContext(), this, throwable.toString());
}

return getContext().getCoreLibrary().internalError(throwable.getClass().getSimpleName(), this);
return getContext().getCoreLibrary().internalError(String.format("%s %s", throwable.getClass().getSimpleName(), throwable.getMessage()), this);
}

}
58 changes: 43 additions & 15 deletions core/src/main/java/org/jruby/truffle/nodes/objects/ClassNode.java
Original file line number Diff line number Diff line change
@@ -9,35 +9,63 @@
*/
package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.*;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;

import java.math.BigInteger;

/**
* Reads the class of an object.
*/
public class ClassNode extends RubyNode {

@Child protected BoxingNode child;
@NodeChild(value="object", type=RubyNode.class)
public abstract class ClassNode extends RubyNode {

public ClassNode(RubyContext context, SourceSection sourceSection, BoxingNode child) {
public ClassNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.child = child;
}

@Override
public RubyClass executeRubyClass(VirtualFrame frame) {
return child.executeRubyBasicObject(frame).getLogicalClass();
public ClassNode(ClassNode prev) {
super(prev);
}

@Specialization(guards = "isTrue")
protected RubyClass getClassTrue(boolean value) {
return getContext().getCoreLibrary().getTrueClass();
}

@Specialization(guards = "!isTrue")
protected RubyClass getClassFalse(boolean value) {
return getContext().getCoreLibrary().getFalseClass();
}

@Specialization
protected RubyClass getClass(int value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
protected RubyClass getClass(long value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
protected RubyClass getClass(double value) {
return getContext().getCoreLibrary().getFloatClass();
}

@Specialization
protected RubyClass getClass(BigInteger value) {
return getContext().getCoreLibrary().getBignumClass();
}

@Override
public Object execute(VirtualFrame frame) {
return executeRubyClass(frame);
@Specialization
protected RubyClass getClass(RubyBasicObject object) {
return object.getLogicalClass();
}

}
Original file line number Diff line number Diff line change
@@ -15,12 +15,8 @@
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.nodes.cast.BoxingNodeFactory;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.RespecializeHook;
import org.jruby.truffle.nodes.objectstorage.UninitializedReadObjectFieldNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.objectstorage.*;
@@ -51,52 +47,87 @@ public void hookWrite(ObjectStorage object, String name, Object value) {

};

@Child protected BoxingNode receiver;
@Child protected RubyNode receiver;
@Child protected ReadHeadObjectFieldNode readNode;
private final boolean isGlobal;

private final BranchProfile nullProfile = new BranchProfile();
private final BranchProfile primitiveProfile = new BranchProfile();

public ReadInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, boolean isGlobal) {
super(context, sourceSection);
this.receiver = BoxingNodeFactory.create(context, sourceSection, receiver);
this.receiver = receiver;
readNode = new ReadHeadObjectFieldNode(name, hook);
this.isGlobal = isGlobal;
}

@Override
public int executeIntegerFixnum(VirtualFrame frame) throws UnexpectedResultException {
return readNode.executeInteger(receiver.executeRubyBasicObject(frame));
final Object receiverObject = receiver.execute(frame);

if (receiverObject instanceof RubyBasicObject) {
return readNode.executeInteger((RubyBasicObject) receiverObject);
} else {
// TODO(CS): need to put this onto the fast path?

CompilerDirectives.transferToInterpreter();
throw new UnexpectedResultException(getContext().getCoreLibrary().getNilObject());
}
}

@Override
public long executeLongFixnum(VirtualFrame frame) throws UnexpectedResultException {
return readNode.executeLong(receiver.executeRubyBasicObject(frame));
final Object receiverObject = receiver.execute(frame);

if (receiverObject instanceof RubyBasicObject) {
return readNode.executeLong((RubyBasicObject) receiverObject);
} else {
// TODO(CS): need to put this onto the fast path?

CompilerDirectives.transferToInterpreter();
throw new UnexpectedResultException(getContext().getCoreLibrary().getNilObject());
}
}

@Override
public double executeFloat(VirtualFrame frame) throws UnexpectedResultException {
return readNode.executeDouble(receiver.executeRubyBasicObject(frame));
final Object receiverObject = receiver.execute(frame);

if (receiverObject instanceof RubyBasicObject) {
return readNode.executeDouble((RubyBasicObject) receiverObject);
} else {
// TODO(CS): need to put this onto the fast path?

CompilerDirectives.transferToInterpreter();
throw new UnexpectedResultException(getContext().getCoreLibrary().getNilObject());
}
}

@Override
public Object execute(VirtualFrame frame) {
Object value = readNode.execute(receiver.executeRubyBasicObject(frame));
final Object receiverObject = receiver.execute(frame);

if (value == null) {
nullProfile.enter();
value = getContext().getCoreLibrary().getNilObject();
}
if (receiverObject instanceof RubyBasicObject) {
Object value = readNode.execute((RubyBasicObject) receiverObject);

if (value == null) {
nullProfile.enter();
value = getContext().getCoreLibrary().getNilObject();
}

return value;
return value;
} else {
primitiveProfile.enter();
return getContext().getCoreLibrary().getNilObject();
}
}

@Override
public Object isDefined(VirtualFrame frame) {
notDesignedForCompilation();

if (isGlobal) {
if (readNode.getName().equals("$~") || readNode.isSet(receiver.executeRubyBasicObject(frame))) {
if (readNode.getName().equals("$~") || readNode.isSet((RubyBasicObject) receiver.execute(frame))) {
return getContext().makeString("global-variable");
} else{
return getContext().getCoreLibrary().getNilObject();
@@ -107,15 +138,20 @@ public Object isDefined(VirtualFrame frame) {

try {
final Object receiverObject = receiver.execute(frame);
final RubyBasicObject receiverRubyObject = context.getCoreLibrary().box(receiverObject);

final ObjectLayout layout = receiverRubyObject.getObjectLayout();
final StorageLocation storageLocation = layout.findStorageLocation(readNode.getName());
if (receiverObject instanceof RubyBasicObject) {
final RubyBasicObject receiverRubyObject = (RubyBasicObject) receiverObject;

if (storageLocation.isSet(receiverRubyObject)) {
return context.makeString("instance-variable");
final ObjectLayout layout = receiverRubyObject.getObjectLayout();
final StorageLocation storageLocation = layout.findStorageLocation(readNode.getName());

if (storageLocation.isSet(receiverRubyObject)) {
return context.makeString("instance-variable");
} else {
return getContext().getCoreLibrary().getNilObject();
}
} else {
return getContext().getCoreLibrary().getNilObject();
return false;
}
} catch (Exception e) {
return getContext().getCoreLibrary().getNilObject();
Original file line number Diff line number Diff line change
@@ -10,36 +10,68 @@
package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.*;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;

import java.math.BigInteger;

/**
* Reads the singleton (meta, eigen) class of an object.
*/
public class SingletonClassNode extends RubyNode {

@Child protected BoxingNode child;
@NodeChild(value="object", type=RubyNode.class)
public abstract class SingletonClassNode extends RubyNode {

public SingletonClassNode(RubyContext context, SourceSection sourceSection, BoxingNode child) {
public SingletonClassNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.child = child;
}

@Override
public RubyClass executeRubyClass(VirtualFrame frame) {
notDesignedForCompilation();
public SingletonClassNode(SingletonClassNode prev) {
super(prev);
}

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

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

@Specialization
protected Object singletonClass(int value) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
protected Object singletonClass(long value) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
protected Object singletonClass(double value) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

return child.executeRubyBasicObject(frame).getSingletonClass(this);
@Specialization
protected Object singletonClass(BigInteger value) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Override
public Object execute(VirtualFrame frame) {
return executeRubyClass(frame);
@Specialization
protected RubyClass singletonClass(RubyBasicObject object) {
return object.getSingletonClass(this);
}

}
Original file line number Diff line number Diff line change
@@ -14,8 +14,6 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.nodes.cast.BoxingNode;
import org.jruby.truffle.nodes.cast.BoxingNodeFactory;
import org.jruby.truffle.nodes.objectstorage.*;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -49,69 +47,91 @@ public void hookWrite(ObjectStorage object, String name, Object value) {

};

@Child protected BoxingNode receiver;
@Child protected RubyNode receiver;
@Child protected RubyNode rhs;
@Child protected WriteHeadObjectFieldNode writeNode;
private final boolean isGlobal;

public WriteInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs, boolean isGlobal) {
super(context, sourceSection);
this.receiver = BoxingNodeFactory.create(context, sourceSection, receiver);
this.receiver = receiver;
this.rhs = rhs;
writeNode = new WriteHeadObjectFieldNode(name, hook);
this.isGlobal = isGlobal;
}

@Override
public int executeIntegerFixnum(VirtualFrame frame) throws UnexpectedResultException {
final RubyBasicObject object = receiver.executeRubyBasicObject(frame);
final Object object = receiver.execute(frame);

try {
final int value = rhs.executeIntegerFixnum(frame);
if (object instanceof RubyBasicObject) {
try {
final int value = rhs.executeIntegerFixnum(frame);

writeNode.execute(object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute(object, e.getResult());
throw e;
writeNode.execute((RubyBasicObject) object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute((RubyBasicObject) object, e.getResult());
throw e;
}
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
}
}

@Override
public long executeLongFixnum(VirtualFrame frame) throws UnexpectedResultException {
final RubyBasicObject object = receiver.executeRubyBasicObject(frame);
final Object object = receiver.execute(frame);

try {
final long value = rhs.executeLongFixnum(frame);
if (object instanceof RubyBasicObject) {
try {
final long value = rhs.executeLongFixnum(frame);

writeNode.execute(object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute(object, e.getResult());
throw e;
writeNode.execute((RubyBasicObject) object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute((RubyBasicObject) object, e.getResult());
throw e;
}
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
}
}

@Override
public double executeFloat(VirtualFrame frame) throws UnexpectedResultException {
final RubyBasicObject object = receiver.executeRubyBasicObject(frame);
final Object object = receiver.execute(frame);

try {
final double value = rhs.executeFloat(frame);
if (object instanceof RubyBasicObject) {
try {
final double value = rhs.executeFloat(frame);

writeNode.execute(object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute(object, e.getResult());
throw e;
writeNode.execute((RubyBasicObject) object, value);
return value;
} catch (UnexpectedResultException e) {
writeNode.execute((RubyBasicObject) object, e.getResult());
throw e;
}
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
}
}

@Override
public Object execute(VirtualFrame frame) {
final RubyBasicObject object = receiver.executeRubyBasicObject(frame);
final Object object = receiver.execute(frame);
final Object value = rhs.execute(frame);
writeNode.execute(object, value);

if (object instanceof RubyBasicObject) {
writeNode.execute((RubyBasicObject) object, value);
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
}

return value;
}

Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ protected void lookup(VirtualFrame frame) {

// TODO: this is wrong, we need the lexically enclosing method (or define_method)'s module
final RubyModule declaringModule = RubyCallStack.getCurrentMethod().getDeclaringModule();
final RubyClass selfMetaClass = getContext().getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments())).getMetaClass();
final RubyClass selfMetaClass = getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

method = ModuleOperations.lookupSuperMethod(declaringModule, name, selfMetaClass);

@@ -74,13 +74,13 @@ public Object isDefined(VirtualFrame frame) {
final RubyContext context = getContext();

try {
final RubyBasicObject self = context.getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments()));
final Object self = RubyArguments.getSelf(frame.getArguments());

if (!guard()) {
lookup(frame);
}

if (method == null || method.isUndefined() || !method.isVisibleTo(this, self.getMetaClass())) {
if (method == null || method.isUndefined() || !method.isVisibleTo(this, context.getCoreLibrary().getMetaClass(self))) {
return getContext().getCoreLibrary().getNilObject();
} else {
return context.makeString("super");
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.nodes.RootNode;
import org.jruby.RubyClass;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.*;
import org.jruby.truffle.runtime.backtrace.Backtrace;
@@ -46,16 +47,14 @@ public static String inspect(RubyContext context, Object object) {
public static Object send(RubyContext context, Object object, String methodName, RubyProc block, Object... arguments) {
CompilerAsserts.neverPartOfCompilation();

final RubyBasicObject rubyObject = context.getCoreLibrary().box(object);

final RubyMethod method = ModuleOperations.lookupMethod(rubyObject.getMetaClass(), methodName);
final RubyMethod method = ModuleOperations.lookupMethod(context.getCoreLibrary().getMetaClass(object), methodName);

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

return method.getCallTarget().call(
RubyArguments.pack(method, method.getDeclarationFrame(), rubyObject, block, arguments));
RubyArguments.pack(method, method.getDeclarationFrame(), object, block, arguments));
}

public static void panic(RubyContext context, Node currentNode, String message) {
233 changes: 185 additions & 48 deletions core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -38,6 +38,12 @@

public class CoreLibrary {

public static final long FIXNUM_MIN_VALUE = Long.MIN_VALUE;
public static final long FIXNUM_MAX_VALUE = Long.MAX_VALUE;

public static final BigInteger MIN_VALUE_BIG = BigInteger.valueOf(FIXNUM_MIN_VALUE);
public static final BigInteger MAX_VALUE_BIG = BigInteger.valueOf(FIXNUM_MAX_VALUE);

private final RubyContext context;

@CompilerDirectives.CompilationFinal private RubyClass argumentErrorClass;
@@ -102,9 +108,7 @@ public class CoreLibrary {
@CompilerDirectives.CompilationFinal private RubyArray argv;
@CompilerDirectives.CompilationFinal private RubyBasicObject globalVariablesObject;
@CompilerDirectives.CompilationFinal private RubyBasicObject mainObject;
@CompilerDirectives.CompilationFinal private RubyFalseClass falseObject;
@CompilerDirectives.CompilationFinal private RubyNilClass nilObject;
@CompilerDirectives.CompilationFinal private RubyTrueClass trueObject;
@CompilerDirectives.CompilationFinal private RubyHash envHash;

private ArrayNodes.MinBlock arrayMinBlock;
@@ -116,6 +120,39 @@ public CoreLibrary(RubyContext context) {
this.context = context;
}

/**
* Convert a value to a {@code Float}, without doing any lookup.
*/
public static double toDouble(Object value) {
RubyNode.notDesignedForCompilation();

assert value != null;

if (value instanceof RubyNilClass || value instanceof RubyNilClass) {
return 0;
}

if (value instanceof Integer) {
return (int) value;
}

if (value instanceof BigInteger) {
return ((BigInteger) value).doubleValue();
}

if (value instanceof Double) {
return (double) value;
}

CompilerDirectives.transferToInterpreter();

throw new UnsupportedOperationException();
}

public static boolean fitsIntoInteger(long value) {
return value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE;
}

public void initialize() {
// Create the cyclic classes and modules

@@ -236,8 +273,6 @@ public void initialize() {

mainObject = new RubyObject(objectClass);
nilObject = new RubyNilClass(nilClass);
trueObject = new RubyTrueClass(trueClass);
falseObject = new RubyFalseClass(falseClass);

// Create the globals object

@@ -333,60 +368,63 @@ public void initializeEncodingConstants() {

}

public RubyBasicObject box(Object object) {
public RubyClass getMetaClass(Object object) {
RubyNode.notDesignedForCompilation();

// TODO(cs): pool common object instances like small Fixnums?

if (object instanceof RubyBasicObject) {
return (RubyBasicObject) object;
}

if (object instanceof Boolean) {
return ((RubyBasicObject) object).getMetaClass();
} else if (object instanceof Boolean) {
if ((boolean) object) {
return trueObject;
return trueClass;
} else {
return falseObject;
return falseClass;
}
} else if (object instanceof Integer) {
return fixnumClass;
} else if (object instanceof Long) {
return fixnumClass;
} else if (object instanceof BigInteger) {
return bignumClass;
} else if (object instanceof Double) {
return floatClass;
} else {
throw new UnsupportedOperationException(String.format("Don't know how to get the metaclass for %s", object.getClass()));
}
}

if (object instanceof Integer) {
return new RubyFixnum.IntegerFixnum(fixnumClass, (int) object);
}

if (object instanceof Long) {
return new RubyFixnum.LongFixnum(fixnumClass, (long) object);
}

if (object instanceof BigInteger) {
return new RubyBignum(bignumClass, (BigInteger) object);
}

if (object instanceof Double) {
return new RubyFloat(floatClass, (double) object);
}

if (object instanceof RubyNilClass) {
return nilObject;
}
public RubyClass getLogicalClass(Object object) {
RubyNode.notDesignedForCompilation();

if (object instanceof String) {
return context.makeString((String) object);
if (object instanceof RubyBasicObject) {
return ((RubyBasicObject) object).getLogicalClass();
} else if (object instanceof Boolean) {
if ((boolean) object) {
return trueClass;
} else {
return falseClass;
}
} else if (object instanceof Integer) {
return fixnumClass;
} else if (object instanceof Long) {
return fixnumClass;
} else if (object instanceof BigInteger) {
return bignumClass;
} else if (object instanceof Double) {
return floatClass;
} else {
throw new UnsupportedOperationException(String.format("Don't know how to get the logical class for %s", object.getClass()));
}

CompilerDirectives.transferToInterpreter();

throw new UnsupportedOperationException("Don't know how to box " + object.getClass().getName());
}

/**
* Convert a value to a boolean according to Ruby rules. Never fails.
*/
public boolean isTruthy(Object value) {
// TODO(CS): mark are neverPartOfCompilation
if (value instanceof Boolean) {
return (boolean) value;
} else {
return value != nilObject && value != falseObject;
return value != nilObject;
}
}

@@ -440,6 +478,11 @@ public RubyException typeErrorCantDefineSingleton(Node currentNode) {
return typeError("can't define singleton", currentNode);
}

public RubyException typeErrorNoClassToMakeAlias(Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeError("no class to make alias", currentNode);
}

public RubyException typeErrorShouldReturn(String object, String method, String expectedType, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeError(String.format("%s#%s should return %s", object, method, expectedType), currentNode);
@@ -457,7 +500,7 @@ public RubyException typeErrorCantConvertInto(String from, String to, Node curre

public RubyException typeErrorCantConvertInto(Object from, RubyClass to, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeErrorCantConvertInto(box(from).getLogicalClass().getName(), to.getName(), currentNode);
return typeErrorCantConvertInto(getLogicalClass(from).getName(), to.getName(), currentNode);
}

public RubyException typeErrorIsNotA(String value, String expectedType, Node currentNode) {
@@ -692,14 +735,6 @@ public RubyBasicObject getMainObject() {
return mainObject;
}

public RubyTrueClass getTrueObject() {
return trueObject;
}

public RubyFalseClass getFalseObject() {
return falseObject;
}

public RubyNilClass getNilObject() {
return nilObject;
}
@@ -747,4 +782,106 @@ public RubyClass getArgumentErrorClass() {
public RubyClass getEncodingConverterClass() {
return encodingConverterClass;
}

public static int toInt(Object value) {
RubyNode.notDesignedForCompilation();

assert value != null;

if (value instanceof RubyNilClass || value instanceof RubyNilClass) {
return 0;
}

if (value instanceof Integer) {
return (int) value;
}

if (value instanceof Long && fitsIntoInteger((long) value)) {
return (int) (long) value;
}

if (value instanceof BigInteger) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
}

if (value instanceof Double) {
return (int) (double) value;
}

CompilerDirectives.transferToInterpreter();

throw new UnsupportedOperationException(value.getClass().toString());
}

public static long toLong(Object value) {
RubyNode.notDesignedForCompilation();

// TODO(CS): stop using this in compilation - use a specialising node instead

assert value != null;

if (value instanceof RubyNilClass || value instanceof RubyNilClass) {
return 0;
}

if (value instanceof Integer) {
return (int) value;
}

if (value instanceof Long) {
return (long) value;
}

if (value instanceof BigInteger) {
throw new UnsupportedOperationException();
}

if (value instanceof Double) {
return (long) (double) value;
}

CompilerDirectives.transferToInterpreter();

throw new UnsupportedOperationException(value.getClass().toString());
}

public static Object fixnumOrBignum(double value) {
RubyNode.notDesignedForCompilation();

if (value >= FIXNUM_MIN_VALUE && value <= FIXNUM_MAX_VALUE) {
final long longValue = (long) value;

if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {
return (int) longValue;
} else {
return value;
}
} else {
return value;
}
}

public static Object fixnumOrBignum(BigInteger value) {
RubyNode.notDesignedForCompilation();

assert value != null;

if (value.compareTo(MIN_VALUE_BIG) >= 0 && value.compareTo(MAX_VALUE_BIG) <= 0) {
final long longValue = value.longValue();

if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {
return (int) longValue;
} else {
return value;
}
} else {
return value;
}
}

public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}

}
26 changes: 7 additions & 19 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyArray.java
Original file line number Diff line number Diff line change
@@ -81,16 +81,10 @@ public static RubyArray fromObject(RubyClass arrayClass, Object object) {

if (object instanceof Integer) {
store = new int[]{(int) object};
} else if (object instanceof RubyFixnum.IntegerFixnum) {
store = new int[]{((RubyFixnum.IntegerFixnum) object).getValue()};
} else if (object instanceof Long) {
store = new long[]{(long) object};
} else if (object instanceof RubyFixnum.LongFixnum) {
store = new long[]{((RubyFixnum.LongFixnum) object).getValue()};
} else if (object instanceof Double) {
store = new double[]{(double) object};
} else if (object instanceof RubyFloat) {
store = new double[]{((RubyFloat) object).getValue()};
} else {
store = new Object[]{object};
}
@@ -116,20 +110,12 @@ public static RubyArray fromObjects(RubyClass arrayClass, Object... objects) {
for (Object object : objects) {
if (object instanceof Integer) {
canUseDouble = false;
} else if (object instanceof RubyFixnum.IntegerFixnum) {
canUseDouble = false;
} else if (object instanceof Long) {
canUseInteger = canUseInteger && RubyFixnum.fitsIntoInteger((long) object);
canUseDouble = false;
} else if (object instanceof RubyFixnum.LongFixnum) {
canUseInteger = canUseInteger && RubyFixnum.fitsIntoInteger(((RubyFixnum.LongFixnum) object).getValue());
canUseInteger = canUseInteger && CoreLibrary.fitsIntoInteger((long) object);
canUseDouble = false;
} else if (object instanceof Double) {
canUseInteger = false;
canUseLong = false;
} else if (object instanceof RubyFloat) {
canUseInteger = false;
canUseLong = false;
} else {
canUseInteger = false;
canUseLong = false;
@@ -141,23 +127,23 @@ public static RubyArray fromObjects(RubyClass arrayClass, Object... objects) {
final int[] store = new int[objects.length];

for (int n = 0; n < objects.length; n++) {
store[n] = RubyFixnum.toInt(objects[n]);
store[n] = CoreLibrary.toInt(objects[n]);
}

return new RubyArray(arrayClass, store, objects.length);
} else if (canUseLong) {
final long[] store = new long[objects.length];

for (int n = 0; n < objects.length; n++) {
store[n] = RubyFixnum.toLong(objects[n]);
store[n] = CoreLibrary.toLong(objects[n]);
}

return new RubyArray(arrayClass, store, objects.length);
} else if (canUseDouble) {
final double[] store = new double[objects.length];

for (int n = 0; n < objects.length; n++) {
store[n] = RubyFloat.toDouble(objects[n]);
store[n] = CoreLibrary.toDouble(objects[n]);
}

return new RubyArray(arrayClass, store, objects.length);
@@ -277,7 +263,9 @@ public ArrayAllocationSite getAllocationSite() {
@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
for (Object object : slowToArray()) {
getContext().getCoreLibrary().box(object).visitObjectGraph(visitor);
if (object instanceof RubyBasicObject) {
((RubyBasicObject) object).visitObjectGraph(visitor);
}
}
}

Original file line number Diff line number Diff line change
@@ -185,7 +185,9 @@ public void visitObjectGraph(ObjectSpaceManager.ObjectGraphVisitor visitor) {
metaClass.visitObjectGraph(visitor);

for (Object instanceVariable : getFields().values()) {
getContext().getCoreLibrary().box(instanceVariable).visitObjectGraph(visitor);
if (instanceVariable instanceof RubyBasicObject) {
((RubyBasicObject) instanceVariable).visitObjectGraph(visitor);
}
}

visitObjectGraphChildren(visitor);
73 changes: 0 additions & 73 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyBignum.java

This file was deleted.

This file was deleted.

261 changes: 0 additions & 261 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyFixnum.java

This file was deleted.

104 changes: 0 additions & 104 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyFloat.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -119,8 +119,13 @@ public Map<Object, Object> slowToMap() {
@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
for (Map.Entry<Object, Object> entry : slowToMap().entrySet()) {
getContext().getCoreLibrary().box(entry.getKey()).visitObjectGraph(visitor);
getContext().getCoreLibrary().box(entry.getValue()).visitObjectGraph(visitor);
if (entry.getKey() instanceof RubyBasicObject) {
((RubyBasicObject) entry.getKey()).visitObjectGraph(visitor);
}

if (entry.getValue() instanceof RubyBasicObject) {
((RubyBasicObject) entry.getValue()).visitObjectGraph(visitor);
}
}
}

Original file line number Diff line number Diff line change
@@ -43,7 +43,9 @@ public Object[] getValues() {
@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
for (Object object : values) {
getContext().getCoreLibrary().box(object).visitObjectGraph(visitor);
if (object instanceof RubyBasicObject) {
((RubyBasicObject) object).visitObjectGraph(visitor);
}
}
}

Original file line number Diff line number Diff line change
@@ -445,7 +445,9 @@ public Map<String, Object> getClassVariables() {
@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
for (RubyConstant constant : constants.values()) {
getContext().getCoreLibrary().box(constant.getValue()).visitObjectGraph(visitor);
if (constant.getValue() instanceof RubyBasicObject) {
((RubyBasicObject) constant.getValue()).visitObjectGraph(visitor);
}
}

for (RubyMethod method : methods.values()) {
15 changes: 7 additions & 8 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyRange.java
Original file line number Diff line number Diff line change
@@ -80,12 +80,6 @@ public final long getExclusiveEnd() {
}
}

@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
getContext().getCoreLibrary().box(begin).visitObjectGraph(visitor);
getContext().getCoreLibrary().box(end).visitObjectGraph(visitor);
}

}

public static class ObjectRange extends RubyRange {
@@ -109,8 +103,13 @@ public Object getEnd() {

@Override
public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visitor) {
getContext().getCoreLibrary().box(begin).visitObjectGraph(visitor);
getContext().getCoreLibrary().box(end).visitObjectGraph(visitor);
if (begin instanceof RubyBasicObject) {
((RubyBasicObject) begin).visitObjectGraph(visitor);
}

if (end instanceof RubyBasicObject) {
((RubyBasicObject) end).visitObjectGraph(visitor);
}
}

}
Original file line number Diff line number Diff line change
@@ -114,7 +114,7 @@ public Object toInteger() {
try {
final int value = Integer.parseInt(toString());

if (value >= RubyFixnum.MIN_VALUE && value <= RubyFixnum.MAX_VALUE) {
if (value >= CoreLibrary.FIXNUM_MIN_VALUE && value <= CoreLibrary.FIXNUM_MAX_VALUE) {
return value;
} else {
return BigInteger.valueOf(value);

This file was deleted.

Original file line number Diff line number Diff line change
@@ -117,7 +117,7 @@ public static void format(PrintStream stream, String format, List<Object> values

case 'd': {
formatBuilder.append("d");
final long value = RubyFixnum.toLong(values.get(v));
final long value = CoreLibrary.toLong(values.get(v));
stream.printf(formatBuilder.toString(), value);
break;
}
@@ -126,7 +126,7 @@ public static void format(PrintStream stream, String format, List<Object> values
formatBuilder.append(".");
formatBuilder.append(precision);
formatBuilder.append("f");
final double value = RubyFloat.toDouble(values.get(v));
final double value = CoreLibrary.toDouble(values.get(v));
stream.printf(formatBuilder.toString(), value);
break;
}
19 changes: 0 additions & 19 deletions core/src/main/java/org/jruby/truffle/runtime/core/Unboxable.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -257,7 +257,9 @@ public void visitFrame(Frame frame, ObjectGraphVisitor visitor) {
for (FrameSlot slot : frame.getFrameDescriptor().getSlots()) {
Object value = frame.getValue(slot);
if (!(value instanceof Visibility)) { // TODO(cs): Better condition for hidden local variables
context.getCoreLibrary().box(value).visitObjectGraph(visitor);
if (value instanceof RubyBasicObject) {
((RubyBasicObject) value).visitObjectGraph(visitor);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ public RubyNode visitAliasNode(org.jruby.ast.AliasNode node) {
final org.jruby.ast.LiteralNode oldName = (org.jruby.ast.LiteralNode) node.getOldName();
final org.jruby.ast.LiteralNode newName = (org.jruby.ast.LiteralNode) node.getNewName();

return new AliasNode(context, sourceSection, new SelfNode(context, sourceSection), newName.getName(), oldName.getName());
return AliasNodeFactory.create(context, sourceSection, newName.getName(), oldName.getName(), new SelfNode(context, sourceSection));
}

@Override
@@ -605,9 +605,9 @@ public RubyNode visitClassVarAsgnNode(org.jruby.ast.ClassVarAsgnNode node) {
final SourceSection sourceSection = translate(node.getPosition());
final RubyNode receiver;
if (useClassVariablesAsIfInClass) {
receiver = BoxingNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection));
receiver = new SelfNode(context, sourceSection);
} else {
receiver = new ClassNode(context, sourceSection, BoxingNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection)));
receiver = ClassNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection));
}
final RubyNode rhs = node.getValueNode().accept(this);
return new WriteClassVariableNode(context, sourceSection, node.getName(), receiver, rhs);
@@ -618,9 +618,9 @@ public RubyNode visitClassVarNode(org.jruby.ast.ClassVarNode node) {
final SourceSection sourceSection = translate(node.getPosition());
final RubyNode receiver;
if (useClassVariablesAsIfInClass) {
receiver = BoxingNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection));
receiver = new SelfNode(context, sourceSection);
} else {
receiver = new ClassNode(context, sourceSection, BoxingNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection)));
receiver = ClassNodeFactory.create(context, sourceSection, new SelfNode(context, sourceSection));
}
return new ReadClassVariableNode(context, sourceSection, node.getName(), receiver);
}
@@ -791,7 +791,7 @@ public RubyNode visitDefsNode(org.jruby.ast.DefsNode node) {

final RubyNode objectNode = node.getReceiverNode().accept(this);

final SingletonClassNode singletonClassNode = new SingletonClassNode(context, sourceSection, BoxingNodeFactory.create(context, sourceSection, objectNode));
final SingletonClassNode singletonClassNode = SingletonClassNodeFactory.create(context, sourceSection, objectNode);

return translateMethodDefinition(sourceSection, singletonClassNode, node.getName(), node, node.getArgsNode(), node.getBodyNode(), true);
}
@@ -869,7 +869,7 @@ public RubyNode visitFalseNode(org.jruby.ast.FalseNode node) {
public RubyNode visitFixnumNode(org.jruby.ast.FixnumNode node) {
final long value = node.getValue();

if (RubyFixnum.fitsIntoInteger(value)) {
if (CoreLibrary.fitsIntoInteger(value)) {
return new FixnumLiteralNode.IntegerFixnumLiteralNode(context, translate(node.getPosition()), (int) value);
} else {
return new FixnumLiteralNode.LongFixnumLiteralNode(context, translate(node.getPosition()), value);
@@ -1964,7 +1964,7 @@ public RubyNode visitSClassNode(org.jruby.ast.SClassNode node) {

final RubyNode receiverNode = node.getReceiverNode().accept(this);

final SingletonClassNode singletonClassNode = new SingletonClassNode(context, sourceSection, BoxingNodeFactory.create(context, sourceSection, receiverNode));
final SingletonClassNode singletonClassNode = SingletonClassNodeFactory.create(context, sourceSection, receiverNode);

return openModule(sourceSection, singletonClassNode, "(singleton-def)", node.getBodyNode());
}
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ public RubyNode visitAliasNode(org.jruby.ast.AliasNode node) {
final org.jruby.ast.LiteralNode oldName = (org.jruby.ast.LiteralNode) node.getOldName();
final org.jruby.ast.LiteralNode newName = (org.jruby.ast.LiteralNode) node.getNewName();

return new AliasNode(context, sourceSection, new SelfNode(context, sourceSection), newName.getName(), oldName.getName());
return AliasNodeFactory.create(context, sourceSection, newName.getName(), oldName.getName(), new SelfNode(context, sourceSection));
}

}

0 comments on commit a90e5d0

Please sign in to comment.