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: 6bbfc011186d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e9d73a6b2b65
Choose a head ref
  • 3 commits
  • 1 file changed
  • 1 contributor

Commits on Jun 26, 2015

  1. Copy the full SHA
    36b1913 View commit details
  2. Copy the full SHA
    a16ff8f View commit details
  3. [Truffle] Fixed an array bounds check bug.

    A RubyArray's size and its store's length are not guaranteed to be the same.
    nirvdrum committed Jun 26, 2015
    Copy the full SHA
    e9d73a6 View commit details
Showing with 37 additions and 85 deletions.
  1. +37 −85 truffle/src/main/java/org/jruby/truffle/nodes/core/array/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayMirror;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
@@ -2096,50 +2097,50 @@ public Object injectEmptyArrayNoInitial(VirtualFrame frame, RubyArray array, Obj

@Specialization(guards = { "isIntArray(array)", "!isEmptyArray(array)", "wasProvided(initial)" })
public Object injectIntegerFixnum(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
return injectIntegerFixnumHelper(frame, array, initial, block, 0);
return injectHelper(frame, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)), array, initial, block, 0);
}

@Specialization(guards = { "isIntArray(array)", "!isEmptyArray(array)", "wasNotProvided(initial)" })
public Object injectIntegerFixnumNoInitial(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
final int[] store = (int[]) getStore(array);
final ArrayMirror mirror = ArrayMirror.reflect((int[]) ArrayNodes.getStore(array));

return injectIntegerFixnumHelper(frame, array, store[0], block, 1);
return injectHelper(frame, mirror, array, mirror.get(0), block, 1);
}

@Specialization(guards = { "isLongArray(array)", "!isEmptyArray(array)", "wasProvided(initial)" })
public Object injectLongFixnum(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
return injectLongFixnumHelper(frame, array, initial, block, 0);
return injectHelper(frame, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)), array, initial, block, 0);
}

@Specialization(guards = { "isLongArray(array)", "!isEmptyArray(array)", "wasNotProvided(initial)" })
public Object injectLongFixnumNoInitial(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
final long[] store = (long[]) getStore(array);
final ArrayMirror mirror = ArrayMirror.reflect((long[]) ArrayNodes.getStore(array));

return injectLongFixnumHelper(frame, array, store[0], block, 1);
return injectHelper(frame, mirror, array, mirror.get(0), block, 1);
}

@Specialization(guards = { "isDoubleArray(array)", "!isEmptyArray(array)", "wasProvided(initial)" })
public Object injectFloat(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
return injectFloatHelper(frame, array, initial, block, 0);
return injectHelper(frame, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)), array, initial, block, 0);
}

@Specialization(guards = { "isDoubleArray(array)", "!isEmptyArray(array)", "wasNotProvided(initial)" })
public Object injectFloatNoInitial(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
final double[] store = (double[]) getStore(array);
final ArrayMirror mirror = ArrayMirror.reflect((double[]) ArrayNodes.getStore(array));

return injectFloatHelper(frame, array, store[0], block, 1);
return injectHelper(frame, mirror, array, mirror.get(0), block, 1);
}

@Specialization(guards = { "isObjectArray(array)", "!isEmptyArray(array)", "wasProvided(initial)" })
public Object injectObject(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
return injectObjectHelper(frame, array, initial, block, 0);
return injectHelper(frame, ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array)), array, initial, block, 0);
}

@Specialization(guards = { "isObjectArray(array)", "!isEmptyArray(array)", "wasNotProvided(initial)" })
public Object injectObjectNoInitial(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) {
final Object[] store = (Object[]) getStore(array);
final ArrayMirror mirror = ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array));

return injectObjectHelper(frame, array, store[0], block, 1);
return injectHelper(frame, mirror, array, mirror.get(0), block, 1);
}

@Specialization(guards = { "isNullArray(array)", "wasProvided(initial)" })
@@ -2152,82 +2153,34 @@ public Object injectNullNoInitial(VirtualFrame frame, RubyArray array, Object in
return nil();
}

