Skip to content

Commit 6b78b31

Browse files
committed
[GR-42807] Ensure deleted elements are filled with hole values.
PullRequest: js/2676
2 parents 4f5e0e0 + cd81cf2 commit 6b78b31

File tree

12 files changed

+92
-30
lines changed

12 files changed

+92
-30
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
6+
*/
7+
8+
var s2 = "";
9+
var a0 = [];
10+
var a1 = [];
11+
var a2 = [];
12+
var a3 = [];
13+
var a4 = [];
14+
var o1 = {};
15+
for (let i = 0; i < 5; i++) {
16+
Array.prototype.shift.apply(a1);
17+
a1.splice(NaN, -2044533922.5, a0, s2);
18+
}
19+
for (let i = 0; i < 5; i++) {
20+
Array.prototype.shift.apply(a2);
21+
a2.splice(NaN, -2044533922.5, 3, 4);
22+
}
23+
for (let i = 0; i < 5; i++) {
24+
Array.prototype.shift.apply(a3);
25+
a3.splice(NaN, -2044533922.5, 3.1, 4.15);
26+
}
27+
for (let i = 0; i < 5; i++) {
28+
Array.prototype.shift.apply(a4);
29+
a4.splice(NaN, -2044533922.5, o1, o1);
30+
}

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractJSObjectArray.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ protected final void fillHoles(JSDynamicObject object, int internalIndex, int gr
140140
if (grown != 0) {
141141
incrementHolesCount(object, Math.abs(grown) - 1);
142142
}
143+
assert checkFillHoles(object, internalIndex, grown);
143144
}
144145

145146
@Override

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractObjectArray.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ protected final void fillHoles(JSDynamicObject object, int internalIndex, int gr
142142
if (grown != 0) {
143143
incrementHolesCount(object, Math.abs(grown) - 1);
144144
}
145+
assert checkFillHoles(object, internalIndex, grown);
145146
}
146147

147148
@Override

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractWritableArray.java

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,9 @@ protected final int prepareSupportedHoles(JSDynamicObject object, int index, Pro
199199
}
200200

201201
@SuppressWarnings("unused")
202-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
203-
throw Errors.shouldNotReachHere();
202+
protected final void incrementHolesCount(JSDynamicObject object, int offset) {
203+
assert isHolesType();
204+
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
204205
}
205206

206207
protected abstract void setHoleValue(JSDynamicObject object, int index);
@@ -348,6 +349,27 @@ protected void fillHoles(JSDynamicObject object, int internalIndex, int grown, P
348349
}
349350
}
350351

352+
protected final boolean checkFillHoles(JSDynamicObject object, int internalIndex, int grown) {
353+
int start;
354+
int end;
355+
if (grown > 1) {
356+
start = internalIndex - grown + 1;
357+
end = internalIndex;
358+
} else if (grown < -1) {
359+
start = internalIndex + 1;
360+
end = internalIndex - grown;
361+
} else {
362+
return true;
363+
}
364+
365+
for (int i = start; i < end; i++) {
366+
if (!isHolePrepared(object, i)) {
367+
return false;
368+
}
369+
}
370+
return true;
371+
}
372+
351373
public abstract AbstractWritableArray toDouble(JSDynamicObject object, long index, double value);
352374

353375
public abstract AbstractWritableArray toObject(JSDynamicObject object, long index, Object value);
@@ -520,7 +542,7 @@ protected final void setLengthLessContiguous(JSDynamicObject object, long length
520542
if (SET_LENGTH_PROFILE.contiguousShrinkUsed(profile, newUsedLength < oldUsed)) {
521543
if (isHolesType()) {
522544
incrementHolesCount(object, -countHolesPrepared(object, arrayOffset + newUsedLength, arrayOffset + oldUsed));
523-
assert arrayGetHoleCount(object) == countHoles(object);
545+
assert assertHoleCount(object);
524546
}
525547

526548
// use old arrayOffset
@@ -614,7 +636,7 @@ protected final ScriptArray deleteElementHoles(JSDynamicObject object, long inde
614636
}
615637
}
616638
}
617-
assert arrayGetHoleCount(object) == countHoles(object);
639+
assert assertHoleCount(object);
618640
return this;
619641
}
620642

@@ -806,6 +828,14 @@ private int countHolesPrepared(JSDynamicObject object, int start, int end) {
806828
return holeCount;
807829
}
808830

831+
protected final boolean assertHoleCount(JSDynamicObject object) {
832+
assert isHolesType();
833+
int holeCount = arrayGetHoleCount(object);
834+
int countedHoles = countHoles(object);
835+
assert holeCount == countedHoles : String.format("holeCount, %d, differs from the actual count, %d", holeCount, countedHoles);
836+
return true;
837+
}
838+
809839
/**
810840
* Move {@code len} elements from {@code src} to {@code dst}.
811841
*/
@@ -837,6 +867,20 @@ public ScriptArray shiftRangeImpl(JSDynamicObject object, long from) {
837867
return removeRangeImpl(object, 0, from);
838868
}
839869

