From e34920575d6dac353cb3d8a5d1b9c11ae05c5a8c Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 10 Jun 2019 16:49:47 +0000 Subject: Inline combined methods for NativeObject and UnboxedArrayObject accesses. --- js/src/jit/BaselineIC.cpp | 34 +++++----- js/src/jit/BaselineIC.h | 12 ++-- js/src/jit/BaselineInspector.cpp | 2 +- js/src/jit/BaselineInspector.h | 2 +- js/src/jit/MCallOptimize.cpp | 10 +-- js/src/jit/VMFunctions.cpp | 2 +- js/src/jsarray.cpp | 117 ++++++++++++++++++--------------- js/src/jsobj.cpp | 22 ++++--- js/src/vm/UnboxedObject-inl.h | 138 +++------------------------------------ 9 files changed, 115 insertions(+), 224 deletions(-) (limited to 'js') diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 1d230e083..28e263ac7 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -2373,8 +2373,8 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index, Shape* oldShape, uint32_t oldCapacity, uint32_t oldInitLength, bool* isAddingCaseOut, size_t* protoDepthOut) { - uint32_t initLength = GetAnyBoxedOrUnboxedInitializedLength(obj); - uint32_t capacity = GetAnyBoxedOrUnboxedCapacity(obj); + uint32_t initLength = obj->as().getDenseInitializedLength(); + uint32_t capacity = obj->as().getDenseCapacity(); *isAddingCaseOut = false; *protoDepthOut = 0; @@ -2464,8 +2464,8 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_ uint32_t oldCapacity = 0; uint32_t oldInitLength = 0; if (index.isInt32() && index.toInt32() >= 0) { - oldCapacity = GetAnyBoxedOrUnboxedCapacity(obj); - oldInitLength = GetAnyBoxedOrUnboxedInitializedLength(obj); + oldCapacity = obj->as().getDenseCapacity(); + oldInitLength = obj->as().getDenseInitializedLength(); } if (op == JSOP_INITELEM || op == JSOP_INITHIDDENELEM) { @@ -5762,14 +5762,14 @@ TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script, jsb } static bool -CopyArray(JSContext* cx, HandleObject obj, MutableHandleValue result) +CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result) { - uint32_t length = GetAnyBoxedOrUnboxedArrayLength(obj); - JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, obj, length, TenuredObject); + uint32_t length = arr->length(); + JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject); if (!nobj) return false; EnsureArrayGroupAnalyzed(cx, nobj); - CopyBoxedOrUnboxedDenseElements(cx, nobj, obj, 0, 0, length); + CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length); result.setObject(*nobj); return true; @@ -5801,26 +5801,22 @@ TryAttachStringSplit(JSContext* cx, ICCall_Fallback* stub, HandleScript script, RootedValue arr(cx); // Copy the array before storing in stub. - if (!CopyArray(cx, obj, &arr)) + if (!CopyArray(cx, obj.as(), &arr)) return false; // Atomize all elements of the array. - RootedObject arrObj(cx, &arr.toObject()); - uint32_t initLength = GetAnyBoxedOrUnboxedArrayLength(arrObj); + RootedArrayObject arrObj(cx, &arr.toObject().as()); + uint32_t initLength = arrObj->length(); for (uint32_t i = 0; i < initLength; i++) { - JSAtom* str = js::AtomizeString(cx, GetAnyBoxedOrUnboxedDenseElement(arrObj, i).toString()); + JSAtom* str = js::AtomizeString(cx, arrObj->getDenseElement(i).toString()); if (!str) return false; - if (!SetAnyBoxedOrUnboxedDenseElement(cx, arrObj, i, StringValue(str))) { - // The value could not be stored to an unboxed dense element. - return true; - } + arrObj->setDenseElementWithType(cx, i, StringValue(str)); } ICCall_StringSplit::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(), - script->pcToOffset(pc), str, sep, - arr); + script->pcToOffset(pc), str, sep, arrObj); ICStub* newStub = compiler.getStub(compiler.getStubSpace(script)); if (!newStub) return false; @@ -6705,7 +6701,7 @@ ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm) return true; } -typedef bool (*CopyArrayFn)(JSContext*, HandleObject, MutableHandleValue); +typedef bool (*CopyArrayFn)(JSContext*, HandleArrayObject, MutableHandleValue); static const VMFunction CopyArrayInfo = FunctionInfo(CopyArray, "CopyArray"); bool diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h index afbea3b69..901fca9cc 100644 --- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -2818,10 +2818,10 @@ class ICCall_StringSplit : public ICMonitoredStub uint32_t pcOffset_; GCPtrString expectedStr_; GCPtrString expectedSep_; - GCPtrObject templateObject_; + GCPtrArrayObject templateObject_; ICCall_StringSplit(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset, JSString* str, - JSString* sep, JSObject* templateObject) + JSString* sep, ArrayObject* templateObject) : ICMonitoredStub(ICStub::Call_StringSplit, stubCode, firstMonitorStub), pcOffset_(pcOffset), expectedStr_(str), expectedSep_(sep), templateObject_(templateObject) @@ -2848,7 +2848,7 @@ class ICCall_StringSplit : public ICMonitoredStub return expectedSep_; } - GCPtrObject& templateObject() { + GCPtrArrayObject& templateObject() { return templateObject_; } @@ -2858,7 +2858,7 @@ class ICCall_StringSplit : public ICMonitoredStub uint32_t pcOffset_; RootedString expectedStr_; RootedString expectedSep_; - RootedObject templateObject_; + RootedArrayObject templateObject_; MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm); @@ -2869,13 +2869,13 @@ class ICCall_StringSplit : public ICMonitoredStub public: Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset, HandleString str, - HandleString sep, HandleValue templateObject) + HandleString sep, HandleArrayObject templateObject) : ICCallStubCompiler(cx, ICStub::Call_StringSplit), firstMonitorStub_(firstMonitorStub), pcOffset_(pcOffset), expectedStr_(cx, str), expectedSep_(cx, sep), - templateObject_(cx, &templateObject.toObject()) + templateObject_(cx, templateObject) { } ICStub* getStub(ICStubSpace* space) { diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index 9c7b88fb2..bcb527516 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -580,7 +580,7 @@ BaselineInspector::getTemplateObjectForNative(jsbytecode* pc, Native native) bool BaselineInspector::isOptimizableCallStringSplit(jsbytecode* pc, JSString** strOut, JSString** sepOut, - JSObject** objOut) + ArrayObject** objOut) { if (!hasBaselineScript()) return false; diff --git a/js/src/jit/BaselineInspector.h b/js/src/jit/BaselineInspector.h index 4a1791798..1ed4b5547 100644 --- a/js/src/jit/BaselineInspector.h +++ b/js/src/jit/BaselineInspector.h @@ -113,7 +113,7 @@ class BaselineInspector bool hasSeenNonStringIterMore(jsbytecode* pc); MOZ_MUST_USE bool isOptimizableCallStringSplit(jsbytecode* pc, JSString** strOut, - JSString** sepOut, JSObject** objOut); + JSString** sepOut, ArrayObject** objOut); JSObject* getTemplateObject(jsbytecode* pc); JSObject* getTemplateObjectForNative(jsbytecode* pc, Native native); JSObject* getTemplateObjectForClassHook(jsbytecode* pc, const Class* clasp); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 748a70973..0d5779cee 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -522,7 +522,7 @@ IonBuilder::inlineArray(CallInfo& callInfo) // Make sure initLength matches the template object's length. This is // not guaranteed to be the case, for instance if we're inlining the // MConstant may come from an outer script. - if (initLength != GetAnyBoxedOrUnboxedArrayLength(templateObject)) + if (initLength != templateObject->as().length()) return InliningStatus_NotInlined; // Don't inline large allocations. @@ -1396,7 +1396,7 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo) // Check if exist a template object in stub. JSString* stringStr = nullptr; JSString* stringSep = nullptr; - JSObject* templateObject = nullptr; + ArrayObject* templateObject = nullptr; if (!inspector->isOptimizableCallStringSplit(pc, &stringStr, &stringSep, &templateObject)) return InliningStatus_NotInlined; @@ -1422,13 +1422,13 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo) if (!key.maybeTypes()->hasType(TypeSet::StringType())) return InliningStatus_NotInlined; - uint32_t initLength = GetAnyBoxedOrUnboxedArrayLength(templateObject); - if (GetAnyBoxedOrUnboxedInitializedLength(templateObject) != initLength) + uint32_t initLength = templateObject->length(); + if (templateObject->getDenseInitializedLength() != initLength) return InliningStatus_NotInlined; Vector arrayValues; for (uint32_t i = 0; i < initLength; i++) { - Value str = GetAnyBoxedOrUnboxedDenseElement(templateObject, i); + Value str = templateObject->getDenseElement(i); MOZ_ASSERT(str.toString()->isAtom()); MConstant* value = MConstant::New(alloc().fallible(), str, constraints()); if (!value) diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 0717bb86d..7b1e1cad6 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -339,7 +339,7 @@ ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval) bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length) { - *length = GetAnyBoxedOrUnboxedArrayLength(obj); + *length = obj->as().length(); DenseElementResult result = SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1, ShouldUpdateTypes::DontUpdate); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index a8bd3f028..da692c1b5 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -248,18 +248,20 @@ static bool GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index, bool* hole, MutableHandleValue vp) { - AssertGreaterThanZero(index); - if (index < GetAnyBoxedOrUnboxedInitializedLength(obj)) { - vp.set(GetAnyBoxedOrUnboxedDenseElement(obj, uint32_t(index))); - if (!vp.isMagic(JS_ELEMENTS_HOLE)) { - *hole = false; - return true; + if (obj->isNative()) { + NativeObject* nobj = &obj->as(); + if (index < nobj->getDenseInitializedLength()) { + vp.set(nobj->getDenseElement(size_t(index))); + if (!vp.isMagic(JS_ELEMENTS_HOLE)) { + *hole = false; + return true; + } } - } - if (obj->is()) { - if (obj->as().maybeGetElement(uint32_t(index), vp)) { - *hole = false; - return true; + if (nobj->is() && index <= UINT32_MAX) { + if (nobj->as().maybeGetElement(uint32_t(index), vp)) { + *hole = false; + return true; + } } } @@ -337,11 +339,11 @@ GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp) { MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj)); - if (length > GetBoxedOrUnboxedInitializedLength(aobj)) + if (length > aobj->as().getDenseInitializedLength()) return DenseElementResult::Incomplete; for (size_t i = 0; i < length; i++) { - vp[i] = GetBoxedOrUnboxedDenseElement(aobj, i); + vp[i] = aobj->as().getDenseElement(i); // No other indexed properties so hole => undefined. if (vp[i].isMagic(JS_ELEMENTS_HOLE)) @@ -849,7 +851,7 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject* obj) if (ObjectMayHaveExtraIndexedOwnProperties(obj)) return true; - if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0) + if (obj->as().getDenseInitializedLength() != 0) return true; } while (true); } @@ -1068,12 +1070,13 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_ // length > initLength we rely on the second loop to add the // other elements. MOZ_ASSERT(*numProcessed == 0); - uint32_t initLength = Min(GetBoxedOrUnboxedInitializedLength(obj), length); + uint32_t initLength = Min(obj->as().getDenseInitializedLength(), + length); while (*numProcessed < initLength) { if (!CheckForInterrupt(cx)) return DenseElementResult::Failure; - Value elem = GetBoxedOrUnboxedDenseElement(obj, *numProcessed); + Value elem = obj->as().getDenseElement(*numProcessed); if (elem.isString()) { if (!sb.append(elem.toString())) @@ -1207,11 +1210,14 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp) // An optimized version of a special case of steps 7-11: when length==1 and // the 0th element is a string, ToString() of that element is a no-op and // so it can be immediately returned as the result. - if (length == 1 && GetAnyBoxedOrUnboxedInitializedLength(obj) == 1) { - Value elem0 = GetAnyBoxedOrUnboxedDenseElement(obj, 0); - if (elem0.isString()) { - args.rval().set(elem0); - return true; + if (length == 1 && obj->isNative()) { + NativeObject* nobj = &obj->as(); + if (nobj->getDenseInitializedLength() == 1) { + Value elem0 = nobj->getDenseElement(0); + if (elem0.isString()) { + args.rval().set(elem0); + return true; + } } } @@ -1359,7 +1365,7 @@ DenseElementResult ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length) { /* An empty array or an array with no elements is already reversed. */ - if (length == 0 || GetBoxedOrUnboxedInitializedLength(obj) == 0) + if (length == 0 || obj->as().getDenseInitializedLength() == 0) return DenseElementResult::Success; if (obj->as().denseElementsAreFrozen()) @@ -1385,15 +1391,15 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length) uint32_t lo = 0, hi = length - 1; for (; lo < hi; lo++, hi--) { - origlo = GetBoxedOrUnboxedDenseElement(obj, lo); - orighi = GetBoxedOrUnboxedDenseElement(obj, hi); - SetBoxedOrUnboxedDenseElementNoTypeChange(obj, lo, orighi); + origlo = obj->as().getDenseElement(lo); + orighi = obj->as().getDenseElement(hi); + obj->as().setDenseElement(lo, orighi); if (orighi.isMagic(JS_ELEMENTS_HOLE) && !SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo))) { return DenseElementResult::Failure; } - SetBoxedOrUnboxedDenseElementNoTypeChange(obj, hi, origlo); + obj->as().setDenseElement(hi, origlo); if (origlo.isMagic(JS_ELEMENTS_HOLE) && !SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi))) { @@ -2074,14 +2080,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp) uint32_t newlength = length + args.length(); args.rval().setNumber(newlength); - // SetOrExtendBoxedOrUnboxedDenseElements takes care of updating the - // length for boxed and unboxed arrays. Handle updates to the length of - // non-arrays here. - bool isArray; - if (!IsArray(cx, obj, &isArray)) - return false; - - if (!isArray) + // Handle updates to the length of non-arrays here. + if (!obj->is()) return SetLengthProperty(cx, obj, newlength); return true; @@ -2141,14 +2141,15 @@ template static inline DenseElementResult ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj) { - MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj)); + MOZ_ASSERT(obj->isNative()); + + size_t initlen = obj->as().getDenseInitializedLength(); /* * At this point the length and initialized length have already been * decremented and the result fetched, so just shift the array elements * themselves. */ - size_t initlen = GetBoxedOrUnboxedInitializedLength(obj); obj->as().moveDenseElementsNoPreBarrier(0, 1, initlen); return DenseElementResult::Success; @@ -2165,6 +2166,15 @@ js::ArrayShiftMoveElements(JSObject* obj) JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success); } +static inline void +SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen) +{ + size_t oldInitlen = obj->getDenseInitializedLength(); + obj->setDenseInitializedLength(initlen); + if (initlen < oldInitlen) + obj->shrinkElements(cx, initlen); +} + template DenseElementResult ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval) @@ -2179,11 +2189,11 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval) if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED))) return DenseElementResult::Incomplete; - size_t initlen = GetBoxedOrUnboxedInitializedLength(obj); + size_t initlen = obj->as().getDenseInitializedLength(); if (initlen == 0) return DenseElementResult::Incomplete; - rval.set(GetBoxedOrUnboxedDenseElement(obj, 0)); + rval.set(obj->as().getDenseElement(0)); if (rval.isMagic(JS_ELEMENTS_HOLE)) rval.setUndefined(); @@ -2191,7 +2201,7 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval) if (result != DenseElementResult::Success) return result; - SetBoxedOrUnboxedInitializedLength(cx, obj, initlen - 1); + SetInitializedLength(cx, obj.as(), initlen - 1); return DenseElementResult::Success; } @@ -2364,7 +2374,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co return false; /* If it's a frozen array, always pick the slow path */ - if (arr->is() && arr->as().denseElementsAreFrozen()) + if (arr->as().denseElementsAreFrozen()) return false; /* @@ -2396,7 +2406,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co * is subsumed by the initializedLength comparison.) */ return !ObjectMayHaveExtraIndexedProperties(arr) && - startingIndex + count <= GetAnyBoxedOrUnboxedInitializedLength(arr); + startingIndex + count <= arr->as().getDenseInitializedLength(); } /* ES 2016 draft Mar 25, 2016 22.1.3.26. */ @@ -2541,7 +2551,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI return false; /* Steps 15.c-d. */ - SetBoxedOrUnboxedInitializedLength(cx, obj, finalLength); + SetInitializedLength(cx, obj.as(), finalLength); } else { /* * This is all very slow if the length is very large. We don't yet @@ -2629,7 +2639,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI return false; /* Steps 16.a-b. */ - SetBoxedOrUnboxedInitializedLength(cx, obj, len + itemCount - actualDeleteCount); + SetInitializedLength(cx, obj.as(), len + itemCount - actualDeleteCount); } else { RootedValue fromValue(cx); for (double k = len - actualDeleteCount; k > actualStart; k--) { @@ -2851,7 +2861,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be begin = end; if (!ObjectMayHaveExtraIndexedProperties(obj)) { - size_t initlen = GetAnyBoxedOrUnboxedInitializedLength(obj); + size_t initlen = obj->as().getDenseInitializedLength(); size_t count = 0; if (initlen > begin) count = Min(initlen - begin, end - begin); @@ -2859,7 +2869,9 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count)); if (!narr) return false; - SetAnyBoxedOrUnboxedArrayLength(cx, narr, end - begin); + + MOZ_ASSERT(count >= narr->as().length()); + narr->as().setLength(cx, count); if (count) { DebugOnly result = @@ -2991,7 +3003,7 @@ template DenseElementResult ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result) { - int32_t length = GetAnyBoxedOrUnboxedArrayLength(obj); + int32_t length = obj->as().length(); uint32_t begin = NormalizeSliceTerm(beginArg, length); uint32_t end = NormalizeSliceTerm(endArg, length); @@ -2999,18 +3011,19 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en if (begin > end) begin = end; - size_t initlen = GetBoxedOrUnboxedInitializedLength(obj); + size_t initlen = obj->as().getDenseInitializedLength(); + size_t count = Min(initlen - begin, end - begin); if (initlen > begin) { - size_t count = Min(initlen - begin, end - begin); if (count) { - DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements(cx, result, count); - if (rv != DenseElementResult::Success) - return rv; + if (!result->as().ensureElements(cx, count)) + return DenseElementResult::Failure; CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count); } } - SetAnyBoxedOrUnboxedArrayLength(cx, result, end - begin); + MOZ_ASSERT(count >= result->as().length()); + result->as().setLength(cx, count); + return DenseElementResult::Success; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c26a42f48..deaa1d53e 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1143,19 +1143,18 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle proto) } static bool -GetScriptArrayObjectElements(JSContext* cx, HandleObject obj, MutableHandle> values) +GetScriptArrayObjectElements(JSContext* cx, HandleArrayObject arr, MutableHandle> values) { - MOZ_ASSERT(!obj->isSingleton()); - MOZ_ASSERT(obj->is()); - MOZ_ASSERT(!obj->isIndexed()); + MOZ_ASSERT(!arr->isSingleton()); + MOZ_ASSERT(!arr->isIndexed()); - size_t length = GetAnyBoxedOrUnboxedArrayLength(obj); + size_t length = arr->length(); if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), length)) return false; - size_t initlen = GetAnyBoxedOrUnboxedInitializedLength(obj); + size_t initlen = arr->getDenseInitializedLength(); for (size_t i = 0; i < initlen; i++) - values[i].set(GetAnyBoxedOrUnboxedDenseElement(obj, i)); + values[i].set(arr->getDenseElement(i)); return true; } @@ -1212,7 +1211,7 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin if (obj->is()) { Rooted> values(cx, GCVector(cx)); - if (!GetScriptArrayObjectElements(cx, obj, &values)) + if (!GetScriptArrayObjectElements(cx, obj.as(), &values)) return nullptr; // Deep clone any elements. @@ -1339,8 +1338,11 @@ js::XDRObjectLiteral(XDRState* xdr, MutableHandleObject obj) if (isArray) { Rooted> values(cx, GCVector(cx)); - if (mode == XDR_ENCODE && !GetScriptArrayObjectElements(cx, obj, &values)) - return false; + if (mode == XDR_ENCODE) { + RootedArrayObject arr(cx, &obj->as()); + if (!GetScriptArrayObjectElements(cx, arr, &values)) + return false; + } uint32_t initialized; if (mode == XDR_ENCODE) diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h index 499f3604b..b308464fe 100644 --- a/js/src/vm/UnboxedObject-inl.h +++ b/js/src/vm/UnboxedObject-inl.h @@ -172,130 +172,10 @@ UnboxedPlainObject::layout() const return group()->unboxedLayout(); } -///////////////////////////////////////////////////////////////////// -// Combined methods for NativeObject and UnboxedArrayObject accesses. -///////////////////////////////////////////////////////////////////// - -static inline bool -HasAnyBoxedOrUnboxedDenseElements(JSObject* obj) -{ - return obj->isNative(); -} - -static inline size_t -GetAnyBoxedOrUnboxedInitializedLength(JSObject* obj) -{ - if (obj->isNative()) - return obj->as().getDenseInitializedLength(); - return 0; -} - -static inline size_t -GetAnyBoxedOrUnboxedCapacity(JSObject* obj) -{ - if (obj->isNative()) - return obj->as().getDenseCapacity(); - return 0; -} - -static inline Value -GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index) -{ - return obj->as().getDenseElement(index); -} - -static inline size_t -GetAnyBoxedOrUnboxedArrayLength(JSObject* obj) -{ - return obj->as().length(); -} - -static inline void -SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length) -{ - MOZ_ASSERT(length >= obj->as().length()); - obj->as().setLength(cx, length); -} - -static inline bool -SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value) -{ - obj->as().setDenseElementWithType(cx, index, value); - return true; -} - -static inline bool -InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value) -{ - obj->as().initDenseElementWithType(cx, index, value); - return true; -} - ///////////////////////////////////////////////////////////////////// // Template methods for NativeObject and UnboxedArrayObject accesses. ///////////////////////////////////////////////////////////////////// -static inline JSValueType -GetBoxedOrUnboxedType(JSObject* obj) -{ - return JSVAL_TYPE_MAGIC; -} - -static inline bool -HasBoxedOrUnboxedDenseElements(JSObject* obj) -{ - return obj->isNative(); -} - -static inline size_t -GetBoxedOrUnboxedInitializedLength(JSObject* obj) -{ - return obj->as().getDenseInitializedLength(); -} - -static inline DenseElementResult -SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen) -{ - size_t oldInitlen = GetBoxedOrUnboxedInitializedLength(obj); - obj->as().setDenseInitializedLength(initlen); - if (initlen < oldInitlen) - obj->as().shrinkElements(cx, initlen); - return DenseElementResult::Success; -} - -static inline size_t -GetBoxedOrUnboxedCapacity(JSObject* obj) -{ - return obj->as().getDenseCapacity(); -} - -static inline Value -GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index) -{ - return obj->as().getDenseElement(index); -} - -static inline void -SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value) -{ - obj->as().setDenseElement(index, value); -} - -static inline bool -SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value) -{ - obj->as().setDenseElementWithType(cx, index, value); - return true; -} - -static inline DenseElementResult -EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count) -{ - if (!obj->as().ensureElements(cx, count)) - return DenseElementResult::Failure; - return DenseElementResult::Success; -} - static inline DenseElementResult SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj, uint32_t start, const Value* vp, uint32_t count, @@ -334,7 +214,7 @@ static inline DenseElementResult MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart, uint32_t length) { - MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj)); + MOZ_ASSERT(obj->isNative()); if (obj->as().denseElementsAreFrozen()) return DenseElementResult::Incomplete; @@ -350,13 +230,13 @@ static inline DenseElementResult CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src, uint32_t dstStart, uint32_t srcStart, uint32_t length) { - MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(src)); - MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(dst)); - MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(dst) == dstStart); - MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(src) >= srcStart + length); - MOZ_ASSERT(GetBoxedOrUnboxedCapacity(dst) >= dstStart + length); + MOZ_ASSERT(src->isNative()); + MOZ_ASSERT(dst->isNative()); + MOZ_ASSERT(dst->as().getDenseInitializedLength() == dstStart); + MOZ_ASSERT(src->as().getDenseInitializedLength() >= srcStart + length); + MOZ_ASSERT(dst->as().getDenseCapacity() >= dstStart + length); - SetBoxedOrUnboxedInitializedLength(cx, dst, dstStart + length); + dst->as().setDenseInitializedLength(dstStart + length); const Value* vp = src->as().getDenseElements() + srcStart; dst->as().initDenseElements(dstStart, vp, length); @@ -383,7 +263,7 @@ template DenseElementResult CallBoxedOrUnboxedSpecialization(F f, JSObject* obj) { - if (!HasAnyBoxedOrUnboxedDenseElements(obj)) + if (!obj->isNative()) return DenseElementResult::Incomplete; return f. DEPENDENT_TEMPLATE_HINT operator()(); } @@ -393,7 +273,7 @@ template DenseElementResult CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2) { - if (!HasAnyBoxedOrUnboxedDenseElements(obj1) || !HasAnyBoxedOrUnboxedDenseElements(obj2)) + if (!obj1->isNative() || !obj2->isNative()) return DenseElementResult::Incomplete; return f. DEPENDENT_TEMPLATE_HINT operator()(); -- cgit v1.2.3