Skip to content

Commit

Permalink
[Truffle] Work on Enumerable specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Mar 14, 2015
1 parent 143279b commit 96317c8
Show file tree
Hide file tree
Showing 14 changed files with 197 additions and 132 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/collect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/detect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/each_entry_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/entries_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/find_all_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/find_index_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/find_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/map_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/select_tags.txt

This file was deleted.

4 changes: 0 additions & 4 deletions spec/truffle/tags/core/enumerable/sort_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/to_a_tags.txt

This file was deleted.

255 changes: 137 additions & 118 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Expand Up @@ -1017,6 +1017,117 @@ public RubyArray eachWithEmpty(VirtualFrame frame, RubyArray array, RubyProc blo
return array;
}

@Specialization(guards = "isIntegerFixnum")
public Object eachWithIndexInt(VirtualFrame frame, RubyArray array, RubyProc block) {
final int[] store = (int[]) array.getStore();

int count = 0;

try {
outer:
for (int n = 0; n < array.getSize(); n++) {
while (true) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
} catch (RedoException e) {
redoProfile.enter();
}
}
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}
}

return array;
}

@Specialization(guards = "isLongFixnum")
public Object eachWithIndexLong(VirtualFrame frame, RubyArray array, RubyProc block) {
final long[] store = (long[]) array.getStore();

int count = 0;

try {
outer:
for (int n = 0; n < array.getSize(); n++) {
while (true) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
} catch (RedoException e) {
redoProfile.enter();
}
}
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}
}

return array;
}

@Specialization(guards = "isFloat")
public Object eachWithIndexDouble(VirtualFrame frame, RubyArray array, RubyProc block) {
final double[] store = (double[]) array.getStore();

int count = 0;

try {
outer:
for (int n = 0; n < array.getSize(); n++) {
while (true) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

try {
yield(frame, block, store[n], n);
continue outer;
} catch (BreakException e) {
breakProfile.enter();
return e.getResult();
} catch (NextException e) {
nextProfile.enter();
continue outer;
} catch (RedoException e) {
redoProfile.enter();
}
}
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}
}

return array;
}

@Specialization(guards = "isObject")
public Object eachWithIndexObject(VirtualFrame frame, RubyArray array, RubyProc block) {
final Object[] store = (Object[]) array.getStore();
Expand Down Expand Up @@ -1054,6 +1165,11 @@ public Object eachWithIndexObject(VirtualFrame frame, RubyArray array, RubyProc
return array;
}

@Specialization
public Object eachWithIndexObject(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
return ruby(frame, "to_enum(:each_with_index)");
}

}

@CoreMethod(names = "include?", required = 1)
Expand Down Expand Up @@ -2878,9 +2994,7 @@ public SortNode(SortNode prev) {
}

@Specialization(guards = "isNull")
public RubyArray sortNull(RubyArray array, UndefinedPlaceholder block) {
notDesignedForCompilation();

public RubyArray sortNull(RubyArray array, Object block) {
return new RubyArray(getContext().getCoreLibrary().getArrayClass());
}

Expand All @@ -2898,7 +3012,7 @@ public RubyArray sortVeryShortIntegerFixnum(VirtualFrame frame, RubyArray array,
if (i < size) {
for (int j = i + 1; j < RubyArray.ARRAYS_SMALL; j++) {
if (j < size) {
if ((int) compareDispatchNode.call(frame, store[j], "<=>", null, store[i]) < 0) {
if (castSortValue(compareDispatchNode.call(frame, store[j], "<=>", null, store[i])) < 0) {
final int temp = store[j];
store[j] = store[i];
store[i] = temp;
Expand All @@ -2912,16 +3026,6 @@ public RubyArray sortVeryShortIntegerFixnum(VirtualFrame frame, RubyArray array,
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), newStore, size);
}

@Specialization(guards = "isIntegerFixnum")
public RubyArray sortIntegerFixnum(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
notDesignedForCompilation();

final Object[] boxed = ArrayUtils.box((int[]) array.getStore());
sort(frame, boxed);
final int[] unboxed = ArrayUtils.unboxInteger(boxed, array.getSize());
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), unboxed, array.getSize());
}

@ExplodeLoop
@Specialization(guards = {"isLongFixnum", "isSmall"})
public RubyArray sortVeryShortLongFixnum(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
Expand All @@ -2936,7 +3040,7 @@ public RubyArray sortVeryShortLongFixnum(VirtualFrame frame, RubyArray array, Un
if (i < size) {
for (int j = i + 1; j < RubyArray.ARRAYS_SMALL; j++) {
if (j < size) {
if ((int) compareDispatchNode.call(frame, store[j], "<=>", null, store[i]) < 0) {
if (castSortValue(compareDispatchNode.call(frame, store[j], "<=>", null, store[i])) < 0) {
final long temp = store[j];
store[j] = store[i];
store[i] = temp;
Expand All @@ -2950,26 +3054,6 @@ public RubyArray sortVeryShortLongFixnum(VirtualFrame frame, RubyArray array, Un
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), newStore, size);
}

@Specialization(guards = "isLongFixnum")
public RubyArray sortLongFixnum(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
notDesignedForCompilation();

final Object[] boxed = ArrayUtils.box((long[]) array.getStore());
sort(frame, boxed);
final long[] unboxed = ArrayUtils.unboxLong(boxed, array.getSize());
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), unboxed, array.getSize());
}

@Specialization(guards = "isFloat")
public RubyArray sortDouble(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
notDesignedForCompilation();

final Object[] boxed = ArrayUtils.box((double[]) array.getStore());
sort(frame, boxed);
final double[] unboxed = ArrayUtils.unboxDouble(boxed, array.getSize());
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), unboxed, array.getSize());
}

@Specialization(guards = {"isObject", "isSmall"})
public RubyArray sortVeryShortObject(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
final Object[] oldStore = (Object[]) array.getStore();
Expand All @@ -2983,7 +3067,7 @@ public RubyArray sortVeryShortObject(VirtualFrame frame, RubyArray array, Undefi
final Object x = store[i];
int j = i;
// TODO(CS): node for this cast
while (j > 0 && (int) compareDispatchNode.call(frame, store[j - 1], "<=>", null, x) > 0) {
while (j > 0 && castSortValue(compareDispatchNode.call(frame, store[j - 1], "<=>", null, x)) > 0) {
store[j] = store[j - 1];
j--;
}
Expand All @@ -2993,51 +3077,29 @@ public RubyArray sortVeryShortObject(VirtualFrame frame, RubyArray array, Undefi
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store, size);
}

@Specialization(guards = "isObject")
public RubyArray sortObject(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
notDesignedForCompilation();

final Object[] store = Arrays.copyOf((Object[]) array.getStore(), array.getSize());
sort(frame, store);
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store, array.getSize());
}

@Specialization(guards = "isObject")
public RubyArray sortWithCompareBlock(VirtualFrame frame, RubyArray array, RubyProc block) {
notDesignedForCompilation();

final Object[] store = Arrays.copyOf((Object[]) array.getStore(), array.getSize());
sort(frame, store, block);
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store, array.getSize());
@Specialization
public Object sortUsingRubinius(VirtualFrame frame, RubyArray array, RubyProc block) {
return sortUsingRubinius(frame, array, (Object) block);
}

private <T> void sort(VirtualFrame frame, T[] objects) {
final VirtualFrame finalFrame = frame;

Arrays.sort(objects, new Comparator<Object>() {

@Override
public int compare(Object a, Object b) {
// TODO(CS): node for this cast
return (int) compareDispatchNode.call(finalFrame, a, "<=>", null, b);
}

});
@Specialization(guards = {"!isNull", "!isSmall"})
public Object sortUsingRubinius(VirtualFrame frame, RubyArray array, Object block) {
if (block == UndefinedPlaceholder.INSTANCE) {
return ruby(frame, "sorted = dup; Rubinius.privately { sorted.isort!(0, right) }; sorted", "right", array.getSize());
} else {
return ruby(frame, "sorted = dup; Rubinius.privately { sorted.isort_block!(0, right, block) }; sorted", "right", array.getSize(), "block", block);
}
}

private <T> void sort(VirtualFrame frame, T[] objects, RubyProc compare) {
final VirtualFrame finalFrame = frame;
final RubyProc finalCompare = compare;

Arrays.sort(objects, new Comparator<Object>() {
private int castSortValue(Object value) {
if (value instanceof Integer) {
return (int) value;
}

@Override
public int compare(Object a, Object b) {
// TODO(CS): node for this cast
return (int) yieldNode.dispatch(finalFrame, finalCompare, a, b);
}
CompilerDirectives.transferToInterpreter();

});
// TODO CS 14-Mar-15 - what's the error message here?
throw new RaiseException(getContext().getCoreLibrary().argumentError("expecting a Fixnum to sort", this));
}

protected static boolean isSmall(RubyArray array) {
Expand All @@ -3046,49 +3108,6 @@ protected static boolean isSmall(RubyArray array) {

}

@CoreMethod(names = "sort!", raiseIfFrozenSelf = true)
public abstract static class SortBangNode extends ArrayCoreMethodNode {

@Child private CallDispatchHeadNode compareDispatchNode;

public SortBangNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
compareDispatchNode = DispatchHeadNodeFactory.createMethodCall(context);
}

public SortBangNode(SortBangNode prev) {
super(prev);
compareDispatchNode = prev.compareDispatchNode;
}

@Specialization
public RubyArray sort(VirtualFrame frame, RubyArray array) {
notDesignedForCompilation();

final Object[] store = array.slowToArray();
sort(frame, store);
array.setStore(store, array.getSize());
return array;
}

// TODO(CS): copied from #sort

private <T> void sort(VirtualFrame frame, T[] objects) {
final VirtualFrame finalFrame = frame;

Arrays.sort(objects, new Comparator<Object>() {

@Override
public int compare(Object a, Object b) {
// TODO(CS): node for this cast
return (int) compareDispatchNode.call(finalFrame, a, "<=>", null, b);
}

});
}

}

@CoreMethod(names = "uniq")
public abstract static class UniqNode extends CoreMethodNode {

Expand Down
4 changes: 4 additions & 0 deletions truffle/src/main/ruby/core/array.rb
Expand Up @@ -45,4 +45,8 @@ def element_reference_fallback(method_name, args)
end
end

def sort!(&block)
replace sort(&block)
end

end

0 comments on commit 96317c8

Please sign in to comment.