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

Commits on Jan 29, 2016

  1. Copy the full SHA
    b586607 View commit details
  2. Copy the full SHA
    ddbd199 View commit details
  3. prefer runtime passed to safeArray helpers + size should not change d…

    …uring select
    
    some more related cleanup - use context.nil and avoid getRuntime() when possible
    kares committed Jan 29, 2016
    Copy the full SHA
    4239838 View commit details
  4. Copy the full SHA
    13bc118 View commit details
  5. clear up left over refs on select!/reject! (will avoid leaks - gets T…

    …estRubyArray green)
    kares committed Jan 29, 2016
    Copy the full SHA
    9dd0df9 View commit details
Showing with 153 additions and 136 deletions.
  1. +132 −115 core/src/main/java/org/jruby/RubyArray.java
  2. +5 −6 core/src/test/java/org/jruby/test/TestRubyArray.java
  3. +16 −15 spec/regression/GH-1371_gzip_spec.rb
247 changes: 132 additions & 115 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -120,11 +120,14 @@ public ClassIndex getNativeClassIndex() {
}

private final void concurrentModification() {
concurrentModification(getRuntime());
concurrentModification(getRuntime(), null);
}

private static void concurrentModification(Ruby runtime) {
throw runtime.newConcurrencyError("Detected invalid array contents due to unsynchronized modifications with concurrent users");
private static void concurrentModification(Ruby runtime, Exception cause) {
RuntimeException ex = runtime.newConcurrencyError("Detected invalid array contents due to unsynchronized modifications with concurrent users");
// NOTE: probably not useful to be on except for debugging :
// if ( cause != null ) ex.initCause(cause);
throw ex;
}

/** rb_ary_s_create
@@ -574,8 +577,8 @@ private IRubyObject initializeCommon(ThreadContext context, IRubyObject arg0, IR
} else {
fill(values, begin, begin + ilen, arg1);
}
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
}
realLength = ilen;
}
@@ -641,8 +644,9 @@ public boolean includes(ThreadContext context, IRubyObject item) {
int myBegin = this.begin;
int end = myBegin + realLength;
IRubyObject[] values = this.values;
final Ruby runtime = context.runtime;
for (int i = myBegin; i < end; i++) {
final IRubyObject value = safeArrayRef(values, i);
final IRubyObject value = safeArrayRef(runtime, values, i);
if (equalInternal(context, value, item)) return true;
}

@@ -661,20 +665,21 @@ public RubyFixnum hash(ThreadContext context) {
*/
@JRubyMethod(name = "hash")
public RubyFixnum hash19(final ThreadContext context) {
return (RubyFixnum) getRuntime().execRecursiveOuter(new Ruby.RecursiveFunction() {
return (RubyFixnum) context.runtime.execRecursiveOuter(new Ruby.RecursiveFunction() {
public IRubyObject call(IRubyObject obj, boolean recur) {
final Ruby runtime = context.runtime;
int begin = RubyArray.this.begin;
long h = realLength;
if (recur) {
h ^= RubyNumeric.num2long(invokedynamic(context, context.runtime.getArray(), HASH));
h ^= RubyNumeric.num2long(invokedynamic(context, runtime.getArray(), HASH));
} else {
for (int i = begin; i < begin + realLength; i++) {
h = (h << 1) | (h < 0 ? 1 : 0);
final IRubyObject value = safeArrayRef(values, i);
final IRubyObject value = safeArrayRef(runtime, values, i);
h ^= RubyNumeric.num2long(invokedynamic(context, value, HASH));
}
}
return getRuntime().newFixnum(h);
return runtime.newFixnum(h);
}
}, RubyArray.this);
}
@@ -683,7 +688,9 @@ public IRubyObject call(IRubyObject obj, boolean recur) {
*
*/
public final IRubyObject store(long index, IRubyObject value) {
if (index < 0 && (index += realLength) < 0) throw getRuntime().newIndexError("index " + (index - realLength) + " out of array");
if (index < 0 && (index += realLength) < 0) {
throw getRuntime().newIndexError("index " + (index - realLength) + " out of array");
}

modify();

@@ -769,18 +776,20 @@ public IRubyObject fetch(ThreadContext context, IRubyObject arg0, Block block) {
if (index < 0) index += realLength;
if (index < 0 || index >= realLength) {
if (block.isGiven()) return block.yield(context, arg0);
throw getRuntime().newIndexError("index " + index + " out of array");
throw context.runtime.newIndexError("index " + index + " out of array");
}

return safeArrayRef(values, begin + (int) index);
return safeArrayRef(context.runtime, values, begin + (int) index);
}

/** rb_ary_fetch
*
*/
@JRubyMethod
public IRubyObject fetch(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
if (block.isGiven()) getRuntime().getWarnings().warn(ID.BLOCK_BEATS_DEFAULT_VALUE, "block supersedes default value argument");
if (block.isGiven()) {
context.runtime.getWarnings().warn(ID.BLOCK_BEATS_DEFAULT_VALUE, "block supersedes default value argument");
}

long index = RubyNumeric.num2long(arg0);

@@ -790,7 +799,7 @@ public IRubyObject fetch(ThreadContext context, IRubyObject arg0, IRubyObject ar
return arg1;
}

return safeArrayRef(values, begin + (int) index);
return safeArrayRef(context.runtime, values, begin + (int) index);
}

/** rb_ary_to_ary
@@ -1141,13 +1150,13 @@ public RubyArray push_m19(IRubyObject[] items) {
public IRubyObject pop(ThreadContext context) {
modifyCheck();

if (realLength == 0) return context.runtime.getNil();
if (realLength == 0) return context.nil;

if (isShared) {
return safeArrayRef(values, begin + --realLength);
return safeArrayRef(context.runtime, values, begin + --realLength);
} else {
int index = begin + --realLength;
return safeArrayRefSet(values, index, context.runtime.getNil());
return safeArrayRefSet(context.runtime, values, index, context.nil);
}
}

@@ -1165,10 +1174,10 @@ public IRubyObject pop(ThreadContext context, IRubyObject num) {
@JRubyMethod(name = "shift")
public IRubyObject shift(ThreadContext context) {
modifyCheck();
Ruby runtime = context.runtime;
if (realLength == 0) return runtime.getNil();

final IRubyObject obj = safeArrayRefCondSet(values, begin, !isShared, runtime.getNil());
if (realLength == 0) return context.nil;

final IRubyObject obj = safeArrayRefCondSet(context.runtime, values, begin, !isShared, context.nil);
begin++;
realLength--;
return obj;
@@ -1423,15 +1432,16 @@ public RubyArray concat19(IRubyObject obj) {
*
*/
private IRubyObject inspectAry(ThreadContext context) {
Encoding encoding = context.runtime.getDefaultInternalEncoding();
final Ruby runtime = context.runtime;
Encoding encoding = runtime.getDefaultInternalEncoding();
if (encoding == null) encoding = USASCIIEncoding.INSTANCE;
RubyString str = RubyString.newStringLight(context.runtime, DEFAULT_INSPECT_STR_SIZE, encoding);
RubyString str = RubyString.newStringLight(runtime, DEFAULT_INSPECT_STR_SIZE, encoding);
str.cat((byte)'[');
boolean tainted = isTaint();

for (int i = 0; i < realLength; i++) {

RubyString s = inspect(context, safeArrayRef(values, begin + i));
RubyString s = inspect(context, safeArrayRef(runtime, values, begin + i));
if (s.isTaint()) tainted = true;
if (i > 0) str.cat(',', encoding).cat(' ', encoding);
else str.setEncoding(s.getEncoding());
@@ -1552,7 +1562,7 @@ public IRubyObject each(ThreadContext context, Block block) {
for (int i = 0; i < realLength; i++) {
// do not coarsen the "safe" catch, since it will misinterpret AIOOBE from the yielded code.
// See JRUBY-5434
block.yield(context, safeArrayRef(values, begin + i));
block.yield(context, safeArrayRef(context.runtime, values, begin + i));
}
return this;
}
@@ -1626,7 +1636,7 @@ public IRubyObject reverseEach(ThreadContext context, Block block) {
while(len-- > 0) {
// do not coarsen the "safe" catch, since it will misinterpret AIOOBE from the yielded code.
// See JRUBY-5434
block.yield(context, safeArrayRef(values, begin + len));
block.yield(context, safeArrayRef(context.runtime, values, begin + len));
if (realLength < len) len = realLength;
}

@@ -1694,7 +1704,7 @@ private RubyString joinAny(ThreadContext context, IRubyObject obj, RubyString se
for (; i < begin + realLength; i++) {
if (i > begin && sep != null) result.append19(sep);

IRubyObject val = safeArrayRef(values, i);
IRubyObject val = safeArrayRef(context.runtime, values, i);

if (val instanceof RubyString) {
result.append19(val);
@@ -1757,7 +1767,7 @@ public IRubyObject join19(final ThreadContext context, IRubyObject sep) {
}

for (int i = begin; i < begin + realLength; i++) {
IRubyObject val = safeArrayRef(values, i);
IRubyObject val = safeArrayRef(runtime, values, i);
IRubyObject tmp = val.checkStringType19();
if (tmp.isNil() || tmp != val) {
len += ((begin + realLength) - i) * 10;
@@ -2041,8 +2051,8 @@ private IRubyObject fillCommon(ThreadContext context, int beg, long len, IRubyOb
if (len > 0) {
try {
fill(values, begin + beg, begin + end, item);
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}
}

@@ -2055,7 +2065,7 @@ private IRubyObject fillCommon(ThreadContext context, int beg, long len, Block b
// See [ruby-core:17483]
if (len < 0) return this;

if (len > Integer.MAX_VALUE - beg) throw getRuntime().newArgumentError("argument too big");
if (len > Integer.MAX_VALUE - beg) throw context.runtime.newArgumentError("argument too big");

int end = (int)(beg + len);
if (end > realLength) {
@@ -2064,11 +2074,11 @@ private IRubyObject fillCommon(ThreadContext context, int beg, long len, Block b
realLength = end;
}

Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
for (int i = beg; i < end; i++) {
IRubyObject v = block.yield(context, runtime.newFixnum(i));
if (i >= realLength) break;
safeArraySet(values, begin + i, v);
safeArraySet(runtime, values, begin + i, v);
}
return this;
}
@@ -2290,7 +2300,7 @@ private RubyArray safeReverse() {
*
*/
public IRubyObject collect(ThreadContext context, Block block) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
if (!block.isGiven()) return new RubyArray(runtime, runtime.getArray(), this);

IRubyObject[] arr = new IRubyObject[realLength];
@@ -2299,7 +2309,7 @@ public IRubyObject collect(ThreadContext context, Block block) {
for (i = 0; i < realLength; i++) {
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from the yield
// See JRUBY-5434
arr[i] = block.yield(context, safeArrayRef(values, i + begin));
arr[i] = block.yield(context, safeArrayRef(runtime, values, i + begin));
}

// use iteration count as new size in case something was deleted along the way
@@ -2326,7 +2336,7 @@ public RubyArray collectBang(ThreadContext context, Block block) {
for (int i = 0, len = realLength; i < len; i++) {
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from the yield
// See JRUBY-5434
store(i, block.yield(context, safeArrayRef(values, begin + i)));
store(i, block.yield(context, safeArrayRef(context.runtime, values, begin + i)));
}

return this;
@@ -2352,13 +2362,13 @@ public IRubyObject map_bang(ThreadContext context, Block block) {
*
*/
public IRubyObject selectCommon(ThreadContext context, Block block) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
RubyArray result = new RubyArray(runtime, realLength);

for (int i = 0; i < realLength; i++) {
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from the yield
// See JRUBY-5434
IRubyObject value = safeArrayRef(values, begin + i);
IRubyObject value = safeArrayRef(runtime, values, begin + i);

if (block.yield(context, value).isTrue()) result.append(value);
}
@@ -2374,31 +2384,31 @@ public IRubyObject select(ThreadContext context, Block block) {

@JRubyMethod(name = "select!")
public IRubyObject select_bang(ThreadContext context, Block block) {
Ruby runtime = context.runtime;
if (!block.isGiven()) return enumeratorizeWithSize(context, this, "select!", enumLengthFn());

modify();

int i1, i2, len0, len1;

len0 = len1 = 0;
final Ruby runtime = context.runtime;
final int len = realLength; final int beg = begin;

int len0 = 0, len1 = 0;
try {
for (i1 = i2 = 0; i1 < size(); len0 = ++i1) {
int i1, i2;
for (i1 = i2 = 0; i1 < len; len0 = ++i1) {
final IRubyObject[] values = this.values;
// Do not coarsen the "safe" check, since it will misinterpret
// AIOOBE from the yield (see JRUBY-5434)
IRubyObject value = safeArrayRef(values, begin + i1);
IRubyObject value = safeArrayRef(runtime, values, begin + i1);

if (!block.yield(context, value).isTrue()) continue;

if (i1 != i2) {
store(i2, value);
}
if (i1 != i2) safeArraySet(runtime, values, beg + i2, value);
len1 = ++i2;
}
return (i1 == i2) ? context.nil : this;
} finally {
selectBangEnsure(len0, len1);
}
finally {
selectBangEnsure(runtime, len, beg, len0, len1);
}
}

@@ -2419,11 +2429,11 @@ public IRubyObject delete(ThreadContext context, IRubyObject item, Block block)
int i2 = 0;
IRubyObject value = item;

Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
for (int i1 = 0; i1 < realLength; i1++) {
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from equalInternal
// See JRUBY-5434
IRubyObject e = safeArrayRef(values, begin + i1);
IRubyObject e = safeArrayRef(runtime, values, begin + i1);
if (equalInternal(context, e, item)) {
value = e;
continue;
@@ -2435,7 +2445,7 @@ public IRubyObject delete(ThreadContext context, IRubyObject item, Block block)
if (realLength == i2) {
if (block.isGiven()) return block.yield(context, item);

return runtime.getNil();
return context.nil;
}

modify();
@@ -2450,8 +2460,8 @@ public IRubyObject delete(ThreadContext context, IRubyObject item, Block block)
int valuesLength = myValues.length - myBegin;
if (i2 << 1 < valuesLength && valuesLength > ARRAY_DEFAULT_SIZE) realloc(i2 << 1, valuesLength);
}
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}

return value;
@@ -2504,9 +2514,9 @@ public IRubyObject delete_at(IRubyObject obj) {
/** rb_ary_reject_bang
*
*/
public IRubyObject rejectCommon(ThreadContext context, Block block) {
public final IRubyObject rejectCommon(ThreadContext context, Block block) {
RubyArray ary = aryDup();
ary.reject_bang(context, block);
ary.rejectBang(context, block);
return ary;
}

@@ -2519,38 +2529,47 @@ public IRubyObject reject(ThreadContext context, Block block) {
public IRubyObject rejectBang(ThreadContext context, Block block) {
modify();

int i1, i2, len0, len1;

len0 = len1 = 0;
final Ruby runtime = context.runtime;
final int len = realLength; final int beg = begin;

int len0 = 0, len1 = 0;
try {
for (i1 = i2 = 0; i1 < realLength; len0 = ++i1) {
int i1, i2;
for (i1 = i2 = 0; i1 < len; len0 = ++i1) {
final IRubyObject[] values = this.values;
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from the yield
// See JRUBY-5434
IRubyObject v = safeArrayRef(values, begin + i1);
if (block.yield(context, v).isTrue()) continue;
if (i1 != i2) {
store(i2, v);
}
IRubyObject value = safeArrayRef(runtime, values, beg + i1);

if (block.yield(context, value).isTrue()) continue;

if (i1 != i2) safeArraySet(runtime, values, beg + i2, value);
len1 = ++i2;
}

return (i1 == i2) ? context.nil : this;
} finally {
selectBangEnsure(len0, len1);
}
finally {
selectBangEnsure(runtime, len, beg, len0, len1);
}
}

// MRI: select_bang_ensure
private void selectBangEnsure(int len0, int len1) {
int len = size();
int i1 = len0, i2 = len1;

private void selectBangEnsure(final Ruby runtime, final int len, final int beg,
int i1, int i2) {
if (i2 < i1) {
realLength = len - i1 + i2;
if (i1 < len) {
System.arraycopy(values, begin + i1, values, begin + i2, len - i1);
safeArrayCopy(runtime, values, beg + i1, values, beg + i2, len - i1);
}
else if (realLength > 0) {
// nil out left-overs to avoid leaks (MRI doesn't)
try {
Helpers.fillNil(values, beg + i2, beg + i1, runtime);
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
}
}
realLength = len - i1 + i2;
}
}

@@ -2563,7 +2582,7 @@ public IRubyObject reject_bang(ThreadContext context, Block block) {
*
*/
public IRubyObject deleteIf(ThreadContext context, Block block) {
reject_bang(context, block);
rejectBang(context, block);
return this;
}

@@ -2619,14 +2638,14 @@ public static interface ArgumentVisitor {
}

private IRubyObject zipCommon(ThreadContext context, IRubyObject[] args, Block block, ArgumentVisitor visitor) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;

if (block.isGiven()) {
for (int i = 0; i < realLength; i++) {
IRubyObject[] tmp = new IRubyObject[args.length + 1];
// Do not coarsen the "safe" check, since it will misinterpret AIOOBE from the yield
// See JRUBY-5434
tmp[0] = safeArrayRef(values, begin + i);
tmp[0] = safeArrayRef(runtime, values, begin + i);
for (int j = 0; j < args.length; j++) {
tmp[j + 1] = visitor.visit(context, args[j], i);
}
@@ -2645,8 +2664,8 @@ private IRubyObject zipCommon(ThreadContext context, IRubyObject[] args, Block b
}
result[i] = newArrayNoCopyLight(runtime, tmp);
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}
return newArrayNoCopy(runtime, result);
}
@@ -2845,15 +2864,13 @@ private boolean flatten(ThreadContext context, final int level, final RubyArray
ary = (RubyArray) stack.pop(context);
}
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification();
concurrentModification(context.runtime, ex);
}
return modified;
}

public IRubyObject flatten_bang(ThreadContext context) {
Ruby runtime = context.runtime;

RubyArray result = new RubyArray(runtime, getMetaClass(), realLength);
RubyArray result = new RubyArray(context.runtime, getMetaClass(), realLength);
if (flatten(context, -1, result)) {
modifyCheck();
isShared = false;
@@ -2862,7 +2879,7 @@ public IRubyObject flatten_bang(ThreadContext context) {
values = result.values;
return this;
}
return runtime.getNil();
return context.nil;
}

@JRubyMethod(name = "flatten!")
@@ -3106,8 +3123,8 @@ public IRubyObject uniq(ThreadContext context) {
IRubyObject v = elt(i);
if (hash.fastDelete(v)) result.values[j++] = v;
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}
result.realLength = j;
return result;
@@ -3242,8 +3259,8 @@ public int compare(Object o1, Object o2) {
return compareOthers(context, (IRubyObject)o1, (IRubyObject)o2);
}
});
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}
return this;
}
@@ -3790,8 +3807,8 @@ public IRubyObject shuffle_bang(ThreadContext context, IRubyObject[] args) {
values[begin + i] = eltOk(r);
values[begin + r] = tmp;
}
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}

return this;
@@ -3841,7 +3858,7 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
}
return eltOk(randomReal(context, randgen, realLength));
}
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
int n = RubyNumeric.num2int(args[0]);

if (n < 0)
@@ -3920,8 +3937,8 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
ary.realLength = n;
return ary;
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
return this; // not reached
}
}
@@ -3954,8 +3971,8 @@ private IRubyObject internalRotateBang(ThreadContext context, int cnt) {
return this;
}
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}

return context.runtime.getNil();
@@ -3979,8 +3996,8 @@ private IRubyObject internalRotate(ThreadContext context, int cnt) {
System.arraycopy(ptr, begin + cnt, ptr2, 0, len);
System.arraycopy(ptr, begin, ptr2, len, cnt);
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification();
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(context.runtime, ex);
}

return rotated;
@@ -4099,8 +4116,8 @@ public static void marshalTo(RubyArray array, MarshalStream output) throws IOExc
for (int i = 0; i < length; i++) {
output.dumpObject(ary[i + begin]);
}
} catch (ArrayIndexOutOfBoundsException aioob) {
concurrentModification(array.getRuntime());
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(array.getRuntime(), ex);
}
}

@@ -4429,11 +4446,11 @@ private IRubyObject safeArrayRef(IRubyObject[] values, int i) {
return safeArrayRef(getRuntime(), values, i);
}

private IRubyObject safeArrayRef(Ruby runtime, IRubyObject[] values, int i) {
private static IRubyObject safeArrayRef(Ruby runtime, IRubyObject[] values, int i) {
try {
return values[i];
} catch (ArrayIndexOutOfBoundsException x) {
concurrentModification(runtime);
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
return null; // not reached
}
}
@@ -4445,38 +4462,38 @@ private IRubyObject safeArraySet(IRubyObject[] values, int i, IRubyObject value)
private static IRubyObject safeArraySet(Ruby runtime, IRubyObject[] values, int i, IRubyObject value) {
try {
return values[i] = value;
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification(runtime);
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
return null; // not reached
}
}

private IRubyObject safeArrayRefSet(IRubyObject[] values, int i, IRubyObject value) {
return safeArrayRefSet(getRuntime(), values, i, value);
}
//private IRubyObject safeArrayRefSet(IRubyObject[] values, int i, IRubyObject value) {
// return safeArrayRefSet(getRuntime(), values, i, value);
//}

private static IRubyObject safeArrayRefSet(Ruby runtime, IRubyObject[] values, int i, IRubyObject value) {
try {
IRubyObject tmp = values[i];
values[i] = value;
return tmp;
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification(runtime);
concurrentModification(runtime, e);
return null; // not reached
}
}

private IRubyObject safeArrayRefCondSet(IRubyObject[] values, int i, boolean doSet, IRubyObject value) {
return safeArrayRefCondSet(getRuntime(), values, i, doSet, value);
}
//private IRubyObject safeArrayRefCondSet(IRubyObject[] values, int i, boolean doSet, IRubyObject value) {
// return safeArrayRefCondSet(getRuntime(), values, i, doSet, value);
//}

private static IRubyObject safeArrayRefCondSet(Ruby runtime, IRubyObject[] values, int i, boolean doSet, IRubyObject value) {
try {
IRubyObject tmp = values[i];
if (doSet) values[i] = value;
return tmp;
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification(runtime);
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
return null; // not reached
}
}
@@ -4485,11 +4502,11 @@ private void safeArrayCopy(IRubyObject[] source, int sourceStart, IRubyObject[]
safeArrayCopy(getRuntime(), source, sourceStart, target, targetStart, length);
}

private void safeArrayCopy(Ruby runtime, IRubyObject[] source, int sourceStart, IRubyObject[] target, int targetStart, int length) {
private static void safeArrayCopy(Ruby runtime, IRubyObject[] source, int sourceStart, IRubyObject[] target, int targetStart, int length) {
try {
System.arraycopy(source, sourceStart, target, targetStart, length);
} catch (ArrayIndexOutOfBoundsException e) {
concurrentModification(runtime);
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification(runtime, ex);
}
// not reached
}
11 changes: 5 additions & 6 deletions core/src/test/java/org/jruby/test/TestRubyArray.java
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2006 Ola Bini <Ola.Bini@ki.se>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -30,7 +30,6 @@
import java.util.Arrays;
import java.util.List;

import org.jruby.Ruby;
import org.jruby.RubyArray;

/**
@@ -76,7 +75,7 @@ public void testConstructors() throws Exception {
}

/**
* Test Array#[]= (store) and Array#[] (retrieve).
* Test Array#[]= (store) and Array#[] (retrieve).
*/
public void testLookups() throws Exception {
// value equality
@@ -171,19 +170,19 @@ public void testSetsLeftoverValuesToNullInDelete() throws Exception {
assertNotSame("first element nil", runtime.getNil(), arr.eltInternal(0));
assertSame("second element not nil", runtime.getNil(), arr.eltInternal(1));
}

private void assertSublistContainsCorrectSubset(final List<?> list) {
final List<?> subList = list.subList(1, 3);
assertEquals(2, subList.size());
assertEquals("bar", subList.get(0));
assertEquals("baz", subList.get(1));
}

public void testSubListContainsCorrectSubset() {
// Demonstrates that this is a fair test
final List<?> javaArray = Arrays.asList("foo", "bar", "baz", "anything");
assertSublistContainsCorrectSubset(javaArray);

// Ruby should give the same results
final RubyArray rubyArray = (RubyArray)runtime.evalScriptlet("$h = ['foo', 'bar', 'baz', 'anything']");
assertSublistContainsCorrectSubset(rubyArray);
31 changes: 16 additions & 15 deletions spec/regression/GH-1371_gzip_spec.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
require 'zlib'
describe 'Zlib::GzipWriter' do

class IoLikeObject
attr_reader :body
before(:all) { require 'zlib' }

def initialize
@body = []
end

def write(str)
@body << str
end
end

describe Zlib::GzipWriter do
GZIP_MAGIC_1 = 0x1F
GZIP_MAGIC_2 = 0X8B

class IoLikeObject
attr_reader :body

def initialize
@body = []
end

def write(str)
@body << str
end
end

it "doesn't corrupt the output" do
io_like_object = IoLikeObject.new
gzip = Zlib::GzipWriter.new(io_like_object)
@@ -31,11 +32,11 @@ def write(str)
gzip.flush

# first chunk should still be intact (specifically: it should not be overwritten with the second)
first_chunk.should == io_like_object.body[0]
expect( first_chunk ).to eql io_like_object.body[0]

gzip.close

# extra sanity check of the gzip "magic bytes"
io_like_object.body[0].bytes.to_a[0..1].should == [GZIP_MAGIC_1, GZIP_MAGIC_2]
expect( io_like_object.body[0].bytes.to_a[0..1] ).to eql [GZIP_MAGIC_1, GZIP_MAGIC_2]
end
end