Closed
Bug 690622
Opened 13 years ago
Closed 5 years ago
JSObject::moveDenseArrayElements doesn't get along well with holes
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
WORKSFORME
People
(Reporter: Waldo, Unassigned)
Details
js> var arr = [0, 1, 2, 3, 4, , 6]; js> for (var p in arr) { print(p); if (p === "1") arr.shift(); } 0 1 2 3 4 js> arr [1, 2, 3, 4, , 6] Quoth ES5: "If a property that has not yet been visited during enumeration is deleted, then it will not be visited." The shift call, in shifting elements toward zero by one, will delete index 4 (see the hole in |arr| above). This happens before index 4 is enumerated. Therefore, 4 should not be printed here. But it is, because we're not suppressing deleted properties because the deletion is implicit in the moveDenseArrayElements memmove. It seems to me that fundamentally, moveDenseArrayElements is unsound with respect to non-packed arrays, unless the caller actually goes through the moved elements afterward and suppresses any deleted elements. No caller (shift, unshift, splice) does this now. I'll probably end up making sure splice handles this properly in bug 668024. But the other two will need some sort of changing. And perhaps this just demonstrates that moveDenseArrayElements is an unwise idea, or that it should assert that it's being used on a packed array. Thoughts people have on this mess, and what to do about it, are appreciated. For what it's worth, none of Opera, Safari, Chrome, or IE have this bug, at least as far as the above testcase is concerned -- none print 4. (They don't all agree on printing 5, but ES5 permits either behavior there, so that's not a bug.)
Reporter | ||
Comment 1•13 years ago
|
||
It turns out type inference adds a useful frob to check whether an object (or rather, all objects with a given latent type) is being enumerated. arr->getType(cx)->hasAllFlags(OBJECT_FLAG_ITERATED)) should give the info necessary to de-optimize away from moveDenseStuff in those cases. (The flag is set regardless whether type inference is enabled or not.) This trick is used in bug 694210 to make splice deletion-safe with respect to moveDenseStuff. So with that, this becomes reasonably tractable without having to add a loop checking for holes or anything -- just check for enumeration, and if so fall back to the really slow path, not just to a slightly-less-fast path.
Assignee | ||
Updated•10 years ago
|
Assignee: general → nobody
Comment 2•5 years ago
|
||
Resolving as WFM:
js> var arr = [0, 1, 2, 3, 4, , 6];
js> for (var p in arr) {
print(p);
if (p === "1")
arr.shift();
}
0
1
2
3
js> arr
[1, 2, 3, 4, , 6]
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → WORKSFORME
You need to log in
before you can comment on or make changes to this bug.
Description
•