From 43badc67e619949ef83c3c55f18252b4fae93275 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 30 Jan 2012 17:13:07 -0800 Subject: [PATCH] Bug 714616: fix write barrier in Array.shift, r=billm --HG-- extra : rebase_source : 2fd10ab4cc3a93aee188ef6f9bbc388f66da2d37 --- js/src/jit-test/tests/basic/bug714616.js | 8 ++++++++ js/src/jsarray.cpp | 4 ++-- js/src/jsobj.h | 1 + js/src/jsobjinlines.h | 9 ++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug714616.js diff --git a/js/src/jit-test/tests/basic/bug714616.js b/js/src/jit-test/tests/basic/bug714616.js new file mode 100644 index 00000000000..706594d0559 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug714616.js @@ -0,0 +1,8 @@ +array1 = new Array(); +size = 10; +for (i = 0; i < size; (array1.length)++) +{ + array1.push(array1.shift()); + ++i +} + diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index abd3dfd1f2f..d925a3b0e11 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2506,7 +2506,7 @@ mjit::stubs::ArrayShift(VMFrame &f) * themselves. */ uint32_t initlen = obj->getDenseArrayInitializedLength(); - obj->moveDenseArrayElements(0, 1, initlen); + obj->moveDenseArrayElementsUnbarriered(0, 1, initlen); } #endif /* JS_METHODJIT */ @@ -2533,7 +2533,7 @@ js::array_shift(JSContext *cx, uintN argc, Value *vp) args.rval() = obj->getDenseArrayElement(0); if (args.rval().isMagic(JS_ARRAY_HOLE)) args.rval().setUndefined(); - obj->moveDenseArrayElements(0, 1, length); + obj->moveDenseArrayElements(0, 1, obj->getDenseArrayInitializedLength() - 1); obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1); obj->setArrayLength(cx, length); if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length))) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 0052fceceed..92e148de4f4 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1066,6 +1066,7 @@ struct JSObject : js::gc::Cell inline void copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count); inline void initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count); inline void moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count); + inline void moveDenseArrayElementsUnbarriered(uintN dstStart, uintN srcStart, uintN count); inline bool denseArrayHasInlineSlots() const; /* Packed information for this array. */ diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index d22bffa2794..b80aada2aee 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -607,7 +607,7 @@ inline void JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count) { JS_ASSERT(dstStart + count <= getDenseArrayCapacity()); - JS_ASSERT(srcStart + count <= getDenseArrayCapacity()); + JS_ASSERT(srcStart + count <= getDenseArrayInitializedLength()); /* * Use a custom write barrier here since it's performance sensitive. We @@ -626,6 +626,13 @@ JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count) memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value)); } +inline void +JSObject::moveDenseArrayElementsUnbarriered(uintN dstStart, uintN srcStart, uintN count) +{ + JS_ASSERT(!compartment()->needsBarrier()); + memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value)); +} + inline bool JSObject::denseArrayHasInlineSlots() const {