From 3b0ec28ebaa3bf14482f02102bbe5fedd7febe0a Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Fri, 31 Aug 2012 21:33:04 -0700 Subject: [PATCH] Bug 787282 - Initialize all slots in ParallelArray constructor when GC might trigger (r=billm) --- js/src/builtin/ParallelArray.cpp | 23 ++++++++++++------- .../jit-test/tests/parallelarray/bug787282.js | 12 ++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 js/src/jit-test/tests/parallelarray/bug787282.js diff --git a/js/src/builtin/ParallelArray.cpp b/js/src/builtin/ParallelArray.cpp index d2d37fe61163..09cefb203847 100644 --- a/js/src/builtin/ParallelArray.cpp +++ b/js/src/builtin/ParallelArray.cpp @@ -121,10 +121,11 @@ NewDenseCopiedArrayWithType(JSContext *cx, uint32_t length, HandleObject source) uint32_t srclen; uint32_t copyUpTo; - // Optimize for the common case: if we have a dense array source, copy - // whatever we can, truncating to length, and filling the rest with - // undefineds. Holes are converted to undefineds eagerly. if (source->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, source)) { + // Optimize for the common case: if we have a dense array source, copy + // whatever we can, truncating to length. This path doesn't trigger + // GC, so we don't need to initialize all the array's slots before + // copying. const Value *srcvp = source->getDenseArrayElements(); srclen = source->getDenseArrayInitializedLength(); @@ -136,7 +137,17 @@ NewDenseCopiedArrayWithType(JSContext *cx, uint32_t length, HandleObject source) elem = srcvp[i].isMagic(JS_ARRAY_HOLE) ? UndefinedValue() : srcvp[i]; buffer->initDenseArrayElementWithType(cx, i, elem); } + + // Fill the rest with undefineds. + for (uint32_t i = copyUpTo; i < length; i++) + buffer->initDenseArrayElementWithType(cx, i, UndefinedValue()); } else { + // This path might GC. The GC expects an object's slots to be + // initialized, so we have to make sure all the array's slots are + // initialized. + for (uint32_t i = 0; i < length; i++) + buffer->initDenseArrayElementWithType(cx, i, UndefinedValue()); + IndexInfo siv(cx); RootedParallelArrayObject sourcePA(cx); @@ -149,14 +160,10 @@ NewDenseCopiedArrayWithType(JSContext *cx, uint32_t length, HandleObject source) for (uint32_t i = 0; i < copyUpTo; i++) { if (!GetElementFromArrayLikeObject(cx, source, sourcePA, siv, i, &elem)) return NULL; - buffer->initDenseArrayElementWithType(cx, i, elem); + buffer->setDenseArrayElementWithType(cx, i, elem); } } - // Fill the rest with undefineds. - for (uint32_t i = copyUpTo; i < length; i++) - buffer->initDenseArrayElementWithType(cx, i, UndefinedValue()); - if (!SetArrayNewType(cx, buffer)) return NULL; diff --git a/js/src/jit-test/tests/parallelarray/bug787282.js b/js/src/jit-test/tests/parallelarray/bug787282.js new file mode 100644 index 000000000000..8ca4a154b923 --- /dev/null +++ b/js/src/jit-test/tests/parallelarray/bug787282.js @@ -0,0 +1,12 @@ +// |jit-test| error: TypeError + +var protoArr = Proxy.create({}, null); +void (Array.prototype.__proto__ = protoArr); +gczeal(2); +function testCopyBigArray() { + var a = new Array(10000); + for (var cnt = 0; cnt < a.length; cnt+=2) { + var p = new ParallelArray(a); + } +} +testCopyBigArray();