Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement two-object specialized arrays, plus misc improvements.
Browse files Browse the repository at this point in the history
* Reduce #unpack logic.
* Pull a couple more methods up to RubyArray with accessors.
* Document specialized array classes.
* Eliminate flag; null values field is good enough (maybe better).
headius committed Jun 11, 2016
1 parent a83428f commit caee6c4
Showing 5 changed files with 208 additions and 124 deletions.
34 changes: 25 additions & 9 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@
import org.jruby.runtime.marshal.MarshalStream;
import org.jruby.runtime.marshal.UnmarshalStream;
import org.jruby.specialized.RubyArrayOneObject;
import org.jruby.specialized.RubyArrayTwoObject;
import org.jruby.util.ByteList;
import org.jruby.util.Pack;
import org.jruby.util.Qsort;
@@ -143,6 +144,8 @@ public static IRubyObject create(IRubyObject klass, IRubyObject[] args, Block bl
switch (args.length) {
case 1:
return new RubyArrayOneObject((RubyClass) klass, args[0]);
case 2:
return new RubyArrayTwoObject((RubyClass) klass, args[0], args[1]);
default:
arr = (RubyArray) ((RubyClass) klass).allocate();
}
@@ -213,7 +216,7 @@ public static RubyArray newArrayLight(Ruby runtime, IRubyObject... objs) {
*
*/
public static RubyArray newArray(Ruby runtime, IRubyObject car, IRubyObject cdr) {
return new RubyArray(runtime, new IRubyObject[] { car, cdr });
return new RubyArrayTwoObject(runtime, car, cdr);
}

public static RubyArray newEmptyArray(Ruby runtime) {
@@ -224,7 +227,14 @@ public static RubyArray newEmptyArray(Ruby runtime) {
*
*/
public static RubyArray newArray(Ruby runtime, IRubyObject[] args) {
if (args.length == 1) return new RubyArrayOneObject(runtime, args[0]);
switch (args.length) {
case 0:
return newEmptyArray(runtime);
case 1:
return new RubyArrayOneObject(runtime, args[0]);
case 2:
return new RubyArrayTwoObject(runtime, args[0], args[1]);
}
RubyArray arr = new RubyArray(runtime, new IRubyObject[args.length]);
System.arraycopy(args, 0, arr.values, 0, args.length);
arr.realLength = args.length;
@@ -254,8 +264,14 @@ public static RubyArray newArrayNoCopyLight(Ruby runtime, IRubyObject[] args) {
}

public static RubyArray newArray(Ruby runtime, Collection<? extends IRubyObject> collection) {
if (collection.size() == 1) return new RubyArrayOneObject(runtime, collection.iterator().next());
return new RubyArray(runtime, collection.toArray(new IRubyObject[collection.size()]));
// This may seem inefficient for packed arrays, but the cost of this versus is not really worse
// than the cost of constructing and walking an Iterator.
IRubyObject[] values = collection.toArray(new IRubyObject[collection.size()]);
switch (values.length) {
case 1: return new RubyArrayOneObject(runtime, values[0]);
case 2: return new RubyArrayTwoObject(runtime, values[0], values[1]);
}
return new RubyArray(runtime, values);
}

public static final int ARRAY_DEFAULT_SIZE = 16;
@@ -918,7 +934,6 @@ private final void spliceOne(long beg, IRubyObject rpl) {
}

private void spliceRealloc(int length, int valuesLength) {
unpack();
int tryLength = valuesLength + (valuesLength >> 1);
int len = length > tryLength ? length : tryLength;
IRubyObject[] vals = new IRubyObject[len];
@@ -2089,7 +2104,7 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, IRuby
modify();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

@@ -2115,7 +2130,7 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, Block
modify();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

@@ -3322,13 +3337,13 @@ public int compare(Object o1, Object o2) {
return this;
}

private static int compareFixnums(RubyFixnum o1, RubyFixnum o2) {
protected static int compareFixnums(RubyFixnum o1, RubyFixnum o2) {
long a = o1.getLongValue();
long b = o2.getLongValue();
return a > b ? 1 : a == b ? 0 : -1;
}

private static int compareOthers(ThreadContext context, IRubyObject o1, IRubyObject o2) {
protected static int compareOthers(ThreadContext context, IRubyObject o1, IRubyObject o2) {
IRubyObject ret = invokedynamic(context, o1, OP_CMP, o2);
int n = RubyComparable.cmpint(context, ret, o1, o2);
//TODO: ary_sort_check should be done here
@@ -4687,6 +4702,7 @@ public final RubyArray aryDup19() {
*/
@Deprecated
public void ensureCapacity(int minCapacity) {
unpack();
if ( isShared || (values.length - begin) < minCapacity ) {
final int len = this.realLength;
int newCapacity = minCapacity > len ? minCapacity : len;
36 changes: 11 additions & 25 deletions core/src/main/java/org/jruby/specialized/RubyArrayOneObject.java
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
import static org.jruby.runtime.Helpers.arrayOf;

/**
* Created by headius on 5/28/16.
* One object version of RubyArraySpecialized.
*/
public class RubyArrayOneObject extends RubyArraySpecialized {
private IRubyObject value;
@@ -27,14 +27,13 @@ public RubyArrayOneObject(Ruby runtime, IRubyObject value) {
super(runtime, false);
this.value = value;
this.realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, true);
}

public RubyArrayOneObject(RubyClass otherClass, IRubyObject value) {
// packed arrays are omitted from ObjectSpace
super(otherClass, false);
this.value = value;
this.realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, true);
}

RubyArrayOneObject(RubyArrayOneObject other) {
@@ -60,15 +59,8 @@ public final IRubyObject eltInternalSet(int index, IRubyObject value) {
}

@Override
protected void unpack() {
if (!packed()) return;
// CON: I believe most of the time we'll fail because we need to grow, so give a bit of extra room
IRubyObject nil = getRuntime().getNil();
values = new IRubyObject[]{nil, value, nil};
protected void finishUnpack(IRubyObject nil) {
value = nil;
begin = 1;
realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, false);
}

@Override
@@ -87,7 +79,6 @@ public IRubyObject rb_clear() {
value = null;
values = IRubyObject.NULL_ARRAY;
realLength = 0;
setFlag(Constants.PACKED_ARRAY_F, false);

return this;
}
@@ -146,7 +137,7 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, Block
modifyCheck();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

@@ -167,7 +158,7 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, IRuby
modifyCheck();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

@@ -279,9 +270,8 @@ protected IRubyObject sortInternal(final ThreadContext context, boolean honorOve
public IRubyObject store(long index, IRubyObject value) {
if (!packed()) return super.store(index, value);

if (index == 1) {
eltSetOk(index, value);
return value;
if (index == 0) {
return this.value = value;
}

unpack();
@@ -291,10 +281,14 @@ public IRubyObject store(long index, IRubyObject value) {
@Override
public IRubyObject subseq(RubyClass metaClass, long beg, long len, boolean light) {
if (!packed()) return super.subseq(metaClass, beg, len, light);

if (len == 0) return newEmptyArray(metaClass.getClassRuntime());

if (beg != 0 || len != 1) {
unpack();
return super.subseq(metaClass, beg, len, light);
}

return new RubyArrayOneObject(metaClass, this);
}

@@ -311,12 +305,4 @@ public IRubyObject uniq(ThreadContext context) {

return new RubyArrayOneObject(this);
}

@Override
@Deprecated
public void ensureCapacity(int minCapacity) {
if (minCapacity == 1) return;
unpack();
super.ensureCapacity(minCapacity);
}
}
82 changes: 55 additions & 27 deletions core/src/main/java/org/jruby/specialized/RubyArraySpecialized.java
Original file line number Diff line number Diff line change
@@ -4,9 +4,46 @@
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.runtime.Constants;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.builtin.IRubyObject;

/**
* Created by headius on 5/28/16.
* This is the base class for all specialized RubyArray.
*
* Specialized RubyArray use fields rather than an IRubyObject[] to hold their values. When they need
* to grow or shrink, they unpack those values to a proper IRubyObject[] and fall back on RubyArray
* logic.
*
* Subclasses should override all methods that would access the array directly to use the fields,
* with guards for the packed flag and access outside packed range. This includes the following
* methods (at the time of this writing...this list will evolve):
*
* RubyArray{@link #eltInternal(int)}
* RubyArray{@link #eltInternalSet(int index, IRubyObject value)}
* RubyArraySpecialized{@link #finishUnpack(IRubyObject nil)}
* RubyArray{@link #aryDup()}
* RubyArray{@link #rb_clear()}
* RubyArray{@link #collect(org.jruby.runtime.ThreadContext, org.jruby.runtime.Block)}
* RubyArray{@link #copyInto(IRubyObject[], int)}
* RubyArray{@link #copyInto(IRubyObject[], int, int)}
* RubyArray{@link #dup()}
* RubyArray{@link #each(org.jruby.runtime.ThreadContext, org.jruby.runtime.Block)}
* RubyArray{@link #fillCommon(org.jruby.runtime.ThreadContext, int, long, org.jruby.runtime.Block)}
* RubyArray{@link #fillCommon(org.jruby.runtime.ThreadContext, int, long, IRubyObject)}
* RubyArray{@link #includes(org.jruby.runtime.ThreadContext, IRubyObject)}
* RubyArray{@link #indexOf(Object)}
* RubyArray{@link #inspectAry(org.jruby.runtime.ThreadContext)}
* RubyArray{@link #internalRotate(org.jruby.runtime.ThreadContext, int)}
* RubyArray{@link #internalRotateBang(org.jruby.runtime.ThreadContext, int)}
* RubyArray{@link #op_plus(IRubyObject)}
* RubyArray{@link #reverse_bang()}
* RubyArray{@link #safeReverse()}
* RubyArray{@link #sortInternal(org.jruby.runtime.ThreadContext, org.jruby.runtime.Block)}
* RubyArray{@link #sortInternal(org.jruby.runtime.ThreadContext, boolean)}
* RubyArray{@link #store(long, IRubyObject)}
* RubyArray{@link #subseq(RubyClass, long, long, boolean)}
* RubyArray{@link #toJavaArray()}
* RubyArray{@link #uniq(org.jruby.runtime.ThreadContext)}
*/
public abstract class RubyArraySpecialized extends RubyArray {
public RubyArraySpecialized(Ruby runtime, boolean light) {
@@ -17,33 +54,24 @@ public RubyArraySpecialized(RubyClass otherClass, boolean light) {
super(otherClass.getClassRuntime(), otherClass, light);
}

// @Override
// public abstract IRubyObject eltSetOk(long offset, IRubyObject value);
//
// @Override
// public abstract IRubyObject eltInternal(int offset);
//
// @Override
// public abstract IRubyObject eltInternalSet(int offset, IRubyObject item);
//
// @Override
// public abstract IRubyObject dup();
//
// @Override
// public abstract IRubyObject each(ThreadContext context, Block block);
//
// @Override
// public abstract void copyInto(IRubyObject[] target, int start);
//
// @Override
// protected abstract IRubyObject fillCommon(ThreadContext context, int beg, long len, IRubyObject item);
//
// @Override
// protected abstract IRubyObject fillCommon(ThreadContext context, int beg, long len, Block block);

protected abstract void unpack();
protected final void unpack() {
if (!packed()) return;

// CON: I believe most of the time we'll unpack because we need to grow, so give a bit of extra room.
// For example, <<, unshift, and push will all just add one to front or back.
Ruby runtime = getRuntime();
IRubyObject[] values = new IRubyObject[realLength + 2];
Helpers.fillNil(values, runtime);
copyInto(values, 1);
this.values = values;
this.begin = 1;

finishUnpack(runtime.getNil());
}

protected abstract void finishUnpack(IRubyObject nil);

protected boolean packed() {
return getFlag(Constants.PACKED_ARRAY_F);
return values == null;
}
}
178 changes: 117 additions & 61 deletions core/src/main/java/org/jruby/specialized/RubyArrayTwoObject.java
Original file line number Diff line number Diff line change
@@ -4,71 +4,71 @@
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyComparable;
import org.jruby.RubyFixnum;
import org.jruby.RubyString;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Block;
import org.jruby.runtime.Constants;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.invokedynamic.MethodNames;
import org.jruby.util.io.EncodingUtils;

import static org.jruby.RubyEnumerator.enumeratorizeWithSize;
import static org.jruby.runtime.Helpers.arrayOf;
import static org.jruby.runtime.Helpers.invokedynamic;

/**
* Created by headius on 5/28/16.
* Two object version of RubyArraySpecialized.
*/
public class RubyArrayTwoObject extends RubyArraySpecialized {
private IRubyObject value;
private IRubyObject car;
private IRubyObject cdr;

public RubyArrayTwoObject(Ruby runtime, IRubyObject value) {
public RubyArrayTwoObject(Ruby runtime, IRubyObject car, IRubyObject cdr) {
// packed arrays are omitted from ObjectSpace
super(runtime, false);
this.value = value;
this.realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, true);
this.car = car;
this.cdr = cdr;
this.realLength = 2;
}

public RubyArrayTwoObject(RubyClass otherClass, IRubyObject value) {
public RubyArrayTwoObject(RubyClass otherClass, IRubyObject car, IRubyObject cdr) {
// packed arrays are omitted from ObjectSpace
super(otherClass, false);
this.value = value;
this.realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, true);
this.car = car;
this.cdr = cdr;
this.realLength = 2;
}

RubyArrayTwoObject(RubyArrayTwoObject other) {
this(other.getMetaClass(), other.value);
this(other.getMetaClass(), other.car, other.cdr);
}

RubyArrayTwoObject(RubyClass metaClass, RubyArrayTwoObject other) {
this(metaClass, other.value);
this(metaClass, other.car, other.cdr);
}

@Override
public final IRubyObject eltInternal(int index) {
if (!packed()) return super.eltInternal(index);
else if (index == 0) return value;
else if (index == 0) return car;
else if (index == 1) return cdr;
throw new ArrayIndexOutOfBoundsException(index);
}

@Override
public final IRubyObject eltInternalSet(int index, IRubyObject value) {
if (!packed()) return super.eltInternalSet(index, value);
if (index == 0) return this.value = value;
if (index == 0) return this.car = value;
if (index == 1) return this.cdr = value;
throw new ArrayIndexOutOfBoundsException(index);
}

@Override
protected void unpack() {
if (!packed()) return;
// CON: I believe most of the time we'll fail because we need to grow, so give a bit of extra room
IRubyObject nil = getRuntime().getNil();
values = new IRubyObject[]{nil, value, nil};
value = nil;
begin = 1;
realLength = 1;
setFlag(Constants.PACKED_ARRAY_F, false);
protected void finishUnpack(IRubyObject nil) {
car = cdr = nil;
}

@Override
@@ -84,10 +84,10 @@ public IRubyObject rb_clear() {
modifyCheck();

// fail packing, but defer [] creation in case it is never needed
value = null;
IRubyObject nil = getRuntime().getNil();
car = cdr = nil;
values = IRubyObject.NULL_ARRAY;
realLength = 0;
setFlag(Constants.PACKED_ARRAY_F, false);

return this;
}
@@ -96,7 +96,7 @@ public IRubyObject rb_clear() {
public IRubyObject collect(ThreadContext context, Block block) {
if (!packed()) return super.collect(context, block);

return new RubyArrayTwoObject(getRuntime(), block.yield(context, value));
return new RubyArrayTwoObject(getRuntime(), block.yield(context, car), block.yield(context, cdr));
}

@Override
@@ -105,21 +105,23 @@ public void copyInto(IRubyObject[] target, int start) {
super.copyInto(target, start);
return;
}
target[start] = value;
target[start] = car;
target[start + 1] = cdr;
}

@Override
public void copyInto(IRubyObject[] target, int start, int len) {
if (!packed()) {
super.copyInto(target, start);
super.copyInto(target, start, len);
return;
}
if (len != 1) {
if (len != 2) {
unpack();
super.copyInto(target, start);
super.copyInto(target, start, len);
return;
}
target[start] = value;
target[start] = car;
target[start + 1] = cdr;
}

@Override
@@ -134,7 +136,8 @@ public IRubyObject each(ThreadContext context, Block block) {

if (!block.isGiven()) return enumeratorizeWithSize(context, this, "each", enumLengthFn());

block.yield(context, value);
block.yield(context, car);
block.yield(context, cdr);

return this;
}
@@ -146,16 +149,17 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, Block
modifyCheck();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

if (len > 1) {
if (len > 2) {
unpack();
return super.fillCommon(context, beg, len, block);
}

value = block.yield(context, RubyFixnum.zero(context.runtime));
car = block.yield(context, RubyFixnum.zero(context.runtime));
if (len > 1) cdr = block.yield(context, RubyFixnum.one(context.runtime));

return this;
}
@@ -167,16 +171,17 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, IRuby
modifyCheck();

// See [ruby-core:17483]
if (len < 0) return this;
if (len <= 0) return this;

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

if (len > 1) {
if (len > 2) {
unpack();
return super.fillCommon(context, beg, len, item);
}

value = item;
car = item;
if (len > 1) cdr = item;

return this;
}
@@ -185,7 +190,8 @@ protected IRubyObject fillCommon(ThreadContext context, int beg, long len, IRuby
public boolean includes(ThreadContext context, IRubyObject item) {
if (!packed()) return super.includes(context, item);

if (equalInternal(context, value, item)) return true;
if (equalInternal(context, car, item)) return true;
if (equalInternal(context, cdr, item)) return true;

return false;
}
@@ -197,7 +203,8 @@ public int indexOf(Object element) {
if (element != null) {
IRubyObject convertedElement = JavaUtil.convertJavaToUsableRubyObject(getRuntime(), element);

if (convertedElement.equals(value)) return 0;
if (convertedElement.equals(car)) return 0;
if (convertedElement.equals(cdr)) return 1;
}
return -1;
}
@@ -211,10 +218,17 @@ protected IRubyObject inspectAry(ThreadContext context) {
EncodingUtils.strBufCat(runtime, str, OPEN_BRACKET);
boolean tainted = isTaint();

RubyString s = inspect(context, value);
if (s.isTaint()) tainted = true;
else str.setEncoding(s.getEncoding());
str.cat19(s);
RubyString s1 = inspect(context, car);
RubyString s2 = inspect(context, cdr);
if (s1.isTaint()) tainted = true;
else str.setEncoding(s1.getEncoding());
str.cat19(s1);

EncodingUtils.strBufCat(runtime, str, COMMA_SPACE);

if (s2.isTaint()) tainted = true;
else str.setEncoding(s2.getEncoding());
str.cat19(s2);

EncodingUtils.strBufCat(runtime, str, CLOSE_BRACKET);

@@ -227,7 +241,8 @@ protected IRubyObject inspectAry(ThreadContext context) {
protected IRubyObject internalRotate(ThreadContext context, int cnt) {
if (!packed()) return super.internalRotate(context, cnt);

return aryDup();
if (cnt % 2 == 1) return new RubyArrayTwoObject(context.runtime, cdr, car);
return new RubyArrayTwoObject(context.runtime, car, cdr);
}

@Override
@@ -236,7 +251,13 @@ protected IRubyObject internalRotateBang(ThreadContext context, int cnt) {

modifyCheck();

return context.runtime.getNil();
if (cnt % 2 == 1) {
IRubyObject tmp = car;
car = cdr;
cdr = tmp;
}

return context.nil;
}

@Override
@@ -251,37 +272,65 @@ public IRubyObject op_plus(IRubyObject obj) {
public IRubyObject reverse_bang() {
if (!packed()) return super.reverse_bang();

IRubyObject tmp = car;
car = cdr;
cdr = tmp;

return this;
}

@Override
protected RubyArray safeReverse() {
if (!packed()) return super.safeReverse();

return new RubyArrayTwoObject(this);
return new RubyArrayTwoObject(getMetaClass(), cdr, car);
}

@Override
protected IRubyObject sortInternal(ThreadContext context, Block block) {
if (!packed()) return super.sortInternal(context, block);


IRubyObject ret = block.yieldArray(context, newArray(context.runtime, car, cdr), null);
//TODO: ary_sort_check should be done here
int compare = RubyComparable.cmpint(context, ret, car, cdr);
if (compare > 0) reverse_bang();
return this;
}

@Override
protected IRubyObject sortInternal(final ThreadContext context, boolean honorOverride) {
if (!packed()) return super.sortInternal(context, honorOverride);

Ruby runtime = context.runtime;

// One check per specialized fast-path to make the check invariant.
final boolean fixnumBypass = !honorOverride || runtime.getFixnum().isMethodBuiltin("<=>");
final boolean stringBypass = !honorOverride || runtime.getString().isMethodBuiltin("<=>");

IRubyObject o1 = car;
IRubyObject o2 = cdr;
int compare;
if (fixnumBypass && o1 instanceof RubyFixnum && o2 instanceof RubyFixnum) {
compare = compareFixnums((RubyFixnum) o1, (RubyFixnum) o2);
} else if (stringBypass && o1 instanceof RubyString && o2 instanceof RubyString) {
compare = ((RubyString) o1).op_cmp((RubyString) o2);
} else {
compare = compareOthers(context, o1, o2);
}

if (compare > 0) reverse_bang();

return this;
}

@Override
public IRubyObject store(long index, IRubyObject value) {
if (!packed()) return super.store(index, value);

if (index == 1) {
eltSetOk(index, value);
return value;
switch ((int) index) {
case 0: return car = value;
case 1: return cdr = value;
}

unpack();
@@ -291,32 +340,39 @@ public IRubyObject store(long index, IRubyObject value) {
@Override
public IRubyObject subseq(RubyClass metaClass, long beg, long len, boolean light) {
if (!packed()) return super.subseq(metaClass, beg, len, light);
if (beg != 0 || len != 1) {

if (len == 0) return newEmptyArray(metaClass.getClassRuntime());

if (beg < 0 || beg > 1 || len < 1 || len > 2) {
unpack();
return super.subseq(metaClass, beg, len, light);
}

if (len == 1) {
if (beg == 0) return new RubyArrayOneObject(metaClass, car);
if (beg == 1) return new RubyArrayOneObject(metaClass, cdr);
}

return new RubyArrayTwoObject(metaClass, this);
}

@Override
public IRubyObject[] toJavaArray() {
if (!packed()) return super.toJavaArray();

return arrayOf(value);
return arrayOf(car, cdr);
}

@Override
public IRubyObject uniq(ThreadContext context) {
if (!packed()) return super.uniq(context);

return new RubyArrayTwoObject(this);
}

@Override
@Deprecated
public void ensureCapacity(int minCapacity) {
if (minCapacity == 1) return;
unpack();
super.ensureCapacity(minCapacity);
if (invokedynamic(context, car, MethodNames.HASH).equals(invokedynamic(context, cdr, MethodNames.HASH)) &&
(car == cdr || invokedynamic(context, car, MethodNames.EQL, cdr).isTrue())) {
// Use cdr because it would have been inserted into RubyArray#uniq's RubyHash last
return new RubyArrayOneObject(getMetaClass(), cdr);
} else {
return new RubyArrayTwoObject(this);
}
}
}
2 changes: 0 additions & 2 deletions core/src/main/resources/org/jruby/runtime/Constants.java
Original file line number Diff line number Diff line change
@@ -106,8 +106,6 @@ public final class Constants {
public static final int COMPARE_BY_IDENTITY_F = registry.newFlag(RubyHash.class);
public static final int PROCDEFAULT_HASH_F = registry.newFlag(RubyHash.class);

public static final int PACKED_ARRAY_F = registry.newFlag(RubyArray.class);

private static final boolean DEBUG = false;
static {
if (DEBUG) registry.printFlags();

0 comments on commit caee6c4

Please sign in to comment.