870+
protected static boolean unusedElementsAreHoles(Object[] array, int usedStart, int usedLength) {
871+
for (int i = 0; i < usedStart; i++) {
872+
if (array[i] != null) {
873+
return false;
874+
}
875+
}
876+
for (int i = usedStart + usedLength; i < array.length; i++) {
877+
if (array[i] != null) {
878+
return false;
879+
}
880+
}
881+
return true;
882+
}
883+
840884
protected interface SetSupportedProfileAccess extends ProfileAccess {
841885
default boolean ensureCapacityGrow(ProfileHolder profile, boolean condition) {
842886
return profile.profile(this, 0, condition);

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/ContiguousJSObjectArray.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public static ContiguousJSObjectArray makeContiguousJSObjectArray(JSDynamicObjec
5252
int integrityLevel) {
5353
ContiguousJSObjectArray arrayType = createContiguousJSObjectArray().setIntegrityLevel(integrityLevel);
5454
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
55+
assert unusedElementsAreHoles(array, arrayOffset, usedLength);
5556
return arrayType;
5657
}
5758

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/ContiguousObjectArray.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public final class ContiguousObjectArray extends AbstractContiguousObjectArray {
5151
public static ContiguousObjectArray makeContiguousObjectArray(JSDynamicObject object, long length, Object[] array, long indexOffset, int arrayOffset, int usedLength, int integrityLevel) {
5252
ContiguousObjectArray arrayType = createContiguousObjectArray().setIntegrityLevel(integrityLevel);
5353
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
54+
assert unusedElementsAreHoles(array, arrayOffset, usedLength);
5455
return arrayType;
5556
}
5657

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/HolesDoubleArray.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public static HolesDoubleArray makeHolesDoubleArray(JSDynamicObject object, int
6565
HolesDoubleArray arrayType = createHolesDoubleArray().setIntegrityLevel(integrityLevel);
6666
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
6767
arraySetHoleCount(object, holeCount);
68-
assert holeCount == arrayType.countHoles(object);
68+
assert arrayType.assertHoleCount(object);
6969
return arrayType;
7070
}
7171

@@ -142,11 +142,6 @@ public AbstractDoubleArray toNonHoles(JSDynamicObject object, long index, Object
142142
return newArray;
143143
}
144144

145-
@Override
146-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
147-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
148-
}
149-
150145
@Override
151146
public boolean isSupported(JSDynamicObject object, long index) {
152147
return isSupportedHoles(object, index);

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/HolesIntArray.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static HolesIntArray makeHolesIntArray(JSDynamicObject object, int length
6464
HolesIntArray arrayType = createHolesIntArray().setIntegrityLevel(integrityLevel);
6565
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
6666
arraySetHoleCount(object, holeCount);
67-
assert holeCount == arrayType.countHoles(object) : String.format("holeCount, %d, differs from the actual count, %d", holeCount, arrayType.countHoles(object));
67+
assert arrayType.assertHoleCount(object);
6868
return arrayType;
6969
}
7070

@@ -160,11 +160,6 @@ public Object getInBoundsFast(JSDynamicObject object, int index) {
160160
return value;
161161
}
162162

163-
@Override
164-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
165-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
166-
}
167-
168163
@Override
169164
public HolesIntArray toHoles(JSDynamicObject object, long index, Object value) {
170165
return this;

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/HolesJSObjectArray.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static HolesJSObjectArray makeHolesJSObjectArray(JSDynamicObject object,
6464
HolesJSObjectArray arrayType = createHolesJSObjectArray().setIntegrityLevel(integrityLevel);
6565
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
6666
arraySetHoleCount(object, holeCount);
67-
assert holeCount == arrayType.countHoles(object);
67+
assert arrayType.assertHoleCount(object);
6868
return arrayType;
6969
}
7070

@@ -153,11 +153,6 @@ public AbstractWritableArray toObject(JSDynamicObject object, long index, Object
153153
return newArray;
154154
}
155155

156-
@Override
157-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
158-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
159-
}
160-
161156
@Override
162157
public int prepareInBounds(JSDynamicObject object, int index, ProfileHolder profile) {
163158
return prepareInBoundsHoles(object, index, profile);

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/HolesObjectArray.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static HolesObjectArray makeHolesObjectArray(JSDynamicObject object, int
6363
HolesObjectArray arrayType = createHolesObjectArray().setIntegrityLevel(integrityLevel);
6464
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
6565
arraySetHoleCount(object, holeCount);
66-
assert holeCount == arrayType.countHoles(object) : String.format("holeCount, %d, differs from the actual count, %d", holeCount, arrayType.countHoles(object));
66+
assert arrayType.assertHoleCount(object);
6767
return arrayType;
6868
}
6969

@@ -135,11 +135,6 @@ public AbstractObjectArray toNonHoles(JSDynamicObject object, long index, Object
135135
return newArray;
136136
}
137137

138-
@Override
139-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
140-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
141-
}
142-
143138
@Override
144139
public int prepareInBounds(JSDynamicObject object, int index, ProfileHolder profile) {
145140
return prepareInBoundsHoles(object, index, profile);

0 commit comments

Comments
 (0)