Skip to content

Commit f34735d

Browse files
committed
[GR-45391] Ensure deleted elements are filled with hole values.
PullRequest: js/2775
2 parents 3bbe7e5 + 52ad63f commit f34735d

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, 2023, 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
@@ -141,6 +141,7 @@ protected final void fillHoles(JSDynamicObject object, int internalIndex, int gr
141141
if (grown != 0) {
142142
incrementHolesCount(object, Math.abs(grown) - 1);
143143
}
144+
assert checkFillHoles(object, internalIndex, grown);
144145
}
145146

146147
@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
@@ -143,6 +143,7 @@ protected final void fillHoles(JSDynamicObject object, int internalIndex, int gr
143143
if (grown != 0) {
144144
incrementHolesCount(object, Math.abs(grown) - 1);
145145
}
146+
assert checkFillHoles(object, internalIndex, grown);
146147
}
147148

148149
@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
@@ -204,8 +204,9 @@ protected final int prepareSupportedHoles(JSDynamicObject object, int index, Nod
204204
}
205205

206206
@SuppressWarnings("unused")
207-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
208-
throw Errors.shouldNotReachHere();
207+
protected final void incrementHolesCount(JSDynamicObject object, int offset) {
208+
assert isHolesType();
209+
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
209210
}
210211

211212
protected abstract void setHoleValue(JSDynamicObject object, int index);
@@ -353,6 +354,27 @@ protected void fillHoles(JSDynamicObject object, int internalIndex, int grown, N
353354
}
354355
}
355356

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

358380
public abstract AbstractWritableArray toObject(JSDynamicObject object, long index, Object value);
@@ -525,7 +547,7 @@ protected final void setLengthLessContiguous(JSDynamicObject object, long length
525547
if (profile.contiguousShrinkUsed(node, newUsedLength < oldUsed)) {
526548
if (isHolesType()) {
527549
incrementHolesCount(object, -countHolesPrepared(object, arrayOffset + newUsedLength, arrayOffset + oldUsed));
528-
assert arrayGetHoleCount(object) == countHoles(object);
550+
assert assertHoleCount(object);
529551
}
530552

531553
// use old arrayOffset
@@ -619,7 +641,7 @@ protected final ScriptArray deleteElementHoles(JSDynamicObject object, long inde
619641
}
620642
}
621643
}
622-
assert arrayGetHoleCount(object) == countHoles(object);
644+
assert assertHoleCount(object);
623645
return this;
624646
}
625647

@@ -814,6 +836,14 @@ private int countHolesPrepared(JSDynamicObject object, int start, int end) {
814836
return holeCount;
815837
}
816838

839+
protected final boolean assertHoleCount(JSDynamicObject object) {
840+
assert isHolesType();
841+
int holeCount = arrayGetHoleCount(object);
842+
int countedHoles = countHoles(object);
843+
assert holeCount == countedHoles : String.format("holeCount, %d, differs from the actual count, %d", holeCount, countedHoles);
844+
return true;
845+
}
846+
817847
/**
818848
* Move {@code len} elements from {@code src} to {@code dst}.
819849
*/
@@ -845,6 +875,20 @@ public ScriptArray shiftRangeImpl(JSDynamicObject object, long from) {
845875
return removeRangeImpl(object, 0, from);
846876
}
847877

878+
protected static boolean unusedElementsAreHoles(Object[] array, int usedStart, int usedLength) {
879+
for (int i = 0; i < usedStart; i++) {
880+
if (array[i] != null) {
881+
return false;
882+
}
883+
}
884+
for (int i = usedStart + usedLength; i < array.length; i++) {
885+
if (array[i] != null) {
886+
return false;
887+
}
888+
}
889+
return true;
890+
}
891+
848892
public static class SetSupportedProfileAccess implements InlinedProfileBag {
849893

850894
private final InlinedConditionProfile ensureCapacityGrow;

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
@@ -53,6 +53,7 @@ public static ContiguousJSObjectArray makeContiguousJSObjectArray(JSDynamicObjec
5353
int integrityLevel) {
5454
ContiguousJSObjectArray arrayType = createContiguousJSObjectArray().setIntegrityLevel(integrityLevel);
5555
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
56+
assert unusedElementsAreHoles(array, arrayOffset, usedLength);
5657
return arrayType;
5758
}
5859

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
@@ -52,6 +52,7 @@ public final class ContiguousObjectArray extends AbstractContiguousObjectArray {
5252
public static ContiguousObjectArray makeContiguousObjectArray(JSDynamicObject object, long length, Object[] array, long indexOffset, int arrayOffset, int usedLength, int integrityLevel) {
5353
ContiguousObjectArray arrayType = createContiguousObjectArray().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/HolesDoubleArray.java

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

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

146-
@Override
147-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
148-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
149-
}
150-
151146
@Override
152147
public boolean isSupported(JSDynamicObject object, long index) {
153148
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
@@ -65,7 +65,7 @@ public static HolesIntArray makeHolesIntArray(JSDynamicObject object, int length
6565
HolesIntArray arrayType = createHolesIntArray().setIntegrityLevel(integrityLevel);
6666
setArrayProperties(object, array, length, usedLength, indexOffset, arrayOffset);
6767
arraySetHoleCount(object, holeCount);
68-
assert holeCount == arrayType.countHoles(object) : String.format("holeCount, %d, differs from the actual count, %d", holeCount, arrayType.countHoles(object));
68+
assert arrayType.assertHoleCount(object);
6969
return arrayType;
7070
}
7171

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

164-
@Override
165-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
166-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
167-
}
168-
169164
@Override
170165
public HolesIntArray toHoles(JSDynamicObject object, long index, Object value) {
171166
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
@@ -65,7 +65,7 @@ public static HolesJSObjectArray makeHolesJSObjectArray(JSDynamicObject object,
6565
HolesJSObjectArray arrayType = createHolesJSObjectArray().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

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

157-
@Override
158-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
159-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
160-
}
161-
162157
@Override
163158
public int prepareInBounds(JSDynamicObject object, int index, Node node, SetSupportedProfileAccess profile) {
164159
return prepareInBoundsHoles(object, index, node, 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
@@ -64,7 +64,7 @@ public static HolesObjectArray makeHolesObjectArray(JSDynamicObject object, int
6464
HolesObjectArray arrayType = createHolesObjectArray().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

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

139-
@Override
140-
protected void incrementHolesCount(JSDynamicObject object, int offset) {
141-
arraySetHoleCount(object, arrayGetHoleCount(object) + offset);
142-
}
143-
144139
@Override
145140
public int prepareInBounds(JSDynamicObject object, int index, Node node, SetSupportedProfileAccess profile) {
146141
return prepareInBoundsHoles(object, index, node, profile);

0 commit comments

Comments
 (0)