Skip to content

Commit

Permalink
Showing 29 changed files with 490 additions and 454 deletions.
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/file/stat/comparison_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/file/utime_tags.txt

This file was deleted.

56 changes: 40 additions & 16 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyGuards.java
Original file line number Diff line number Diff line change
@@ -12,16 +12,17 @@
import com.oracle.truffle.api.interop.TruffleObject;
import org.jruby.truffle.nodes.core.BigDecimalNodes;
import org.jruby.truffle.nodes.core.MethodNodes;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.core.UnboundMethodNodes;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.core.hash.HashNodes;
import org.jruby.truffle.runtime.ThreadLocalObject;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.core.*;

public abstract class RubyGuards {

public static boolean isNotProvided(Object value) {
return value instanceof NotProvided;
}
// Basic Java types

public static boolean isBoolean(Object value) {
return value instanceof Boolean;
@@ -39,18 +40,31 @@ public static boolean isDouble(Object value) {
return value instanceof Double;
}

// Ruby types

public static boolean isRubyBignum(Object value) {
return value instanceof RubyBignum;
}

public static boolean isRubyBigDecimal(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == BigDecimalNodes.BIG_DECIMAL_TYPE;
}

public static boolean isIntegerFixnumRange(Object value) {
return value instanceof RubyRange.IntegerFixnumRange;
}

public static boolean isRubyRange(Object value) {
return value instanceof RubyRange;
}

public static boolean isRubyArray(Object value) {
return value instanceof RubyArray;
return (value instanceof RubyBasicObject) && isRubyArray((RubyBasicObject) value);
}

public static boolean isRubyArray(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == ArrayNodes.ARRAY_TYPE;
}
public static boolean isRubyBinding(Object value) {
return value instanceof RubyBinding;
}
@@ -60,23 +74,27 @@ public static boolean isRubyClass(Object value) {
}

public static boolean isRubyHash(Object value) {
return value instanceof RubyHash;
return (value instanceof RubyBasicObject) && isRubyHash((RubyBasicObject) value);
}

public static boolean isRubyModule(Object value) {
return value instanceof RubyModule;
public static boolean isRubyHash(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == HashNodes.HASH_TYPE;
}

public static boolean isRubyRange(Object value) {
return value instanceof RubyRange;
public static boolean isRubyModule(Object value) {
return value instanceof RubyModule;
}

public static boolean isRubyRegexp(Object value) {
return value instanceof RubyRegexp;
}

public static boolean isRubyString(Object value) {
return value instanceof RubyString;
return (value instanceof RubyBasicObject) && isRubyString((RubyBasicObject) value);
}

public static boolean isRubyString(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == StringNodes.STRING_TYPE;
}

public static boolean isRubyEncoding(Object value) {
@@ -107,6 +125,8 @@ public static boolean isRubyBasicObject(Object value) {
return value instanceof RubyBasicObject;
}

// Internal types

public static boolean isThreadLocal(Object value) {
return value instanceof ThreadLocalObject;
}
@@ -115,10 +135,18 @@ public static boolean isForeignObject(Object object) {
return (object instanceof TruffleObject) && !(object instanceof RubyBasicObject);
}

public static boolean isTrue(boolean value) {
return value;
// Sentinels

public static boolean wasProvided(Object value) {
return !(wasNotProvided(value));
}

public static boolean wasNotProvided(Object value) {
return value instanceof NotProvided;
}

// Values

public static boolean isNaN(double value) {
return Double.isNaN(value);
}
@@ -127,8 +155,4 @@ public static boolean isInfinity(double value) {
return Double.isInfinite(value);
}

public static boolean isRubyBigDecimal(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == BigDecimalNodes.BIG_DECIMAL_TYPE;
}

}
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ public RubyBasicObject initialize(RubyException exception, NotProvided message)
return exception;
}

@Specialization(guards = "!isNotProvided(message)")
@Specialization(guards = "wasProvided(message)")
public RubyBasicObject initialize(RubyException exception, Object message) {
exception.initialize(message);
return exception;
Original file line number Diff line number Diff line change
@@ -606,7 +606,7 @@ public Object round(double n, NotProvided ndigits) {
return fixnumOrBignum.fixnumOrBignum(f);
}

@Specialization(guards = "!isNotProvided(ndigits)")
@Specialization(guards = "wasProvided(ndigits)")
public Object round(VirtualFrame frame, double n, Object ndigits) {
return ruby(frame, "round_internal(ndigits)", "ndigits", ndigits);
}
Original file line number Diff line number Diff line change
@@ -612,12 +612,12 @@ public Object classEval(VirtualFrame frame, RubyModule module, RubyString code,
return classEvalSource(frame, module, code, file.toString());
}

@Specialization(guards = "!isNotProvided(code)")
@Specialization(guards = "wasProvided(code)")
public Object classEval(VirtualFrame frame, RubyModule module, Object code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, toStr(frame, code), file.toString());
}

@Specialization(guards = "!isNotProvided(file)")
@Specialization(guards = "wasProvided(file)")
public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, Object file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, code, toStr(frame, file).toString());
}
@@ -648,7 +648,7 @@ public Object classEval(RubyModule self, NotProvided code, NotProvided file, Not
throw new RaiseException(getContext().getCoreLibrary().argumentError(0, 1, 2, this));
}

@Specialization(guards = "!isNotProvided(code)")
@Specialization(guards = "wasProvided(code)")
public Object classEval(RubyModule self, Object code, NotProvided file, NotProvided line, RubyProc block) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().argumentError(1, 0, this));
@@ -801,7 +801,7 @@ public RubyArray constants(RubyModule module, boolean inherit) {
return ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass(), constantsArray.toArray(new Object[constantsArray.size()]));
}

