diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 4ae67555e3b..7a880c86b51 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4700,6 +4700,8 @@ JS_SetReservedSlot(RawObject obj, uint32_t index, RawValue value) JS_PUBLIC_API(JSObject *) JS_NewArrayObject(JSContext *cx, int length, jsval *vector) { + AutoArrayRooter tvr(cx, length, vector); + JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 68d0b783d9b..1c887912db4 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2603,8 +2603,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp) /* Steps 2, 8-9. */ RootedObject arr(cx); if (CanOptimizeForDenseStorage(obj, actualStart, actualDeleteCount, cx)) { - arr = NewDenseCopiedArray(cx, actualDeleteCount, - obj->getDenseArrayElements() + actualStart); + arr = NewDenseCopiedArray(cx, actualDeleteCount, obj, actualStart); if (!arr) return false; TryReuseArrayType(obj, arr); @@ -2803,9 +2802,8 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp) uint32_t length; if (aobj->isDenseArray()) { length = aobj->getArrayLength(); - const Value *vector = aobj->getDenseArrayElements(); uint32_t initlen = aobj->getDenseArrayInitializedLength(); - nobj = NewDenseCopiedArray(cx, initlen, vector); + nobj = NewDenseCopiedArray(cx, initlen, aobj, 0); if (!nobj) return JS_FALSE; TryReuseArrayType(aobj, nobj); @@ -2911,7 +2909,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp) if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() && !js_PrototypeHasIndexedProperties(obj)) { - nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin); + nobj = NewDenseCopiedArray(cx, end - begin, obj, begin); if (!nobj) return JS_FALSE; TryReuseArrayType(obj, nobj); @@ -3708,17 +3706,15 @@ mjit::stubs::NewDenseUnallocatedArray(VMFrame &f, uint32_t length) #endif JSObject * -NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *vp, RawObject proto /* = NULL */) +NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset, RawObject proto /* = NULL */) { - // XXX vp may be an internal pointer to an object's dense array elements. - SkipRoot skip(cx, &vp); - JSObject* obj = NewArray(cx, length, proto); if (!obj) return NULL; JS_ASSERT(obj->getDenseArrayCapacity() >= length); + const Value* vp = src->getDenseArrayElements() + elementOffset; obj->setDenseArrayInitializedLength(vp ? length : 0); if (vp) @@ -3727,6 +3723,24 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *vp, RawObject p return obj; } +// values must point at already-rooted Value objects +JSObject * +NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObject proto /* = NULL */) +{ + JSObject* obj = NewArray(cx, length, proto); + if (!obj) + return NULL; + + JS_ASSERT(obj->getDenseArrayCapacity() >= length); + + obj->setDenseArrayInitializedLength(values ? length : 0); + + if (values) + obj->initDenseArrayElements(0, values, length); + + return obj; +} + JSObject * NewSlowEmptyArray(JSContext *cx) { diff --git a/js/src/jsarray.h b/js/src/jsarray.h index a98d0fc9083..ddcd9d9d646 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -63,9 +63,13 @@ NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL); extern JSObject * JS_FASTCALL NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL); -/* Create a dense array with a copy of vp. */ +/* Create a dense array with a copy of the dense array elements in src. */ extern JSObject * -NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *vp, RawObject proto = NULL); +NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset, RawObject proto = NULL); + +/* Create a dense array from the given array values, which must be rooted */ +extern JSObject * +NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObject proto = NULL); /* Create a sparse array. */ extern JSObject * diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index eeccda31be6..cfd552e3b5a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2757,8 +2757,8 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp) /* Step 10. */ if (!sepDefined) { - Value v = StringValue(str); - JSObject *aobj = NewDenseCopiedArray(cx, 1, &v); + RootedValue v(cx, StringValue(str)); + JSObject *aobj = NewDenseCopiedArray(cx, 1, v.address()); if (!aobj) return false; aobj->setType(type); diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 227f971a1ff..0ded7f292a4 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1710,7 +1710,7 @@ DebugScopes::onPopCall(StackFrame *fp, JSContext *cx) * aliasing. This unnecessarily includes aliased variables * but it simplifies later indexing logic. */ - StackFrame::CopyVector vec; + AutoValueVector vec(cx); if (!fp->copyRawFrameSlots(&vec) || vec.length() == 0) return; diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index a3f4693dec4..e7675f499d1 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -217,7 +217,7 @@ StackFrame::pcQuadratic(const ContextStack &stack, size_t maxDepth) } bool -StackFrame::copyRawFrameSlots(CopyVector *vec) +StackFrame::copyRawFrameSlots(AutoValueVector *vec) { if (!vec->resize(numFormalArgs() + script()->nfixed)) return false; diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index f4a7813cdd7..5d15fb5af1e 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -497,8 +497,7 @@ class StackFrame inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING); template inline void forEachUnaliasedActual(Op op); - typedef Vector CopyVector; - bool copyRawFrameSlots(CopyVector *v); + bool copyRawFrameSlots(AutoValueVector *v); inline unsigned numFormalArgs() const; inline unsigned numActualArgs() const;