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

Commits on Mar 16, 2015

  1. 1
    Copy the full SHA
    c0a4676 View commit details
  2. Merge pull request #2707 from bjfish/truffle_array_element_set

    [Truffle] Adding progress on Array#[]=.
    chrisseaton committed Mar 16, 2015
    Copy the full SHA
    bbd7e02 View commit details
Showing with 84 additions and 50 deletions.
  1. +0 −25 spec/truffle/tags/core/array/element_set_tags.txt
  2. +84 −25 truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
25 changes: 0 additions & 25 deletions spec/truffle/tags/core/array/element_set_tags.txt
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
fails:Array#[]= sets the section defined by [start,length] to other
fails:Array#[]= replaces the section defined by [start,length] with the given values
fails:Array#[]= just sets the section defined by [start,length] to other even if other is nil
fails:Array#[]= returns nil if the rhs is nil
fails:Array#[]= sets the section defined by range to other
fails:Array#[]= replaces the section defined by range with the given values
fails:Array#[]= just sets the section defined by range to other even if other is nil
fails:Array#[]= expands and nil-pads the array if section assigned by range is outside array boundaries
fails:Array#[]= calls to_int on its start and length arguments
fails:Array#[]= sets elements in the range arguments when passed ranges
fails:Array#[]= inserts the given elements with [range] which the range is zero-width
fails:Array#[]= inserts the given elements with [start, length] which length is zero
fails:Array#[]= inserts the given elements with [range] which the range has negative width
fails:Array#[]= just inserts nil if the section defined by range is zero-width and the rhs is nil
fails:Array#[]= just inserts nil if the section defined by range has negative width and the rhs is nil
fails:Array#[]= does nothing if the section defined by range is zero-width and the rhs is an empty array
fails:Array#[]= does nothing if the section defined by range has negative width and the rhs is an empty array
fails:Array#[]= tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]
fails:Array#[]= raises an IndexError when passed indexes out of bounds
fails:Array#[]= calls to_ary on its rhs argument for multi-element sets
fails:Array#[]= does not call to_ary on rhs array subclasses for multi-element sets
fails:Array#[]= with [index, count] returns non-array value if non-array value assigned
fails:Array#[]= with [index, count] returns array if array assigned
fails:Array#[]= with [index, count] just sets the section defined by [start,length] to nil even if the rhs is nil
fails:Array#[]= with [index, count] just sets the section defined by [start,length] to nil if negative index within bounds, cnt > 0 and the rhs is nil
fails:Array#[]= with [index, count] replaces the section defined by [start,length] to other
fails:Array#[]= with [index, count] replaces the section to other if idx < 0 and cnt > 0
fails:Array#[]= with [index, count] replaces the section to other even if cnt spanning beyond the array boundary
fails:Array#[]= with [index, count] pads the Array with nils if the span is past the end
fails:Array#[]= with [index, count] inserts other section in place defined by idx
fails:Array#[]= with [index, count] raises an IndexError when passed start and negative length
fails:Array#[]= with [m..n] returns non-array value if non-array value assigned
fails:Array#[]= with [m..n] returns array if array assigned
fails:Array#[]= with [m..n] just sets the section defined by range to nil even if the rhs is nil
fails:Array#[]= with [m..n] just sets the section defined by range to nil if m and n < 0 and the rhs is nil
fails:Array#[]= with [m..n] replaces the section defined by range
fails:Array#[]= with [m..n] replaces the section if m and n < 0
fails:Array#[]= with [m..n] replaces the section if m < 0 and n > 0
fails:Array#[]= with [m..n] inserts the other section at m if m > n
109 changes: 84 additions & 25 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -339,6 +339,9 @@ public Object fallback(VirtualFrame frame, RubyArray array, RubyArray args) {
public abstract static class IndexSetNode extends ArrayCoreMethodNode {

@Child private ArrayWriteDenormalizedNode writeNode;
@Child protected ArrayReadSliceDenormalizedNode readSliceNode;
@Child private ConcatNode concatNode;
@Child private PopNode popNode;

private final BranchProfile tooSmallBranch = BranchProfile.create();

@@ -349,6 +352,9 @@ public IndexSetNode(RubyContext context, SourceSection sourceSection) {
public IndexSetNode(IndexSetNode prev) {
super(prev);
writeNode = prev.writeNode;
readSliceNode = prev.readSliceNode;
concatNode = prev.concatNode;
popNode = prev.popNode;
}

@Specialization
@@ -363,7 +369,7 @@ public Object set(VirtualFrame frame, RubyArray array, int index, Object value,

// Set a slice of the array to a particular value

@Specialization(guards = { "isObject", "!isRubyArray(arguments[3])", "!isUndefinedPlaceholder(arguments[3])" })
@Specialization(guards = { "!isRubyArray(arguments[3])", "!isUndefinedPlaceholder(arguments[3])" })
public Object setObject(VirtualFrame frame, RubyArray array, int start, int length, Object value) {
notDesignedForCompilation();

@@ -374,33 +380,63 @@ public Object setObject(VirtualFrame frame, RubyArray array, int start, int leng

final int begin = array.normalizeIndex(start);

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

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

int i = begin + 1;
for (Object obj : endValuesStore ) {
writeNode.executeWrite(frame, array, i, obj);
i += 1;
}
} else {
writeNode.executeWrite(frame, array, begin, value);
}
if (popNode == null) {
CompilerDirectives.transferToInterpreter();
popNode = insert(ArrayNodesFactory.PopNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{null,null}));
}
int popLength = length - 1 < array.getSize() ? length - 1 : array.getSize() - 1;
for(int i = 0; i < popLength; i++) { // TODO 3-15-2015 BF update when pop can pop multiple
popNode.executePop(array);
}
return value;
}
}

// Set a slice of the array to another array

@Specialization(guards = "isIntegerFixnum")
public Object setIntegerFixnum(VirtualFrame frame, RubyArray array, int start, int length, RubyArray value) {
@Specialization
public Object setOtherArray(VirtualFrame frame, RubyArray array, int start, int length, RubyArray value) {
notDesignedForCompilation();

if (length < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().indexNegativeLength(length, this));
}

final int begin = array.normalizeIndex(start);
if (value.getSize() == 0) {
final int begin = array.normalizeIndex(start);

final int exclusiveEnd = begin + length;
int[] store = (int[]) array.getStore();
Object[] store = ArrayUtils.box(array.getStore());

if (begin < 0) {
tooSmallBranch.enter();
@@ -416,27 +452,46 @@ public Object setIntegerFixnum(VirtualFrame frame, RubyArray array, int start, i

return value;
} else {
throw new UnsupportedOperationException();
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(ArrayWriteDenormalizedNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
Object[] values = ArrayUtils.box(value.getStore());
if (value.getSize() == length || (begin + length + 1) > array.getSize()) {
int i = begin;
for (Object obj : values) {
writeNode.executeWrite(frame, array, i, obj);
i += 1;
}
} else { // value.getSize() > length
if (readSliceNode == null) {
CompilerDirectives.transferToInterpreter();
readSliceNode = insert(ArrayReadSliceDenormalizedNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
RubyArray endValues = (RubyArray)readSliceNode.executeReadSlice(frame, array, (begin + length), (array.getSize() - begin - length));
if (concatNode == null) {
CompilerDirectives.transferToInterpreter();
concatNode = insert(ArrayNodesFactory.ConcatNodeFactory.create(getContext(), getSourceSection(), null, null));
}
int i = begin;
for (Object obj : values) {
writeNode.executeWrite(frame, array, i, obj);
i += 1;
}
concatNode.executeConcat(array, endValues);
}
return value;
}
}

@Specialization(guards = "isIntegerFixnum")
public Object setIntegerFixnumRange(VirtualFrame frame, RubyArray array, RubyRange.IntegerFixnumRange range, RubyArray other, UndefinedPlaceholder unused) {
if (range.doesExcludeEnd()) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException();
} else {
int normalizedBegin = array.normalizeIndex(range.getBegin());
int normalizedEnd = array.normalizeIndex(range.getEnd());

if (normalizedBegin == 0 && normalizedEnd == array.getSize() - 1) {
array.setStore(Arrays.copyOf((int[]) other.getStore(), other.getSize()), other.getSize());
} else {
throw new RuntimeException();
}
}
@Specialization(guards = "!isRubyArray(arguments[2])")
public Object setRange(VirtualFrame frame, RubyArray array, RubyRange.IntegerFixnumRange range, Object other, UndefinedPlaceholder unused) {
return setObject(frame, array, range.getBegin(), range.getLength(), other);
}

return other;
@Specialization
public Object setRangeArray(VirtualFrame frame, RubyArray array, RubyRange.IntegerFixnumRange range, RubyArray other, UndefinedPlaceholder unused) {
return setOtherArray(frame, array, range.getBegin(), range.getLength(), other);
}

}
@@ -603,6 +658,8 @@ public ConcatNode(ConcatNode prev) {
super(prev);
}

public abstract RubyArray executeConcat(RubyArray array, RubyArray other);

@CreateCast("other") public RubyNode coerceOtherToAry(RubyNode other) {
return ToAryNodeFactory.create(getContext(), getSourceSection(), other);
}
@@ -2297,6 +2354,8 @@ public PopNode(PopNode prev) {
super(prev);
}

public abstract Object executePop(RubyArray array);

@Specialization(guards = "isNull")
public Object popNil(RubyArray array) {
return nil();