< prev index next >
src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
Print this page
*** 34,43 ****
--- 34,44 ----
/**
* Handle arrays where the index is very large.
*/
class SparseArrayData extends ArrayData {
+ /** Maximum size for dense arrays */
static final int MAX_DENSE_LENGTH = 1024 * 1024;
/** Underlying array. */
private ArrayData underlying;
*** 49,59 ****
SparseArrayData(final ArrayData underlying, final long length) {
this(underlying, length, new TreeMap<Long, Object>());
}
! SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) {
super(length);
assert underlying.length() <= length;
this.underlying = underlying;
this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length());
this.sparseMap = sparseMap;
--- 50,60 ----
SparseArrayData(final ArrayData underlying, final long length) {
this(underlying, length, new TreeMap<Long, Object>());
}
! private SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) {
super(length);
assert underlying.length() <= length;
this.underlying = underlying;
this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length());
this.sparseMap = sparseMap;
*** 87,128 ****
return objArray;
}
@Override
! public void shiftLeft(final int by) {
! underlying.shiftLeft(by);
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long newIndex = entry.getKey().longValue() - by;
if (newIndex < maxDenseLength) {
! underlying = underlying.set((int) newIndex, entry.getValue(), false);
! } else if (newIndex >= 0) {
newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
}
}
sparseMap = newSparseMap;
setLength(Math.max(length() - by, 0));
}
@Override
public ArrayData shiftRight(final int by) {
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
final long len = underlying.length();
if (len + by > maxDenseLength) {
! for (long i = maxDenseLength - by; i < len; i++) {
if (underlying.has((int) i)) {
newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
}
}
! underlying = underlying.shrink((int) (maxDenseLength - by));
}
! underlying.shiftRight(by);
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long newIndex = entry.getKey().longValue() + by;
newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
}
--- 88,140 ----
return objArray;
}
@Override
! public ArrayData shiftLeft(final int by) {
! underlying = underlying.shiftLeft(by);
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long newIndex = entry.getKey().longValue() - by;
+ if (newIndex >= 0) {
if (newIndex < maxDenseLength) {
! final long oldLength = underlying.length();
! underlying = underlying.ensure(newIndex)
! .set((int) newIndex, entry.getValue(), false)
! .safeDelete(oldLength, newIndex - 1, false);
! } else {
newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
}
}
+ }
sparseMap = newSparseMap;
setLength(Math.max(length() - by, 0));
+
+ return sparseMap.isEmpty() ? underlying : this;
}
@Override
public ArrayData shiftRight(final int by) {
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
+ // Move elements from underlying to sparse map if necessary
final long len = underlying.length();
if (len + by > maxDenseLength) {
! // Length of underlying array after shrinking, before right-shifting
! final long tempLength = Math.max(0, maxDenseLength - by);
! for (long i = tempLength; i < len; i++) {
if (underlying.has((int) i)) {
newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
}
}
! underlying = underlying.shrink((int) tempLength);
! underlying.setLength(tempLength);
}
! underlying = underlying.shiftRight(by);
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long newIndex = entry.getKey().longValue() + by;
newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
}
*** 133,150 ****
return this;
}
@Override
public ArrayData ensure(final long safeIndex) {
- // Usually #ensure only needs to be called if safeIndex is greater or equal current length.
- // SparseArrayData is an exception as an index smaller than our current length may still
- // exceed the underlying ArrayData's capacity. Because of this, SparseArrayData invokes
- // its ensure method internally in various places where other ArrayData subclasses don't,
- // making it safe for outside uses to only call ensure(safeIndex) if safeIndex >= length.
- if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
- underlying = underlying.ensure(safeIndex);
- }
if (safeIndex >= length()) {
setLength(safeIndex + 1);
}
return this;
}
--- 145,154 ----
*** 165,176 ****
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! ensure(index);
! underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
--- 169,179 ----
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! underlying = underlying.ensure(index).set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
*** 181,192 ****
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! ensure(index);
! underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
--- 184,194 ----
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! underlying = underlying.ensure(index).set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
*** 196,207 ****
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! ensure(index);
! underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
--- 198,208 ----
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
! underlying = underlying.ensure(index).set(index, value, strict).safeDelete(oldLength, index - 1, strict);
setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
setLength(Math.max(longIndex + 1, length()));
< prev index next >