Details
Description
The following code crashes only on arm64 (not tested on armv7) without JIT:
let o = []; o[10000] = 10; o[20000] = 20; for (let k in o) delete o[k]
but not
let o = {}; o.a = 10; o.b = 20; for (let k in o) delete o[k]
The difference is that in the first case, we are dealing with a SparseArray optimization.
The destructor of SparseArray shows that root() is nullable:
~SparseArray() { if (root()) freeTree(header.left, Q_ALIGNOF(SparseArrayNode)); } inline const SparseArrayNode *SparseArray::lowerBound(uint akey) const { const SparseArrayNode *lb = root()->lowerBound(akey); ... } inline SparseArrayNode *SparseArrayNode::lowerBound(uint akey) { SparseArrayNode *n = this; SparseArrayNode *last = nullptr; while (n) { ... } return last; }
In debug mode, it probably will never crash because root()->lowerBound(akey) never dereferences this if this is null.
However, in release mode, the compiler knows that this is not nullable, so it can optimize the first `while( n )` check to `do {} while( n )` which it does on arm64 at least