Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9401b659e4e8
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ef60a676ef7a
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Jul 26, 2015

  1. Copy the full SHA
    c0d46ed View commit details
  2. [Truffle] Fix Array#insert.

    * Support negatives indices in Array#insert.
    eregon committed Jul 26, 2015
    Copy the full SHA
    000b827 View commit details
  3. Copy the full SHA
    2482dd5 View commit details
  4. Copy the full SHA
    ef60a67 View commit details
Original file line number Diff line number Diff line change
@@ -348,8 +348,15 @@ public Object start(int length) {

@Override
public Object ensure(Object store, int length) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
if (length > ((double[]) store).length) {
CompilerDirectives.transferToInterpreter();
final Object[] newStore = ArrayUtils.box((double[]) store);
final UninitializedArrayBuilderNode newNode = new UninitializedArrayBuilderNode(getContext());
replace(newNode);
newNode.resume(newStore);
return newNode.ensure(newStore, length);
}
return store;
}

@Override
Original file line number Diff line number Diff line change
@@ -737,11 +737,7 @@ public IndexSetNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = {"!isInteger(indexObject)", "!isIntegerFixnumRange(indexObject)"})
public Object set(VirtualFrame frame, RubyBasicObject array, Object indexObject, Object value, NotProvided unused) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
final int index = toIntNode.doInt(frame, indexObject);
final int index = toInt(frame, indexObject);
return set(frame, array, index, value, unused);
}

@@ -753,41 +749,25 @@ public Object set(VirtualFrame frame, RubyBasicObject array, int index, Object v
String errMessage = "index " + index + " too small for array; minimum: " + Integer.toString(-getSize(array));
throw new RaiseException(getContext().getCoreLibrary().indexError(errMessage, this));
}
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}
return writeNode.executeWrite(frame, (RubyBasicObject) array, index, value);
return write(frame, (RubyBasicObject) array, index, value);
}

@Specialization(guards = { "!isRubyArray(value)", "wasProvided(value)", "!isInteger(lengthObject)" })
public Object setObject(VirtualFrame frame, RubyBasicObject array, int start, Object lengthObject, Object value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int length = toIntNode.doInt(frame, lengthObject);
int length = toInt(frame, lengthObject);
return setObject(frame, array, start, length, value);
}

@Specialization(guards = { "!isRubyArray(value)", "wasProvided(value)", "!isInteger(startObject)" })
public Object setObject(VirtualFrame frame, RubyBasicObject array, Object startObject, int length, Object value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int start = toIntNode.doInt(frame, startObject);
int start = toInt(frame, startObject);
return setObject(frame, array, start, length, value);
}

@Specialization(guards = { "!isRubyArray(value)", "wasProvided(value)", "!isInteger(startObject)", "!isInteger(lengthObject)" })
public Object setObject(VirtualFrame frame, RubyBasicObject array, Object startObject, Object lengthObject, Object value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int length = toIntNode.doInt(frame, lengthObject);
int start = toIntNode.doInt(frame, startObject);
int length = toInt(frame, lengthObject);
int start = toInt(frame, startObject);
return setObject(frame, array, start, length, value);
}