@Specialization(guards = "!isNotProvided(inherit)")
@Specialization(guards = "wasProvided(inherit)")
public RubyArray constants(VirtualFrame frame, RubyModule module, Object inherit) {
return constants(module, booleanCast(frame, inherit));
}
Original file line number Diff line number Diff line change
@@ -319,12 +319,12 @@ public Object step(VirtualFrame frame, RubyRange.LongFixnumRange range, int step
return range;
}

@Specialization(guards = { "!isStepValidInt(range, step, block)", "!isNotProvided(step)" })
@Specialization(guards = { "!isStepValidInt(range, step, block)", "wasProvided(step)" })
public Object stepFallback(VirtualFrame frame, RubyRange.IntegerFixnumRange range, Object step, RubyProc block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
}

@Specialization(guards = { "!isStepValidInt(range, step, block)", "!isNotProvided(step)" })
@Specialization(guards = { "!isStepValidInt(range, step, block)", "wasProvided(step)" })
public Object stepFallback(VirtualFrame frame, RubyRange.LongFixnumRange range, Object step, RubyProc block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
}
@@ -339,7 +339,7 @@ public Object step(VirtualFrame frame, RubyRange.IntegerFixnumRange range, NotPr
return ruby(frame, "step_internal(&block)", "block", block);
}

@Specialization(guards = { "!isInteger(step)", "!isLong(step)", "!isNotProvided(step)" })
@Specialization(guards = { "!isInteger(step)", "!isLong(step)", "wasProvided(step)" })
public Object step(VirtualFrame frame, RubyRange.IntegerFixnumRange range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
}
@@ -354,12 +354,12 @@ public Object step(VirtualFrame frame, RubyRange.LongFixnumRange range, NotProvi
return ruby(frame, "step_internal(&block)", "block", block);
}

@Specialization(guards = "!isNotProvided(step)")
@Specialization(guards = "wasProvided(step)")
public Object step(VirtualFrame frame, RubyRange.LongFixnumRange range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
}

@Specialization(guards = "!isNotProvided(step)")
@Specialization(guards = "wasProvided(step)")
public Object step(VirtualFrame frame, RubyRange.ObjectRange range, Object step, RubyProc block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
}
@@ -374,7 +374,7 @@ public Object step(VirtualFrame frame, RubyRange.ObjectRange range, NotProvided
return ruby(frame, "step_internal(&block)", "block", block);
}

