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: 72536b37a897
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3855ace3ceae
Choose a head ref
  • 2 commits
  • 3 files changed
  • 2 contributors

Commits on Mar 25, 2015

  1. Copy the full SHA
    c7bc8f3 View commit details
  2. Merge pull request #2755 from bjfish/truffle_array_insert

    [Truffle] Updating Array#insert to pass additional specs.
    chrisseaton committed Mar 25, 2015
    Copy the full SHA
    3855ace View commit details
10 changes: 0 additions & 10 deletions spec/truffle/tags/core/array/insert_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -120,4 +120,13 @@ public static boolean isOtherSingleObjectArray(RubyArray array, Object[] others)
return others.length == 1 && others[0] instanceof RubyArray && ((RubyArray) others[0]).getStore() instanceof Object[];
}

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

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


}
73 changes: 58 additions & 15 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -1899,9 +1899,10 @@ public Object inject(VirtualFrame frame, RubyArray array, RubySymbol symbol, Und

}

@CoreMethod(names = "insert", required = 2, raiseIfFrozenSelf = true)
@CoreMethod(names = "insert", required = 1, raiseIfFrozenSelf = true, argumentsAsArray = true)
public abstract static class InsertNode extends ArrayCoreMethodNode {

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

public InsertNode(RubyContext context, SourceSection sourceSection) {
@@ -1910,35 +1911,77 @@ public InsertNode(RubyContext context, SourceSection sourceSection) {

public InsertNode(InsertNode prev) {
super(prev);
this.toIntNode = prev.toIntNode;
}

@Specialization(guards = "isNull")
public Object insert(RubyArray array, int index, Object value) {
@Specialization(guards = {"isNull", "isIntIndexAndOtherSingleObjectArg"})
public Object insertNull(RubyArray array, Object[] values) {
notDesignedForCompilation();

final int index = (int) values[0];
if (index < 0) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
}
final Object value = (Object) values[1];
final Object[] store = new Object[index + 1];
Arrays.fill(store, nil());
store[index] = value;
array.setStore(store, array.getSize() + 1);
return array;
}

@Specialization(guards = "isIntegerFixnum")
public Object insert(RubyArray array, int index, int value) {
final int normalizedIndex = array.normalizeIndex(index);
@Specialization(guards = "isArgsLengthTwo", rewriteOn = {ClassCastException.class, IndexOutOfBoundsException.class})
public Object insert(RubyArray array, Object[] values) {
final int index = (int) values[0];
final int value = (int) values[1];
final int[] store = (int[]) array.getStore();
System.arraycopy(store, index, store, index + 1, array.getSize() - index);
store[index] = value;
array.setStore(store, array.getSize() + 1);
return array;
}

@Specialization(contains = {"insert", "insertNull"})
public Object insertBoxed(VirtualFrame frame, RubyArray array, Object[] values) {
notDesignedForCompilation();
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(ToIntNodeFactory.create(getContext(), getSourceSection(), null));
}
index = toIntNode.executeIntegerFixnum(frame, values[0]);
}

final int valuesLength = values.length - 1;
final int normalizedIndex = index < 0 ? array.normalizeIndex(index) + 1 : array.normalizeIndex(index);
if (normalizedIndex < 0) {
tooSmallBranch.enter();
throw new UnsupportedOperationException();
} else if (array.getSize() > store.length + 1) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
} else {
System.arraycopy(store, normalizedIndex, store, normalizedIndex + 1, array.getSize() - normalizedIndex);
store[normalizedIndex] = value;
array.setStore(store, array.getSize() + 1);
String errMessage = "index " + index + " too small for array; minimum: " + Integer.toString(-array.getSize());
throw new RaiseException(getContext().getCoreLibrary().indexError(errMessage, this));
}

Object[] store = ArrayUtils.box(array.getStore());
final int newSize = normalizedIndex < array.getSize() ? array.getSize() + valuesLength : normalizedIndex + valuesLength;
store = Arrays.copyOf(store, newSize);
if (normalizedIndex >= array.getSize()) {
for (int i = array.getSize(); i < normalizedIndex; i++) {
store[i] = nil();
}
}
final int dest = normalizedIndex + valuesLength;
final int len = array.getSize() - normalizedIndex;
if (normalizedIndex < array.getSize()) {
System.arraycopy(store, normalizedIndex, store, dest, len);
}
System.arraycopy(values, 1, store, normalizedIndex, valuesLength);
array.setStore(store, newSize);

return array;
}