@Specialization(guards = "isRubySymbol(symbol)")
public Object inject(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
CompilerDirectives.transferToInterpreter();

final Object[] store = slowToArray(array);

if (store.length < 2) {
if (store.length == 1) {
return store[0];
} else {
return getContext().getCoreLibrary().getNilObject();
}
}

Object accumulator = dispatch.call(frame, store[0], symbol, null, store[1]);

for (int n = 2; n < getSize(array); n++) {
accumulator = dispatch.call(frame, accumulator, symbol, null, store[n]);
}

return accumulator;
@Specialization(guards = { "isRubySymbol(symbol)", "isEmptyArray(array)" })
public Object injectSymbolEmptyArray(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
return nil();
}

private Object injectIntegerFixnumHelper(VirtualFrame frame, RubyArray array, Object initial, RubyProc block, int startIndex) {
int count = 0;

final int[] store = (int[]) getStore(array);

Object accumulator = initial;

try {
for (int n = startIndex; n < getSize(array); n++) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

accumulator = yield(frame, block, accumulator, store[n]);
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}
}

return accumulator;
@Specialization(guards = { "isRubySymbol(symbol)", "isIntArray(array)", "!isEmptyArray(array)" })
public Object injectSymbolIntArray(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
return injectSymbolHelper(frame, ArrayMirror.reflect((int[]) ArrayNodes.getStore(array)), array, symbol);
}

private Object injectLongFixnumHelper(VirtualFrame frame, RubyArray array, Object initial, RubyProc block, int startIndex) {
int count = 0;

final long[] store = (long[]) getStore(array);

Object accumulator = initial;

try {
for (int n = startIndex; n < getSize(array); n++) {
if (CompilerDirectives.inInterpreter()) {
count++;
}
@Specialization(guards = { "isRubySymbol(symbol)", "isLongArray(array)", "!isEmptyArray(array)" })
public Object injectSymbolLongArray(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
return injectSymbolHelper(frame, ArrayMirror.reflect((long[]) ArrayNodes.getStore(array)), array, symbol);
}

accumulator = yield(frame, block, accumulator, store[n]);
}
} finally {
if (CompilerDirectives.inInterpreter()) {
getRootNode().reportLoopCount(count);
}
}
@Specialization(guards = { "isRubySymbol(symbol)", "isDoubleArray(array)", "!isEmptyArray(array)" })
public Object injectSymbolDoubleArray(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
return injectSymbolHelper(frame, ArrayMirror.reflect((double[]) ArrayNodes.getStore(array)), array, symbol);
}

return accumulator;
@Specialization(guards = { "isRubySymbol(symbol)", "isObjectArray(array)", "!isEmptyArray(array)" })
public Object injectSymbolObjectArray(VirtualFrame frame, RubyArray array, RubyBasicObject symbol, NotProvided block) {
return injectSymbolHelper(frame, ArrayMirror.reflect((Object[]) ArrayNodes.getStore(array)), array, symbol);
}

private Object injectFloatHelper(VirtualFrame frame, RubyArray array, Object initial, RubyProc block, int startIndex) {
private Object injectHelper(VirtualFrame frame, ArrayMirror mirror, RubyArray array, Object initial, RubyProc block, int startIndex) {
int count = 0;

final double[] store = (double[]) getStore(array);

Object accumulator = initial;

try {
@@ -2236,7 +2189,7 @@ private Object injectFloatHelper(VirtualFrame frame, RubyArray array, Object ini
count++;
}

accumulator = yield(frame, block, accumulator, store[n]);
accumulator = yield(frame, block, accumulator, mirror.get(n));
}
} finally {
if (CompilerDirectives.inInterpreter()) {
@@ -2247,20 +2200,19 @@ private Object injectFloatHelper(VirtualFrame frame, RubyArray array, Object ini
return accumulator;
}

private Object injectObjectHelper(VirtualFrame frame, RubyArray array, Object initial, RubyProc block, int startIndex) {
int count = 0;

final Object[] store = (Object[]) getStore(array);
private Object injectSymbolHelper(VirtualFrame frame, ArrayMirror mirror, RubyArray array, RubyBasicObject symbol) {
int count = 0;

Object accumulator = initial;
Object accumulator = mirror.get(0);

try {
for (int n = startIndex; n < getSize(array); n++) {
for (int n = 1; n < getSize(array); n++) {
if (CompilerDirectives.inInterpreter()) {
count++;
}

accumulator = yield(frame, block, accumulator, store[n]);
accumulator = dispatch.call(frame, accumulator, symbol, null, mirror.get(n));
}
} finally {
if (CompilerDirectives.inInterpreter()) {