@Specialization(guards = "!isNotProvided(step)")
@Specialization(guards = "wasProvided(step)")
public Object step(VirtualFrame frame, RubyRange.ObjectRange range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
}
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
@@ -62,6 +64,7 @@
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.object.BasicObjectType;
import org.jruby.truffle.runtime.rubinius.RubiniusByteArray;
import org.jruby.util.*;
import org.jruby.util.io.EncodingUtils;
@@ -73,6 +76,20 @@
@CoreClass(name = "String")
public abstract class StringNodes {

public static class StringType extends BasicObjectType {

}

public static final StringType STRING_TYPE = new StringType();

private static final DynamicObjectFactory STRING_FACTORY;

static {
final Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();
final Shape shape = RubyBasicObject.LAYOUT.createShape(STRING_TYPE);
STRING_FACTORY = shape.createFactory();
}

public static void set(RubyString string, ByteList bytes) {
string.bytes = bytes;
}
@@ -149,7 +166,7 @@ public static RubyString createString(RubyClass stringClass, ByteBuffer bytes) {
}

public static RubyString createString(RubyClass stringClass, ByteList bytes) {
return new RubyString(stringClass, bytes);
return new RubyString(stringClass, bytes, STRING_FACTORY.newInstance());
}

@CoreMethod(names = "+", required = 1)
@@ -565,12 +582,12 @@ public Object slice(VirtualFrame frame, RubyString string, int start, int length
return getSubstringNode().execute(frame, string, start, length);
}

@Specialization(guards = "!isNotProvided(length)")
@Specialization(guards = "wasProvided(length)")
public Object slice(VirtualFrame frame, RubyString string, int start, Object length) {
return slice(frame, string, start, getToIntNode().doInt(frame, length));
}

@Specialization(guards = { "!isRubyRange(start)", "!isRubyRegexp(start)", "!isRubyString(start)", "!isNotProvided(length)" })
@Specialization(guards = { "!isRubyRange(start)", "!isRubyRegexp(start)", "!isRubyString(start)", "wasProvided(length)" })
public Object slice(VirtualFrame frame, RubyString string, Object start, Object length) {
return slice(frame, string, getToIntNode().doInt(frame, start), getToIntNode().doInt(frame, length));
}
@@ -580,7 +597,7 @@ public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, No
return slice(frame, string, regexp, 0);
}

@Specialization(guards = "!isNotProvided(capture)")
@Specialization(guards = "wasProvided(capture)")
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, Object capture) {
// Extracted from Rubinius's definition of String#[].
return ruby(frame, "match, str = subpattern(index, other); Regexp.last_match = match; str", "index", regexp, "other", capture);
@@ -1264,7 +1281,7 @@ public RubyString initialize(RubyString self, RubyString from) {
return self;
}

@Specialization(guards = { "!isRubyString(from)", "!isNotProvided(from)" })
@Specialization(guards = { "!isRubyString(from)", "wasProvided(from)" })
public RubyString initialize(VirtualFrame frame, RubyString self, Object from) {
if (toStrNode == null) {
CompilerDirectives.transferToInterpreter();
@@ -2011,7 +2028,7 @@ public Object sum(VirtualFrame frame, RubyString string, NotProvided bits) {
return sum(frame, string, 16);
}

@Specialization(guards = { "!isInteger(bits)", "!isLong(bits)", "!isNotProvided(bits)" })
@Specialization(guards = { "!isInteger(bits)", "!isLong(bits)", "wasProvided(bits)" })
public Object sum(VirtualFrame frame, RubyString string, Object bits) {
return ruby(frame, "sum Rubinius::Type.coerce_to(bits, Fixnum, :to_int)", "bits", bits);
}
Original file line number Diff line number Diff line change
@@ -38,57 +38,57 @@ public AppendManyNode(RubyContext context, SourceSection sourceSection) {

// TODO CS 12-May-15 differentiate between null and empty but possibly having enough space

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, int[] other) {
ArrayNodes.setStore(array, Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, long[] other) {
ArrayNodes.setStore(array, Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, double[] other) {
ArrayNodes.setStore(array, Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, Object[] other) {
ArrayNodes.setStore(array, Arrays.copyOf(other, otherSize), otherSize);
return array;
}

// Append of the correct type

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, int[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, long[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, Object[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array)),
@@ -116,21 +116,21 @@ public void appendManySameTypeGeneric(RubyArray array, ArrayMirror storeMirror,

// Append something else into an Object[]

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, int[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, long[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
@@ -157,7 +157,7 @@ public void appendManyBoxIntoObjectGeneric(RubyArray array, int otherSize, Array

// Append forcing a generalization from int[] to long[]

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendManyLongIntoInteger(RubyArray array, int otherSize, long[] other) {
final int oldSize = ArrayNodes.getSize(array);
final int newSize = oldSize + otherSize;
@@ -173,49 +173,49 @@ public RubyArray appendManyLongIntoInteger(RubyArray array, int otherSize, long[

// Append forcing a generalization to Object[]

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendManyGeneralizeIntegerDouble(RubyArray array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendManyGeneralizeIntegerDouble(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray appendManyGeneralizeLongDouble(RubyArray array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray appendManyGeneralizeLongDouble(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray appendManyGeneralizeDoubleInteger(RubyArray array, int otherSize, int[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray appendManyGeneralizeDoubleLong(RubyArray array, int otherSize, long[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray appendManyGeneralizeDoubleObject(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)),
otherSize, ArrayMirror.reflect(other));
Original file line number Diff line number Diff line change
@@ -35,54 +35,54 @@ public AppendOneNode(RubyContext context, SourceSection sourceSection) {

// TODO CS 12-May-15 differentiate between null and empty but possibly having enough space

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendOneEmpty(RubyArray array, int value) {
ArrayNodes.setStore(array, new int[]{value}, 1);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendOneEmpty(RubyArray array, long value) {
ArrayNodes.setStore(array, new long[]{value}, 1);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendOneEmpty(RubyArray array, double value) {
ArrayNodes.setStore(array, new double[]{value}, 1);
return array;
}

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyArray appendOneEmpty(RubyArray array, Object value) {
ArrayNodes.setStore(array, new Object[]{value}, 1);
return array;
}

// Append of the correct type

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendOneSameType(RubyArray array, int value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendOneSameTypeGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)), value, extendProfile);
return array;
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray appendOneSameType(RubyArray array, long value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendOneSameTypeGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)), value, extendProfile);
return array;
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray appendOneSameType(RubyArray array, double value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendOneSameTypeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)), value, extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray appendOneSameType(RubyArray array, Object value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendOneSameTypeGeneric(array, ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array)), value, extendProfile);
@@ -107,7 +107,7 @@ public void appendOneSameTypeGeneric(RubyArray array, ArrayMirror storeMirror, O

// Append forcing a generalization from int[] to long[]

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray appendOneLongIntoInteger(RubyArray array, long value) {
final int oldSize = ArrayNodes.getSize(array);
final int newSize = oldSize + 1;
@@ -122,19 +122,19 @@ public RubyArray appendOneLongIntoInteger(RubyArray array, long value) {

// Append forcing a generalization to Object[]

@Specialization(guards = {"isIntegerFixnum(array)", "!isInteger(value)", "!isLong(value)"})
@Specialization(guards = {"isIntArray(array)", "!isInteger(value)", "!isLong(value)"})
public RubyArray appendOneGeneralizeInteger(RubyArray array, Object value) {
appendOneGeneralizeGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)), value);
return array;
}

@Specialization(guards = {"isLongFixnum(array)", "!isInteger(value)", "!isLong(value)"})
@Specialization(guards = {"isLongArray(array)", "!isInteger(value)", "!isLong(value)"})
public RubyArray appendOneGeneralizeLong(RubyArray array, Object value) {
appendOneGeneralizeGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)), value);
return array;
}

@Specialization(guards = {"isFloat(array)", "!isDouble(value)"})
@Specialization(guards = {"isDoubleArray(array)", "!isDouble(value)"})
public RubyArray appendOneGeneralizeDouble(RubyArray array, Object value) {
appendOneGeneralizeGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)), value);
return array;
Original file line number Diff line number Diff line change
@@ -31,14 +31,14 @@ public ArrayDropTailNode(RubyContext context, SourceSection sourceSection, int i
this.index = index;
}

@Specialization(guards = "isNull(array)")
@Specialization(guards = "isNullArray(array)")
public RubyArray getHeadNull(RubyArray array) {
CompilerDirectives.transferToInterpreter();

return createEmptyArray();
}

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray getHeadIntegerFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -49,7 +49,7 @@ public RubyArray getHeadIntegerFixnum(RubyArray array) {
}
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray geHeadLongFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -61,7 +61,7 @@ public RubyArray geHeadLongFixnum(RubyArray array) {
}
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray getHeadFloat(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -73,7 +73,7 @@ public RubyArray getHeadFloat(RubyArray array) {
}
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray getHeadObject(RubyArray array) {
CompilerDirectives.transferToInterpreter();

Original file line number Diff line number Diff line change
@@ -34,27 +34,27 @@ public ArrayDupNode(RubyContext context, SourceSection sourceSection) {

public abstract RubyArray executeDup(VirtualFrame frame, RubyArray array);

@Specialization(guards = "isNull(from)")
@Specialization(guards = "isNullArray(from)")
public RubyArray dupNull(RubyArray from) {
return createEmptyArray();
}

@Specialization(guards = "isIntegerFixnum(from)")
@Specialization(guards = "isIntArray(from)")
public RubyArray dupIntegerFixnum(RubyArray from) {
return createArray(Arrays.copyOf((int[]) ArrayNodes.getStore(from), ArrayNodes.getSize(from)), ArrayNodes.getSize(from));
}

@Specialization(guards = "isLongFixnum(from)")
@Specialization(guards = "isLongArray(from)")
public RubyArray dupLongFixnum(RubyArray from) {
return createArray(Arrays.copyOf((long[]) ArrayNodes.getStore(from), ArrayNodes.getSize(from)), ArrayNodes.getSize(from));
}

@Specialization(guards = "isFloat(from)")
@Specialization(guards = "isDoubleArray(from)")
public RubyArray dupFloat(RubyArray from) {
return createArray(Arrays.copyOf((double[]) ArrayNodes.getStore(from), ArrayNodes.getSize(from)), ArrayNodes.getSize(from));
}

@Specialization(guards = "isObject(from)")
@Specialization(guards = "isObjectArray(from)")
public RubyArray dupObject(RubyArray from) {
return createArray(Arrays.copyOf((Object[]) ArrayNodes.getStore(from), ArrayNodes.getSize(from)), ArrayNodes.getSize(from));
}
Original file line number Diff line number Diff line change
@@ -31,14 +31,14 @@ public ArrayGetTailNode(RubyContext context, SourceSection sourceSection, int in
this.index = index;
}

@Specialization(guards = "isNull(array)")
@Specialization(guards = "isNullArray(array)")
public RubyArray getTailNull(RubyArray array) {
CompilerDirectives.transferToInterpreter();

return createEmptyArray();
}

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray getTailIntegerFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -49,7 +49,7 @@ public RubyArray getTailIntegerFixnum(RubyArray array) {
}
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray getTailLongFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -60,7 +60,7 @@ public RubyArray getTailLongFixnum(RubyArray array) {
}
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray getTailFloat(RubyArray array) {
CompilerDirectives.transferToInterpreter();

@@ -71,7 +71,7 @@ public RubyArray getTailFloat(RubyArray array) {
}
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray getTailObject(RubyArray array) {
CompilerDirectives.transferToInterpreter();

Original file line number Diff line number Diff line change
@@ -14,83 +14,7 @@

public class ArrayGuards {

public static boolean isEmpty(RubyArray array) {
return ArrayNodes.getSize(array) == 0;
}

public static boolean isOtherEmpty(RubyArray array, RubyArray other) {
return ArrayNodes.getSize(other) == 0;
}

public static boolean isNull(RubyArray array) {
return ArrayNodes.getStore(array) == null;
}

public static boolean isNullOrEmpty(RubyArray array) {
return ArrayNodes.getStore(array) == null || ArrayNodes.getSize(array) == 0;
}

public static boolean isIntegerFixnum(RubyArray array) {
return ArrayNodes.getStore(array) instanceof int[];
}

public static boolean isLongFixnum(RubyArray array) {
return ArrayNodes.getStore(array) instanceof long[];
}

public static boolean isFloat(RubyArray array) {
return ArrayNodes.getStore(array) instanceof double[];
}

public static boolean isObject(RubyArray array) {
return ArrayNodes.getStore(array) instanceof Object[];
}

public static boolean isOtherNull(RubyArray array, RubyArray other) {
return ArrayNodes.getStore(other) == null;
}

public static boolean isOtherIntegerFixnum(RubyArray array, RubyArray other) {
return ArrayNodes.getStore(other) instanceof int[];
}

public static boolean isOtherLongFixnum(RubyArray array, RubyArray other) {
return ArrayNodes.getStore(other) instanceof long[];
}

public static boolean isOtherFloat(RubyArray array, RubyArray other) {
return ArrayNodes.getStore(other) instanceof double[];
}

public static boolean isOtherObject(RubyArray array, RubyArray other) {
return ArrayNodes.getStore(other) instanceof Object[];
}

public static boolean areBothNull(RubyArray a, RubyArray b) {
return ArrayNodes.getStore(a) == null && ArrayNodes.getStore(b) == null;
}

public static boolean areBothIntegerFixnum(RubyArray a, RubyArray b) {
return ArrayNodes.getStore(a) instanceof int[] && ArrayNodes.getStore(b) instanceof int[];
}

public static boolean areBothIntegerFixnum(RubyArray array, RubyRange.IntegerFixnumRange range, RubyArray other) {
return ArrayNodes.getStore(array) instanceof int[] && ArrayNodes.getStore(other) instanceof int[];
}

public static boolean areBothLongFixnum(RubyArray a, RubyArray b) {
return ArrayNodes.getStore(a) instanceof long[] && ArrayNodes.getStore(b) instanceof long[];
}

public static boolean areBothFloat(RubyArray a, RubyArray b) {
return ArrayNodes.getStore(a) instanceof double[] && ArrayNodes.getStore(b) instanceof double[];
}

public static boolean areBothObject(RubyArray a, RubyArray b) {
return ArrayNodes.getStore(a) instanceof Object[] && ArrayNodes.getStore(b) instanceof Object[];
}

// New names being used for the new primitive nodes - old guards will be removed over time
// Storage strategies

public static boolean isNullArray(RubyArray array) {
return ArrayNodes.getStore(array) == null;
@@ -112,29 +36,10 @@ public static boolean isObjectArray(RubyArray array) {
return ArrayNodes.getStore(array) instanceof Object[];
}

public static boolean isOtherSingleIntegerFixnumArray(RubyArray array, Object[] others) {
return others.length == 1 && others[0] instanceof RubyArray && ArrayNodes.getStore(((RubyArray) others[0])) instanceof int[];
}

public static boolean isOtherSingleObjectArray(RubyArray array, Object[] others) {
return others.length == 1 && others[0] instanceof RubyArray && ArrayNodes.getStore(((RubyArray) others[0])) instanceof Object[];
}

public static boolean isArgsLengthTwo(RubyArray array, Object[] others) {
return others.length == 2;
}
// Higher level properties

public static boolean isIntIndexAndOtherSingleObjectArg(RubyArray array, Object[] others) {
return others.length == 2 && others[0] instanceof Integer && others[1] instanceof Object;
}

public static boolean isNegative(RubyArray array, int size) {
return size < 0;
}

public static boolean isNegative(RubyArray array, long size) {
return size < 0;
public static boolean isEmptyArray(RubyArray array) {
return ArrayNodes.getSize(array) == 0;
}


}
373 changes: 203 additions & 170 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/array/ArrayNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -35,14 +35,14 @@ public ArraySliceNode(RubyContext context, SourceSection sourceSection, int from
this.to = to;
}

@Specialization(guards = "isNull(array)")
@Specialization(guards = "isNullArray(array)")
public RubyArray sliceNull(RubyArray array) {
CompilerDirectives.transferToInterpreter();

return createEmptyArray();
}

@Specialization(guards = "isIntegerFixnum(array)")
@Specialization(guards = "isIntArray(array)")
public RubyArray sliceIntegerFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();
final int to = ArrayNodes.getSize(array) + this.to;
@@ -54,7 +54,7 @@ public RubyArray sliceIntegerFixnum(RubyArray array) {
}
}

@Specialization(guards = "isLongFixnum(array)")
@Specialization(guards = "isLongArray(array)")
public RubyArray sliceLongFixnum(RubyArray array) {
CompilerDirectives.transferToInterpreter();
final int to = ArrayNodes.getSize(array) + this.to;
@@ -66,7 +66,7 @@ public RubyArray sliceLongFixnum(RubyArray array) {
}
}

@Specialization(guards = "isFloat(array)")
@Specialization(guards = "isDoubleArray(array)")
public RubyArray sliceFloat(RubyArray array) {
CompilerDirectives.transferToInterpreter();
final int to = ArrayNodes.getSize(array) + this.to;
@@ -78,7 +78,7 @@ public RubyArray sliceFloat(RubyArray array) {
}
}

@Specialization(guards = "isObject(array)")
@Specialization(guards = "isObjectArray(array)")
public RubyArray sliceObject(RubyArray array) {
CompilerDirectives.transferToInterpreter();
final int to = ArrayNodes.getSize(array) + this.to;
Original file line number Diff line number Diff line change
@@ -31,29 +31,29 @@ public PopOneNode(RubyContext context, SourceSection sourceSection) {

// Pop from an empty array

@Specialization(guards = "isEmpty(array)")
@Specialization(guards = "isEmptyArray(array)")
public RubyBasicObject popOneEmpty(RubyArray array) {
return nil();
}

// Pop from a non-empty array

@Specialization(guards = {"!isEmpty(array)", "isIntegerFixnum(array)"})
@Specialization(guards = {"!isEmptyArray(array)", "isIntArray(array)"})
public Object popOneInteger(RubyArray array) {
return popOneGeneric(array, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)));
}

@Specialization(guards = {"!isEmpty(array)", "isLongFixnum(array)"})
@Specialization(guards = {"!isEmptyArray(array)", "isLongArray(array)"})
public Object popOneLong(RubyArray array) {
return popOneGeneric(array, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)));
}

@Specialization(guards = {"!isEmpty(array)", "isFloat(array)"})
@Specialization(guards = {"!isEmptyArray(array)", "isDoubleArray(array)"})
public Object popOneDouble(RubyArray array) {
return popOneGeneric(array, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)));
}

@Specialization(guards = {"!isEmpty(array)", "isObject(array)"})
@Specialization(guards = {"!isEmptyArray(array)", "isObjectArray(array)"})
public Object popOneObject(RubyArray array) {
return popOneGeneric(array, ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2013, 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.core.hash;

import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.hash.Entry;

public abstract class HashGuards {

// Storage strategies

public static boolean isNullHash(RubyHash hash) {
return HashNodes.getStore(hash) == null;
}

public static boolean isPackedHash(RubyHash hash) {
// Can't do instanceof Object[] due to covariance
return !(isNullHash(hash) || isBucketHash(hash));
}

public static boolean isBucketHash(RubyHash hash) {
return HashNodes.getStore(hash) instanceof Entry[];
}

// Higher level properties

public static boolean isEmptyHash(RubyHash hash) {
return HashNodes.getSize(hash) == 0;
}

public static boolean isCompareByIdentity(RubyHash hash) {
return HashNodes.isCompareByIdentity(hash);
}

public static boolean hasDefaultValue(RubyHash hash) {
return HashNodes.getDefaultValue(hash) != null;
}

public static boolean hasDefaultBlock(RubyHash hash) {
return HashNodes.getDefaultBlock(hash) != null;
}

}
Original file line number Diff line number Diff line change
@@ -10,12 +10,16 @@
package org.jruby.truffle.nodes.core.hash;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.object.BasicObjectType;

public class HashNode extends RubyNode {

130 changes: 57 additions & 73 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/hash/HashNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -30,12 +30,12 @@ public ClassNode(RubyContext context, SourceSection sourceSection) {

public abstract RubyClass executeGetClass(VirtualFrame frame, Object value);

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

@Specialization(guards = "!isTrue(value)")
@Specialization(guards = "!value")
protected RubyClass getClassFalse(boolean value) {
return getContext().getCoreLibrary().getFalseClass();
}
Original file line number Diff line number Diff line change
@@ -30,12 +30,12 @@ public MetaClassNode(RubyContext context, SourceSection sourceSection) {

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

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

@Specialization(guards = "!isTrue(value)")
@Specialization(guards = "!value")
protected RubyClass singletonClassFalse(boolean value) {
return getContext().getCoreLibrary().getFalseClass();
}
Original file line number Diff line number Diff line change
@@ -38,12 +38,12 @@ public SingletonClassNode(RubyContext context, SourceSection sourceSection) {

public abstract RubyClass executeSingletonClass(VirtualFrame frame, Object value);

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

@Specialization(guards = "!isTrue(value)")
@Specialization(guards = "!value")
protected RubyClass singletonClassFalse(boolean value) {
return getContext().getCoreLibrary().getFalseClass();
}
Original file line number Diff line number Diff line change
@@ -40,12 +40,12 @@ public int objectID(Object nil) {
return ObjectIDOperations.NIL;
}

@Specialization(guards = "isTrue(value)")
@Specialization(guards = "value")
public int objectIDTrue(boolean value) {
return ObjectIDOperations.TRUE;
}

@Specialization(guards = "!isTrue(value)")
@Specialization(guards = "!value")
public int objectIDFalse(boolean value) {
return ObjectIDOperations.FALSE;
}
Original file line number Diff line number Diff line change
@@ -297,6 +297,28 @@ public int umask(int mask) {

}

@CoreMethod(names = "utimes", isModuleFunction = true, required = 2)
public abstract static class UtimesNode extends CoreMethodArrayArgumentsNode {

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

@Specialization
public int utimes(RubyString path, RubyBasicObject pointer) {
final String pathString = RubyEncoding.decodeUTF8(path.getByteList().getUnsafeBytes(), path.getByteList().getBegin(), path.getByteList().getRealSize());

final int result = posix().utimes(pathString, PointerPrimitiveNodes.getPointer(pointer));
if (result == -1) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(posix().errno(), this));
}

return result;
}

}

@CoreMethod(names = "mkdir", isModuleFunction = true, required = 2)
public abstract static class MkdirNode extends CoreMethodArrayArgumentsNode {

Original file line number Diff line number Diff line change
@@ -81,14 +81,14 @@ public TimeSSpecificPrimitiveNode(RubyContext context, SourceSection sourceSecti
readTimeZoneNode = new ReadTimeZoneNode(context, sourceSection);
}

@Specialization(guards = { "isTrue(isUTC)", "isNil(offset)" })
@Specialization(guards = { "isUTC", "isNil(offset)" })
public RubyTime timeSSpecificUTC(long seconds, int nanoseconds, boolean isUTC, Object offset) {
// TODO(CS): overflow checks needed?
final long milliseconds = getMillis(seconds, nanoseconds);
return new RubyTime(getContext().getCoreLibrary().getTimeClass(), time(milliseconds), nil());
}

@Specialization(guards = { "!isTrue(isUTC)", "isNil(offset)" })
@Specialization(guards = { "!isUTC", "isNil(offset)" })
public RubyTime timeSSpecific(VirtualFrame frame, long seconds, int nanoseconds, boolean isUTC, Object offset) {
// TODO(CS): overflow checks needed?
final long milliseconds = getMillis(seconds, nanoseconds);
Original file line number Diff line number Diff line change
@@ -9,15 +9,16 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.nodes.core.array.ArrayNodes;

public final class RubyArray extends RubyBasicObject {

public Object store;
public int size;

public RubyArray(RubyClass arrayClass, Object store, int size) {
super(arrayClass);
public RubyArray(RubyClass arrayClass, Object store, int size, DynamicObject dynamicObject) {
super(arrayClass, dynamicObject);
ArrayNodes.setStore(this, store, size);
}

Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.runtime.hash.Entry;
import org.jruby.truffle.runtime.hash.HashOperations;

@@ -22,8 +23,8 @@ public class RubyHash extends RubyBasicObject {
public Entry lastInSequence;
public boolean compareByIdentity;

public RubyHash(RubyClass rubyClass, RubyProc defaultBlock, Object defaultValue, Object store, int size, Entry firstInSequence) {
super(rubyClass);
public RubyHash(RubyClass rubyClass, RubyProc defaultBlock, Object defaultValue, Object store, int size, Entry firstInSequence, DynamicObject dynamicObject) {
super(rubyClass, dynamicObject);
this.defaultBlock = defaultBlock;
this.defaultValue = defaultValue;
this.store = store;
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.DynamicObject;
import org.jcodings.Encoding;
import org.jruby.runtime.Helpers;
import org.jruby.util.ByteList;
@@ -21,8 +22,8 @@ public class RubyString extends RubyBasicObject implements CodeRangeable {
public ByteList bytes;
public int codeRange = StringSupport.CR_UNKNOWN;

public RubyString(RubyClass stringClass, ByteList bytes) {
super(stringClass);
public RubyString(RubyClass stringClass, ByteList bytes, DynamicObject dynamicObject) {
super(stringClass, dynamicObject);
this.bytes = bytes;
}

0 comments on commit a43063a

Please sign in to comment.