@@ -811,33 +791,24 @@ public Object setObject(VirtualFrame frame, RubyBasicObject array, int start, in
final int begin = normalizeIndex(array, start);

if (begin < getSize(array) && length == 1) {
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}

return writeNode.executeWrite(frame, (RubyBasicObject) array, begin, value);
return write(frame, array, begin, value);
} else {
if (getSize(array) > (begin + length)) { // there is a tail, else other values discarded
if (readSliceNode == null) {
CompilerDirectives.transferToInterpreter();
readSliceNode = insert(ArrayReadSliceDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}
RubyBasicObject endValues = (RubyBasicObject) readSliceNode.executeReadSlice(frame, (RubyBasicObject) array, (begin + length), (getSize(array) - begin - length));
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}
writeNode.executeWrite(frame, (RubyBasicObject) array, begin, value);
write(frame, array, begin, value);
Object[] endValuesStore = ArrayUtils.box(getStore(endValues));

int i = begin + 1;
for (Object obj : endValuesStore) {
writeNode.executeWrite(frame, (RubyBasicObject) array, i, obj);
write(frame, array, i, obj);
i += 1;
}
} else {
writeNode.executeWrite(frame, (RubyBasicObject) array, begin, value);
write(frame, array, begin, value);
}
if (popOneNode == null) {
CompilerDirectives.transferToInterpreter();
@@ -853,32 +824,20 @@ public Object setObject(VirtualFrame frame, RubyBasicObject array, int start, in

@Specialization(guards = {"!isInteger(startObject)", "isRubyArray(value)"})
public Object setOtherArray(VirtualFrame frame, RubyBasicObject array, Object startObject, int length, RubyBasicObject value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int start = toIntNode.doInt(frame, startObject);
int start = toInt(frame, startObject);
return setOtherArray(frame, array, start, length, value);
}

@Specialization(guards = {"!isInteger(lengthObject)", "isRubyArray(value)"})
public Object setOtherArray(VirtualFrame frame, RubyBasicObject array, int start, Object lengthObject, RubyBasicObject value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int length = toIntNode.doInt(frame, lengthObject);
int length = toInt(frame, lengthObject);
return setOtherArray(frame, array, start, length, value);
}

@Specialization(guards = {"!isInteger(startObject)", "!isInteger(lengthObject)", "isRubyArray(value)"})
public Object setOtherArray(VirtualFrame frame, RubyBasicObject array, Object startObject, Object lengthObject, RubyBasicObject value) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
int start = toIntNode.doInt(frame, startObject);
int length = toIntNode.doInt(frame, lengthObject);
int start = toInt(frame, startObject);
int length = toInt(frame, lengthObject);
return setOtherArray(frame, array, start, length, value);
}

@@ -903,13 +862,8 @@ public Object setOtherArray(VirtualFrame frame, RubyBasicObject array, int start
final Object[] replacementStore = slowToArray(replacement);

if (replacementLength == length) {
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}

for (int i = 0; i < length; i++) {
writeNode.executeWrite(frame, array, start + i, replacementStore[i]);
write(frame, array, start + i, replacementStore[i]);
}
} else {
final int arrayLength = getSize(array);
@@ -1011,6 +965,21 @@ public Object setIntegerFixnumRange(VirtualFrame frame, RubyBasicObject array, R
return other;
}

private Object write(VirtualFrame frame, RubyBasicObject array, int index, Object value) {
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeGen.create(getContext(), getSourceSection(), null, null, null));
}
return writeNode.executeWrite(frame, array, index, value);
}

private int toInt(VirtualFrame frame, Object indexObject) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
return toIntNode.doInt(frame, indexObject);
}

}

@@ -2250,7 +2219,6 @@ private Object injectSymbolHelper(VirtualFrame frame, ArrayMirror mirror, RubyBa
public abstract static class InsertNode extends ArrayCoreMethodNode {

@Child private ToIntNode toIntNode;
private final BranchProfile tooSmallBranch = BranchProfile.create();

public InsertNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -2259,22 +2227,18 @@ public InsertNode(RubyContext context, SourceSection sourceSection) {
@Specialization(guards = {"isNullArray(array)", "isIntIndexAndOtherSingleObjectArg(values)"})
public Object insertNull(RubyBasicObject array, Object[] values) {
CompilerDirectives.transferToInterpreter();
final int index = (int) values[0];
if (index < 0) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
}
final int index = normalizeInsertIndex(array, (int) values[0]);
final Object value = (Object) values[1];
final Object[] store = new Object[index + 1];
Arrays.fill(store, nil());
store[index] = value;
setStore(array, store, getSize(array) + 1);
setStore(array, store, index + 1);
return array;
}

@Specialization(guards = "isArgsLengthTwo(values)", rewriteOn = {ClassCastException.class, IndexOutOfBoundsException.class})
public Object insert(RubyBasicObject array, Object[] values) {
final int index = (int) values[0];
@Specialization(guards = { "isArgsTwoInts(values)", "isIndexSmallerThanSize(values,array)", "isIntArray(array)", "hasRoomForOneExtra(array)" })
public Object insert(VirtualFrame frame, RubyBasicObject array, Object[] values) {
final int index = normalizeInsertIndex(array, (int) values[0]);
final int value = (int) values[1];
final int[] store = (int[]) getStore(array);
System.arraycopy(store, index, store, index + 1, getSize(array) - index);
@@ -2283,31 +2247,17 @@ public Object insert(RubyBasicObject array, Object[] values) {
return array;
}

@Specialization(contains = {"insert", "insertNull"})
@Specialization(contains = { "insert", "insertNull" })
public Object insertBoxed(VirtualFrame frame, RubyBasicObject array, Object[] values) {
CompilerDirectives.transferToInterpreter();
if (values.length == 1) {
return array;
}

int index;
if (values[0] instanceof Integer) {
index = (int) values[0];
} else {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
index = toIntNode.doInt(frame, values[0]);
}
int index = toInt(frame, values[0]);

final int valuesLength = values.length - 1;
final int normalizedIndex = index < 0 ? normalizeIndex(array, index) + 1 : normalizeIndex(array, index);
if (normalizedIndex < 0) {
CompilerDirectives.transferToInterpreter();
String errMessage = "index " + index + " too small for array; minimum: " + Integer.toString(-getSize(array));
throw new RaiseException(getContext().getCoreLibrary().indexError(errMessage, this));
}
final int normalizedIndex = normalizeInsertIndex(array, index);

Object[] store = ArrayUtils.box(getStore(array));
final int newSize = normalizedIndex < getSize(array) ? getSize(array) + valuesLength : normalizedIndex + valuesLength;
@@ -2328,14 +2278,40 @@ public Object insertBoxed(VirtualFrame frame, RubyBasicObject array, Object[] va
return array;
}

protected static boolean isArgsLengthTwo(Object[] others) {
return others.length == 2;
private int normalizeInsertIndex(RubyBasicObject array, int index) {
final int normalizedIndex = index < 0 ? normalizeIndex(array, index) + 1 : index;
if (normalizedIndex < 0) {
CompilerDirectives.transferToInterpreter();
String errMessage = "index " + index + " too small for array; minimum: " + Integer.toString(-getSize(array));
throw new RaiseException(getContext().getCoreLibrary().indexError(errMessage, this));
}
return normalizedIndex;
}

protected static boolean isArgsTwoInts(Object[] others) {
return others.length == 2 && others[0] instanceof Integer && others[1] instanceof Integer;
}

protected static boolean isIndexSmallerThanSize(Object[] others, RubyBasicObject array) {
return (int) others[0] < getSize(array);
}

protected static boolean hasRoomForOneExtra(RubyBasicObject array) {
return ((int[]) getStore(array)).length > getSize(array);
}

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

private int toInt(VirtualFrame frame, Object indexObject) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeGen.create(getContext(), getSourceSection(), null));
}
return toIntNode.doInt(frame, indexObject);
}

}

@CoreMethod(names = {"map", "collect"}, needsBlock = true, returnsEnumeratorIfNoBlock = true)
Original file line number Diff line number Diff line change
@@ -331,6 +331,10 @@ public Object construct(VirtualFrame frame, RubyBasicObject hashClass, Object[]
return constructFallback(frame, hashClass, args);
}

if (ArrayNodes.getSize(pairArray) != 2) {
return constructFallback(frame, hashClass, args);
}

final Object[] pairStore = (Object[]) ArrayNodes.getStore(pairArray);

final Object key = pairStore[0];