mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 08:18:41 +09:00
Inline combined methods for NativeObject and UnboxedArrayObject accesses.
This commit is contained in:
parent
54b6b407a9
commit
1176a9ace1
9 changed files with 115 additions and 224 deletions
|
|
@ -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<NativeObject>().getDenseInitializedLength();
|
||||
uint32_t capacity = obj->as<NativeObject>().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<NativeObject>().getDenseCapacity();
|
||||
oldInitLength = obj->as<NativeObject>().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<ArrayObject>(), &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<ArrayObject>());
|
||||
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<CopyArrayFn>(CopyArray, "CopyArray");
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<ArrayObject>().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<MConstant*, 0, SystemAllocPolicy> 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)
|
||||
|
|
|
|||
|
|
@ -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<ArrayObject>().length();
|
||||
DenseElementResult result =
|
||||
SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
|
||||
ShouldUpdateTypes::DontUpdate);
|
||||
|
|
|
|||
|
|
@ -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<NativeObject>();
|
||||
if (index < nobj->getDenseInitializedLength()) {
|
||||
vp.set(nobj->getDenseElement(size_t(index)));
|
||||
if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
*hole = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj->is<ArgumentsObject>()) {
|
||||
if (obj->as<ArgumentsObject>().maybeGetElement(uint32_t(index), vp)) {
|
||||
*hole = false;
|
||||
return true;
|
||||
if (nobj->is<ArgumentsObject>() && index <= UINT32_MAX) {
|
||||
if (nobj->as<ArgumentsObject>().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<NativeObject>().getDenseInitializedLength())
|
||||
return DenseElementResult::Incomplete;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
vp[i] = GetBoxedOrUnboxedDenseElement(aobj, i);
|
||||
vp[i] = aobj->as<NativeObject>().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<NativeObject>().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<uint32_t>(GetBoxedOrUnboxedInitializedLength(obj), length);
|
||||
uint32_t initLength = Min<uint32_t>(obj->as<NativeObject>().getDenseInitializedLength(),
|
||||
length);
|
||||
while (*numProcessed < initLength) {
|
||||
if (!CheckForInterrupt(cx))
|
||||
return DenseElementResult::Failure;
|
||||
|
||||
Value elem = GetBoxedOrUnboxedDenseElement(obj, *numProcessed);
|
||||
Value elem = obj->as<NativeObject>().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<NativeObject>();
|
||||
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<NativeObject>().getDenseInitializedLength() == 0)
|
||||
return DenseElementResult::Success;
|
||||
|
||||
if (obj->as<NativeObject>().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<NativeObject>().getDenseElement(lo);
|
||||
orighi = obj->as<NativeObject>().getDenseElement(hi);
|
||||
obj->as<NativeObject>().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<NativeObject>().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<ArrayObject>())
|
||||
return SetLengthProperty(cx, obj, newlength);
|
||||
|
||||
return true;
|
||||
|
|
@ -2141,14 +2141,15 @@ template <JSValueType Type>
|
|||
static inline DenseElementResult
|
||||
ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj));
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
size_t initlen = obj->as<NativeObject>().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<NativeObject>().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 <JSValueType Type>
|
||||
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<NativeObject>().getDenseInitializedLength();
|
||||
if (initlen == 0)
|
||||
return DenseElementResult::Incomplete;
|
||||
|
||||
rval.set(GetBoxedOrUnboxedDenseElement(obj, 0));
|
||||
rval.set(obj->as<NativeObject>().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<NativeObject>(), 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<ArrayObject>() && arr->as<ArrayObject>().denseElementsAreFrozen())
|
||||
if (arr->as<ArrayObject>().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<NativeObject>().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<NativeObject>(), 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<NativeObject>(), 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<NativeObject>().getDenseInitializedLength();
|
||||
size_t count = 0;
|
||||
if (initlen > begin)
|
||||
count = Min<size_t>(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<ArrayObject>().length());
|
||||
narr->as<ArrayObject>().setLength(cx, count);
|
||||
|
||||
if (count) {
|
||||
DebugOnly<DenseElementResult> result =
|
||||
|
|
@ -2991,7 +3003,7 @@ template <JSValueType Type>
|
|||
DenseElementResult
|
||||
ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result)
|
||||
{
|
||||
int32_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
|
||||
int32_t length = obj->as<ArrayObject>().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<NativeObject>().getDenseInitializedLength();
|
||||
size_t count = Min<size_t>(initlen - begin, end - begin);
|
||||
if (initlen > begin) {
|
||||
size_t count = Min<size_t>(initlen - begin, end - begin);
|
||||
if (count) {
|
||||
DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements(cx, result, count);
|
||||
if (rv != DenseElementResult::Success)
|
||||
return rv;
|
||||
if (!result->as<ArrayObject>().ensureElements(cx, count))
|
||||
return DenseElementResult::Failure;
|
||||
CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count);
|
||||
}
|
||||
}
|
||||
|
||||
SetAnyBoxedOrUnboxedArrayLength(cx, result, end - begin);
|
||||
MOZ_ASSERT(count >= result->as<ArrayObject>().length());
|
||||
result->as<ArrayObject>().setLength(cx, count);
|
||||
|
||||
return DenseElementResult::Success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1143,19 +1143,18 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
|
|||
}
|
||||
|
||||
static bool
|
||||
GetScriptArrayObjectElements(JSContext* cx, HandleObject obj, MutableHandle<GCVector<Value>> values)
|
||||
GetScriptArrayObjectElements(JSContext* cx, HandleArrayObject arr, MutableHandle<GCVector<Value>> values)
|
||||
{
|
||||
MOZ_ASSERT(!obj->isSingleton());
|
||||
MOZ_ASSERT(obj->is<ArrayObject>());
|
||||
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<ArrayObject>()) {
|
||||
Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
|
||||
if (!GetScriptArrayObjectElements(cx, obj, &values))
|
||||
if (!GetScriptArrayObjectElements(cx, obj.as<ArrayObject>(), &values))
|
||||
return nullptr;
|
||||
|
||||
// Deep clone any elements.
|
||||
|
|
@ -1339,8 +1338,11 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
|
||||
if (isArray) {
|
||||
Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
|
||||
if (mode == XDR_ENCODE && !GetScriptArrayObjectElements(cx, obj, &values))
|
||||
return false;
|
||||
if (mode == XDR_ENCODE) {
|
||||
RootedArrayObject arr(cx, &obj->as<ArrayObject>());
|
||||
if (!GetScriptArrayObjectElements(cx, arr, &values))
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t initialized;
|
||||
if (mode == XDR_ENCODE)
|
||||
|
|
|
|||
|
|
@ -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<NativeObject>().getDenseInitializedLength();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
GetAnyBoxedOrUnboxedCapacity(JSObject* obj)
|
||||
{
|
||||
if (obj->isNative())
|
||||
return obj->as<NativeObject>().getDenseCapacity();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline Value
|
||||
GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
|
||||
{
|
||||
return obj->as<NativeObject>().getDenseElement(index);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
GetAnyBoxedOrUnboxedArrayLength(JSObject* obj)
|
||||
{
|
||||
return obj->as<ArrayObject>().length();
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length)
|
||||
{
|
||||
MOZ_ASSERT(length >= obj->as<ArrayObject>().length());
|
||||
obj->as<ArrayObject>().setLength(cx, length);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
|
||||
{
|
||||
obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
|
||||
{
|
||||
obj->as<NativeObject>().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<NativeObject>().getDenseInitializedLength();
|
||||
}
|
||||
|
||||
static inline DenseElementResult
|
||||
SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
|
||||
{
|
||||
size_t oldInitlen = GetBoxedOrUnboxedInitializedLength(obj);
|
||||
obj->as<NativeObject>().setDenseInitializedLength(initlen);
|
||||
if (initlen < oldInitlen)
|
||||
obj->as<NativeObject>().shrinkElements(cx, initlen);
|
||||
return DenseElementResult::Success;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
GetBoxedOrUnboxedCapacity(JSObject* obj)
|
||||
{
|
||||
return obj->as<NativeObject>().getDenseCapacity();
|
||||
}
|
||||
|
||||
static inline Value
|
||||
GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
|
||||
{
|
||||
return obj->as<NativeObject>().getDenseElement(index);
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value)
|
||||
{
|
||||
obj->as<NativeObject>().setDenseElement(index, value);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
|
||||
{
|
||||
obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline DenseElementResult
|
||||
EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count)
|
||||
{
|
||||
if (!obj->as<ArrayObject>().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<NativeObject>().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<NativeObject>().getDenseInitializedLength() == dstStart);
|
||||
MOZ_ASSERT(src->as<NativeObject>().getDenseInitializedLength() >= srcStart + length);
|
||||
MOZ_ASSERT(dst->as<NativeObject>().getDenseCapacity() >= dstStart + length);
|
||||
|
||||
SetBoxedOrUnboxedInitializedLength(cx, dst, dstStart + length);
|
||||
dst->as<NativeObject>().setDenseInitializedLength(dstStart + length);
|
||||
|
||||
const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
|
||||
dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
|
||||
|
|
@ -383,7 +263,7 @@ template <typename F>
|
|||
DenseElementResult
|
||||
CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
|
||||
{
|
||||
if (!HasAnyBoxedOrUnboxedDenseElements(obj))
|
||||
if (!obj->isNative())
|
||||
return DenseElementResult::Incomplete;
|
||||
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
|
||||
}
|
||||
|
|
@ -393,7 +273,7 @@ template <typename F>
|
|||
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()<JSVAL_TYPE_MAGIC, JSVAL_TYPE_MAGIC>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue