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: bd7e5b07d7b8
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 59b1a74c4139
Choose a head ref
  • 5 commits
  • 18 files changed
  • 1 contributor

Commits on Mar 14, 2015

  1. Copy the full SHA
    96317c8 View commit details

Commits on Mar 15, 2015

  1. Copy the full SHA
    0cb21b2 View commit details
  2. Merge branch 'master' into truffle-head

    Conflicts:
    	truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
    chrisseaton committed Mar 15, 2015
    Copy the full SHA
    94c0b88 View commit details
  3. Copy the full SHA
    c5f856b View commit details
  4. Copy the full SHA
    59b1a74 View commit details
11 changes: 0 additions & 11 deletions spec/truffle/tags/core/array/sort_tags.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,2 @@
fails:Array#sort may take a block which is used to determine the order of objects a and b described as -1, 0 or +1
fails:Array#sort raises an error when a given block returns nil
fails:Array#sort completes when supplied a block that always returns the same result
fails:Array#sort does not freezes self during being sorted
fails:Array#sort returns the specified value when it would break in the given block
fails:Array#sort uses the sign of Bignum block results as the sort result
fails:Array#sort compares values returned by block with 0
fails:Array#sort raises an error if objects can't be compared
fails:Array#sort! sorts array in place using block value if a block given
fails:Array#sort! does not call #<=> on contained objects when invoked with a block
fails:Array#sort! does not call #<=> on elements when invoked with a block even if Array is large (Rubinius #412)
fails:Array#sort! returns the specified value when it would break in the given block
fails:Array#sort! makes some modification even if finished sorting when it would break in the given block
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.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/kernel/extend_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
fails:Kernel#extend requires multiple arguments
fails:Kernel#extend calls extend_object on argument
fails:Kernel#extend calls extended on argument
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/kernel/freeze_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/kernel/method_tags.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
fails:Kernel#method returns a method object if we repond_to_missing? method
fails:Kernel#method raises a NameError for an invalid method name
fails:Kernel#method raises a NameError for an invalid singleton method name
fails:Kernel#method changes the method called for super on a target aliased method
fails:Kernel#method will see an alias of the original method as == when in a derived class
fails:Kernel#method can be called even if we only repond_to_missing? method, true
255 changes: 137 additions & 118 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -1019,6 +1019,117 @@ public RubyArray eachWithEmpty(VirtualFrame frame, RubyArray array, RubyProc blo
return array;
}

@Specialization(guards = "isIntegerFixnum(array)")
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(array)")
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(array)")
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(array)")
public Object eachWithIndexObject(VirtualFrame frame, RubyArray array, RubyProc block) {
final Object[] store = (Object[]) array.getStore();
@@ -1056,6 +1167,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)
@@ -2882,9 +2998,7 @@ public SortNode(SortNode prev) {
}

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

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

@@ -2902,7 +3016,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;
@@ -2916,16 +3030,6 @@ public RubyArray sortVeryShortIntegerFixnum(VirtualFrame frame, RubyArray array,
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), newStore, size);
}

@Specialization(guards = "isIntegerFixnum(array)")
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(array)", "isSmall(array)"})
public RubyArray sortVeryShortLongFixnum(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
@@ -2940,7 +3044,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;
@@ -2954,26 +3058,6 @@ public RubyArray sortVeryShortLongFixnum(VirtualFrame frame, RubyArray array, Un
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), newStore, size);
}

@Specialization(guards = "isLongFixnum(array)")
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(array)")
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(array)", "isSmall(array)"})
public RubyArray sortVeryShortObject(VirtualFrame frame, RubyArray array, UndefinedPlaceholder block) {
final Object[] oldStore = (Object[]) array.getStore();
@@ -2987,7 +3071,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--;
}
@@ -2997,51 +3081,29 @@ public RubyArray sortVeryShortObject(VirtualFrame frame, RubyArray array, Undefi
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store, size);
}

@Specialization(guards = "isObject(array)")
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(array)")
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(array)", "!isSmall(array)"})
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) {
@@ -3050,49 +3112,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 {

4 changes: 4 additions & 0 deletions truffle/src/main/ruby/core/array.rb
Original file line number Diff line number Diff line change
@@ -45,4 +45,8 @@ def element_reference_fallback(method_name, args)
end
end

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

end
56 changes: 56 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/array.rb
Original file line number Diff line number Diff line change
@@ -905,4 +905,60 @@ def transpose
out
end

# Insertion sort in-place between the given indexes.
def isort!(left, right)
i = left + 1

tup = @tuple

while i < right
j = i

while j > left
jp = j - 1
el1 = tup.at(jp)
el2 = tup.at(j)

unless cmp = (el1 <=> el2)
raise ArgumentError, "comparison of #{el1.inspect} with #{el2.inspect} failed (#{j})"
end

break unless cmp > 0

tup.put(j, el1)
tup.put(jp, el2)

j = jp
end

i += 1
end
end
private :isort!

# Insertion sort in-place between the given indexes using a block.
def isort_block!(left, right, block)
i = left + 1

while i < right
j = i

while j > left
block_result = block.call(@tuple.at(j - 1), @tuple.at(j))

if block_result.nil?
raise ArgumentError, 'block returned nil'
elsif block_result > 0
@tuple.swap(j, (j - 1))
j -= 1
else
break
end
end

i += 1
end
end
private :isort_block!

end