summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2019-06-19 10:56:35 +0000
committerGitHub <noreply@github.com>2019-06-19 10:56:35 +0000
commite52407c8792eb068f1947796ad90ef0f7572de8a (patch)
tree202c502b7e964384fb7f0639b756353374b0c045 /js
parent5f99aa28d4818bb53c71b8d300e5c98229fb1544 (diff)
parent3d0318edf174406865bafb7d54e594aa4681e61d (diff)
downloadaura-central-e52407c8792eb068f1947796ad90ef0f7572de8a.tar.gz
Merge pull request %1137 from MoonchildProductions/remove-unboxed-checked
Remove unboxed (checked branch)
Diffstat (limited to 'js')
-rw-r--r--js/src/builtin/ModuleObject.cpp2
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp13
-rw-r--r--js/src/frontend/BytecodeEmitter.h2
-rw-r--r--js/src/gc/Marking.cpp2
-rw-r--r--js/src/jit/AliasAnalysisShared.cpp4
-rw-r--r--js/src/jit/BaselineCacheIR.cpp16
-rw-r--r--js/src/jit/BaselineCompiler.cpp12
-rw-r--r--js/src/jit/BaselineCompiler.h1
-rw-r--r--js/src/jit/BaselineIC.cpp213
-rw-r--r--js/src/jit/BaselineIC.h68
-rw-r--r--js/src/jit/BaselineInspector.cpp2
-rw-r--r--js/src/jit/BaselineInspector.h2
-rw-r--r--js/src/jit/CacheIR.cpp9
-rw-r--r--js/src/jit/CacheIR.h5
-rw-r--r--js/src/jit/CodeGenerator.cpp381
-rw-r--r--js/src/jit/CodeGenerator.h4
-rw-r--r--js/src/jit/IonBuilder.cpp201
-rw-r--r--js/src/jit/IonBuilder.h12
-rw-r--r--js/src/jit/IonCaches.cpp135
-rw-r--r--js/src/jit/Lowering.cpp46
-rw-r--r--js/src/jit/Lowering.h4
-rw-r--r--js/src/jit/MCallOptimize.cpp83
-rw-r--r--js/src/jit/MIR.cpp45
-rw-r--r--js/src/jit/MIR.h192
-rw-r--r--js/src/jit/MOpcodes.h4
-rw-r--r--js/src/jit/MacroAssembler.cpp35
-rw-r--r--js/src/jit/MacroAssembler.h5
-rw-r--r--js/src/jit/Recover.cpp2
-rw-r--r--js/src/jit/ScalarReplacement.cpp5
-rw-r--r--js/src/jit/SharedIC.cpp9
-rw-r--r--js/src/jit/VMFunctions.cpp27
-rw-r--r--js/src/jit/VMFunctions.h6
-rw-r--r--js/src/jit/shared/LIR-shared.h90
-rw-r--r--js/src/jit/shared/LOpcodes-shared.h4
-rw-r--r--js/src/jsapi.h8
-rw-r--r--js/src/jsarray.cpp523
-rw-r--r--js/src/jsarray.h41
-rw-r--r--js/src/jsfriendapi.cpp2
-rw-r--r--js/src/jsobj.cpp47
-rw-r--r--js/src/jsobjinlines.h2
-rw-r--r--js/src/jsstr.cpp6
-rw-r--r--js/src/jsstr.h2
-rw-r--r--js/src/shell/js.cpp4
-rw-r--r--js/src/vm/Interpreter-inl.h2
-rw-r--r--js/src/vm/Interpreter.cpp16
-rw-r--r--js/src/vm/JSONParser.cpp4
-rw-r--r--js/src/vm/NativeObject-inl.h32
-rw-r--r--js/src/vm/NativeObject.h15
-rw-r--r--js/src/vm/ObjectGroup.cpp103
-rw-r--r--js/src/vm/ObjectGroup.h10
-rw-r--r--js/src/vm/Opcodes.h12
-rw-r--r--js/src/vm/ReceiverGuard.cpp8
-rw-r--r--js/src/vm/Stack.cpp2
-rw-r--r--js/src/vm/Stack.h2
-rw-r--r--js/src/vm/TypeInference.cpp6
-rw-r--r--js/src/vm/TypeInference.h4
-rw-r--r--js/src/vm/UnboxedObject-inl.h663
-rw-r--r--js/src/vm/UnboxedObject.cpp826
-rw-r--r--js/src/vm/UnboxedObject.h207
59 files changed, 633 insertions, 3555 deletions
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 710c7a76c..c6bd2d300 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -947,7 +947,7 @@ ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValu
ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
{
MOZ_ASSERT(!self->namespace_());
- MOZ_ASSERT(exports->is<ArrayObject>() || exports->is<UnboxedArrayObject>());
+ MOZ_ASSERT(exports->is<ArrayObject>());
RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
if (!ns)
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index c524184d6..7f9fa8a5d 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6281,8 +6281,8 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje
}
MOZ_ASSERT(idx == count);
- JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
- newKind, arrayKind);
+ ArrayObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
+ newKind, arrayKind);
if (!obj)
return false;
@@ -9192,7 +9192,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
return false;
}
- if (!emitArray(args, argc, JSOP_SPREADCALLARRAY))
+ if (!emitArray(args, argc))
return false;
if (optCodeEmitted) {
@@ -9683,11 +9683,11 @@ BytecodeEmitter::emitArrayLiteral(ParseNode* pn)
}
}
- return emitArray(pn->pn_head, pn->pn_count, JSOP_NEWARRAY);
+ return emitArray(pn->pn_head, pn->pn_count);
}
bool
-BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
+BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count)
{
/*
@@ -9698,7 +9698,6 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
* to avoid dup'ing and popping the array as each element is added, as
* JSOP_SETELEM/JSOP_SETPROP would do.
*/
- MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
uint32_t nspread = 0;
for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
@@ -9719,7 +9718,7 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
// For arrays with spread, this is a very pessimistic allocation, the
// minimum possible final size.
- if (!emitUint32Operand(op, count - nspread)) // ARRAY
+ if (!emitUint32Operand(JSOP_NEWARRAY, count - nspread)) // ARRAY
return false;
ParseNode* pn2 = pn;
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index 814fa11d4..29050c846 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -521,7 +521,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitAtomOp(ParseNode* pn, JSOp op);
MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
- MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
+ MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count);
MOZ_MUST_USE bool emitArrayComp(ParseNode* pn);
MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index 47d2314c1..da3ef7d0d 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2504,8 +2504,6 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<TypedArrayObject>()) {
tenuredSize += TypedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
- } else if (src->is<UnboxedArrayObject>()) {
- tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
} else if (src->is<ArgumentsObject>()) {
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<ProxyObject>()) {
diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp
index 3b83df74e..0f0d4a66a 100644
--- a/js/src/jit/AliasAnalysisShared.cpp
+++ b/js/src/jit/AliasAnalysisShared.cpp
@@ -93,10 +93,6 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_Elements:
case MDefinition::Op_MaybeCopyElementsForWrite:
case MDefinition::Op_MaybeToDoubleElement:
- case MDefinition::Op_UnboxedArrayLength:
- case MDefinition::Op_UnboxedArrayInitializedLength:
- case MDefinition::Op_IncrementUnboxedArrayInitializedLength:
- case MDefinition::Op_SetUnboxedArrayInitializedLength:
case MDefinition::Op_TypedArrayLength:
case MDefinition::Op_SetTypedObjectOffset:
case MDefinition::Op_SetDisjointTypedElements:
diff --git a/js/src/jit/BaselineCacheIR.cpp b/js/src/jit/BaselineCacheIR.cpp
index bf96932d1..7fb586811 100644
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -787,9 +787,6 @@ BaselineCacheIRCompiler::emitGuardClass()
case GuardClassKind::Array:
clasp = &ArrayObject::class_;
break;
- case GuardClassKind::UnboxedArray:
- clasp = &UnboxedArrayObject::class_;
- break;
case GuardClassKind::MappedArguments:
clasp = &MappedArgumentsObject::class_;
break;
@@ -1004,19 +1001,6 @@ BaselineCacheIRCompiler::emitLoadInt32ArrayLengthResult()
}
bool
-BaselineCacheIRCompiler::emitLoadUnboxedArrayLengthResult()
-{
- Register obj = allocator.useRegister(masm, reader.objOperandId());
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), R0.scratchReg());
- masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0);
-
- // The int32 type was monitored when attaching the stub, so we can
- // just return.
- emitReturnFromIC();
- return true;
-}
-
-bool
BaselineCacheIRCompiler::emitLoadArgumentsObjectLengthResult()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 3fa5a80ed..6b64bfb44 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2049,13 +2049,7 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
return true;
}
-bool
-BaselineCompiler::emit_JSOP_SPREADCALLARRAY()
-{
- return emit_JSOP_NEWARRAY();
-}
-
-typedef JSObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
+typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
const VMFunction jit::NewArrayCopyOnWriteInfo =
FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
@@ -4136,14 +4130,14 @@ BaselineCompiler::emit_JSOP_REST()
{
frame.syncStack(0);
- JSObject* templateObject =
+ ArrayObject* templateObject =
ObjectGroup::newArrayObject(cx, nullptr, 0, TenuredObject,
ObjectGroup::NewArrayKind::UnknownIndex);
if (!templateObject)
return false;
// Call IC.
- ICRest_Fallback::Compiler compiler(cx, &templateObject->as<ArrayObject>());
+ ICRest_Fallback::Compiler compiler(cx, templateObject);
if (!emitOpIC(compiler.getStub(&stubSpace_)))
return false;
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 6b5bf009e..910a52980 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -100,7 +100,6 @@ namespace jit {
_(JSOP_BITNOT) \
_(JSOP_NEG) \
_(JSOP_NEWARRAY) \
- _(JSOP_SPREADCALLARRAY) \
_(JSOP_NEWARRAY_COPYONWRITE) \
_(JSOP_INITELEM_ARRAY) \
_(JSOP_NEWOBJECT) \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 863c61161..64cdf01a6 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1366,7 +1366,7 @@ IsNativeDenseElementAccess(HandleObject obj, HandleValue key)
static bool
IsNativeOrUnboxedDenseElementAccess(HandleObject obj, HandleValue key)
{
- if (!obj->isNative() && !obj->is<UnboxedArrayObject>())
+ if (!obj->isNative())
return false;
if (key.isInt32() && key.toInt32() >= 0 && !obj->is<TypedArrayObject>())
return true;
@@ -1470,20 +1470,6 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
script = rootedScript;
}
- // Check for UnboxedArray[int] accesses.
- if (obj->is<UnboxedArrayObject>() && rhs.isInt32() && rhs.toInt32() >= 0) {
- JitSpew(JitSpew_BaselineIC, " Generating GetElem(UnboxedArray[Int32]) stub");
- ICGetElem_UnboxedArray::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
- obj->group());
- ICStub* unboxedStub = compiler.getStub(compiler.getStubSpace(script));
- if (!unboxedStub)
- return false;
-
- stub->addNewStub(unboxedStub);
- *attached = true;
- return true;
- }
-
// Check for TypedArray[int] => Number and TypedObject[int] => Number accesses.
if ((obj->is<TypedArrayObject>() || IsPrimitiveArrayTypedObject(obj)) &&
rhs.isNumber() &&
@@ -2090,56 +2076,6 @@ ICGetElem_Dense::Compiler::generateStubCode(MacroAssembler& masm)
}
//
-// GetElem_UnboxedArray
-//
-
-bool
-ICGetElem_UnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
-{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
- Label failure;
- masm.branchTestObject(Assembler::NotEqual, R0, &failure);
- masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
- AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
- Register scratchReg = regs.takeAny();
-
- // Unbox R0 and group guard.
- Register obj = masm.extractObject(R0, ExtractTemp0);
- masm.loadPtr(Address(ICStubReg, ICGetElem_UnboxedArray::offsetOfGroup()), scratchReg);
- masm.branchTestObjGroup(Assembler::NotEqual, obj, scratchReg, &failure);
-
- // Unbox key.
- Register key = masm.extractInt32(R1, ExtractTemp1);
-
- // Bounds check.
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()),
- scratchReg);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
- masm.branch32(Assembler::BelowOrEqual, scratchReg, key, &failure);
-
- // Load obj->elements.
- masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
- // Load value.
- size_t width = UnboxedTypeSize(elementType_);
- BaseIndex addr(scratchReg, key, ScaleFromElemWidth(width));
- masm.loadUnboxedProperty(addr, elementType_, R0);
-
- // Only monitor the result if its type might change.
- if (elementType_ == JSVAL_TYPE_OBJECT)
- EmitEnterTypeMonitorIC(masm);
- else
- EmitReturnFromIC(masm);
-
- // Failure case - jump to next stub
- masm.bind(&failure);
- EmitStubGuardFailure(masm);
- return true;
-}
-
-//
// GetElem_TypedArray
//
@@ -2437,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;
@@ -2447,10 +2383,6 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index,
if (initLength < oldInitLength || capacity < oldCapacity)
return false;
- // Unboxed arrays need to be able to emit floating point code.
- if (obj->is<UnboxedArrayObject>() && !obj->runtimeFromMainThread()->jitSupportsFloatingPoint)
- return false;
-
Shape* shape = obj->maybeShape();
// Cannot optimize if the shape changed.
@@ -2532,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) {
@@ -2871,29 +2803,6 @@ ICSetElem_DenseOrUnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
masm.loadValue(valueAddr, tmpVal);
EmitPreBarrier(masm, element, MIRType::Value);
masm.storeValue(tmpVal, element);
- } else {
- // Set element on an unboxed array.
-
- // Bounds check.
- Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLength, scratchReg);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
- masm.branch32(Assembler::BelowOrEqual, scratchReg, key, &failure);
-
- // Load obj->elements.
- masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
- // Compute the address being written to.
- BaseIndex address(scratchReg, key, ScaleFromElemWidth(UnboxedTypeSize(unboxedType_)));
-
- EmitUnboxedPreBarrierForBaseline(masm, address, unboxedType_);
-
- Address valueAddr(masm.getStackPointer(), ICStackValueOffset + sizeof(Value));
- masm.Push(R0);
- masm.loadValue(valueAddr, R0);
- masm.storeUnboxedProperty(address, unboxedType_,
- ConstantOrRegister(TypedOrValueRegister(R0)), &failurePopR0);
- masm.Pop(R0);
}
EmitReturnFromIC(masm);
@@ -3087,40 +2996,6 @@ ICSetElemDenseOrUnboxedArrayAddCompiler::generateStubCode(MacroAssembler& masm)
BaseIndex element(scratchReg, key, TimesEight);
masm.loadValue(valueAddr, tmpVal);
masm.storeValue(tmpVal, element);
- } else {
- // Adding element to an unboxed array.
-
- // Bounds check (key == initLength)
- Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLengthAddr, scratchReg);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
- masm.branch32(Assembler::NotEqual, scratchReg, key, &failure);
-
- // Capacity check.
- masm.checkUnboxedArrayCapacity(obj, RegisterOrInt32Constant(key), scratchReg, &failure);
-
- // Load obj->elements.
- masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
- // Write the value first, since this can fail. No need for pre-barrier
- // since we're not overwriting an old value.
- masm.Push(R0);
- Address valueAddr(masm.getStackPointer(), ICStackValueOffset + sizeof(Value));
- masm.loadValue(valueAddr, R0);
- BaseIndex address(scratchReg, key, ScaleFromElemWidth(UnboxedTypeSize(unboxedType_)));
- masm.storeUnboxedProperty(address, unboxedType_,
- ConstantOrRegister(TypedOrValueRegister(R0)), &failurePopR0);
- masm.Pop(R0);
-
- // Increment initialized length.
- masm.add32(Imm32(1), initLengthAddr);
-
- // If length is now <= key, increment length.
- Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
- Label skipIncrementLength;
- masm.branch32(Assembler::Above, lengthAddr, key, &skipIncrementLength);
- masm.add32(Imm32(1), lengthAddr);
- masm.bind(&skipIncrementLength);
}
EmitReturnFromIC(masm);
@@ -5490,13 +5365,6 @@ GetTemplateObjectForSimd(JSContext* cx, JSFunction* target, MutableHandleObject
return true;
}
-static void
-EnsureArrayGroupAnalyzed(JSContext* cx, JSObject* obj)
-{
- if (PreliminaryObjectArrayWithTemplate* objects = obj->group()->maybePreliminaryObjects())
- objects->maybeAnalyze(cx, obj->group(), /* forceAnalyze = */ true);
-}
-
static bool
GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs& args,
MutableHandleObject res, bool* skipAttach)
@@ -5528,10 +5396,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
// With this and other array templates, analyze the group so that
// we don't end up with a template whose structure might change later.
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count, TenuredObject));
- if (!res)
- return false;
- EnsureArrayGroupAnalyzed(cx, res);
- return true;
+ return !!res;
}
}
@@ -5557,10 +5422,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
}
res.set(NewFullyAllocatedArrayTryReuseGroup(cx, &args.thisv().toObject(), 0,
TenuredObject));
- if (!res)
- return false;
- EnsureArrayGroupAnalyzed(cx, res);
- return true;
+ return !!res;
}
}
}
@@ -5577,10 +5439,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
}
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, 0, TenuredObject));
- if (!res)
- return false;
- EnsureArrayGroupAnalyzed(cx, res);
- return true;
+ return !!res;
}
if (native == StringConstructor) {
@@ -5887,15 +5746,24 @@ 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();
+ ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
if (!nobj)
return false;
- EnsureArrayGroupAnalyzed(cx, nobj);
- CopyAnyBoxedOrUnboxedDenseElements(cx, nobj, obj, 0, 0, length);
-
+
+ MOZ_ASSERT(arr->isNative());
+ MOZ_ASSERT(nobj->isNative());
+ MOZ_ASSERT(nobj->as<NativeObject>().getDenseInitializedLength() == 0);
+ MOZ_ASSERT(arr->as<NativeObject>().getDenseInitializedLength() >= length);
+ MOZ_ASSERT(nobj->as<NativeObject>().getDenseCapacity() >= length);
+
+ nobj->as<NativeObject>().setDenseInitializedLength(length);
+
+ const Value* vp = arr->as<NativeObject>().getDenseElements();
+ nobj->as<NativeObject>().initDenseElements(0, vp, length);
+
result.setObject(*nobj);
return true;
}
@@ -5926,26 +5794,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;
@@ -6830,7 +6694,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
@@ -8301,19 +8165,6 @@ ICGetElem_Dense::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorSt
return New<ICGetElem_Dense>(cx, space, other.jitCode(), firstMonitorStub, other.shape_);
}
-ICGetElem_UnboxedArray::ICGetElem_UnboxedArray(JitCode* stubCode, ICStub* firstMonitorStub,
- ObjectGroup *group)
- : ICMonitoredStub(GetElem_UnboxedArray, stubCode, firstMonitorStub),
- group_(group)
-{ }
-
-/* static */ ICGetElem_UnboxedArray*
-ICGetElem_UnboxedArray::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
- ICGetElem_UnboxedArray& other)
-{
- return New<ICGetElem_UnboxedArray>(cx, space, other.jitCode(), firstMonitorStub, other.group_);
-}
-
ICGetElem_TypedArray::ICGetElem_TypedArray(JitCode* stubCode, Shape* shape, Scalar::Type type)
: ICStub(GetElem_TypedArray, stubCode),
shape_(shape)
@@ -8689,8 +8540,8 @@ static bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback*
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
Value* rest = frame->argv() + numFormals;
- JSObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
- ObjectGroup::NewArrayKind::UnknownIndex);
+ ArrayObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
+ ObjectGroup::NewArrayKind::UnknownIndex);
if (!obj)
return false;
res.setObject(*obj);
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index a57556d99..901fca9cc 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -892,54 +892,6 @@ class ICGetElem_Dense : public ICMonitoredStub
};
};
-class ICGetElem_UnboxedArray : public ICMonitoredStub
-{
- friend class ICStubSpace;
-
- GCPtrObjectGroup group_;
-
- ICGetElem_UnboxedArray(JitCode* stubCode, ICStub* firstMonitorStub, ObjectGroup* group);
-
- public:
- static ICGetElem_UnboxedArray* Clone(JSContext* cx, ICStubSpace* space,
- ICStub* firstMonitorStub, ICGetElem_UnboxedArray& other);
-
- static size_t offsetOfGroup() {
- return offsetof(ICGetElem_UnboxedArray, group_);
- }
-
- GCPtrObjectGroup& group() {
- return group_;
- }
-
- class Compiler : public ICStubCompiler {
- ICStub* firstMonitorStub_;
- RootedObjectGroup group_;
- JSValueType elementType_;
-
- protected:
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
- virtual int32_t getKey() const {
- return static_cast<int32_t>(engine_) |
- (static_cast<int32_t>(kind) << 1) |
- (static_cast<int32_t>(elementType_) << 17);
- }
-
- public:
- Compiler(JSContext* cx, ICStub* firstMonitorStub, ObjectGroup* group)
- : ICStubCompiler(cx, ICStub::GetElem_UnboxedArray, Engine::Baseline),
- firstMonitorStub_(firstMonitorStub),
- group_(cx, group),
- elementType_(group->unboxedLayoutDontCheckGeneration().elementType())
- {}
-
- ICStub* getStub(ICStubSpace* space) {
- return newStub<ICGetElem_UnboxedArray>(space, getStubCode(), firstMonitorStub_, group_);
- }
- };
-};
-
// Accesses scalar elements of a typed array or typed object.
class ICGetElem_TypedArray : public ICStub
{
@@ -1115,9 +1067,7 @@ class ICSetElem_DenseOrUnboxedArray : public ICUpdatedStub
: ICStubCompiler(cx, ICStub::SetElem_DenseOrUnboxedArray, Engine::Baseline),
shape_(cx, shape),
group_(cx, group),
- unboxedType_(shape
- ? JSVAL_TYPE_MAGIC
- : group->unboxedLayoutDontCheckGeneration().elementType())
+ unboxedType_(JSVAL_TYPE_MAGIC)
{}
ICUpdatedStub* getStub(ICStubSpace* space) {
@@ -1225,9 +1175,7 @@ class ICSetElemDenseOrUnboxedArrayAddCompiler : public ICStubCompiler {
: ICStubCompiler(cx, ICStub::SetElem_DenseOrUnboxedArrayAdd, Engine::Baseline),
obj_(cx, obj),
protoChainDepth_(protoChainDepth),
- unboxedType_(obj->is<UnboxedArrayObject>()
- ? obj->as<UnboxedArrayObject>().elementType()
- : JSVAL_TYPE_MAGIC)
+ unboxedType_(JSVAL_TYPE_MAGIC)
{}
template <size_t ProtoChainDepth>
@@ -2870,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)
@@ -2900,7 +2848,7 @@ class ICCall_StringSplit : public ICMonitoredStub
return expectedSep_;
}
- GCPtrObject& templateObject() {
+ GCPtrArrayObject& templateObject() {
return templateObject_;
}
@@ -2910,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);
@@ -2921,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/CacheIR.cpp b/js/src/jit/CacheIR.cpp
index f1061af70..6822a70af 100644
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -175,7 +175,7 @@ TestMatchingReceiver(CacheIRWriter& writer, JSObject* obj, Shape* shape, ObjOper
} else {
writer.guardNoUnboxedExpando(objId);
}
- } else if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
+ } else if (obj->is<TypedObject>()) {
writer.guardGroup(objId, obj->group());
} else {
Shape* shape = obj->maybeShape();
@@ -368,13 +368,6 @@ GetPropIRGenerator::tryAttachObjectLength(CacheIRWriter& writer, HandleObject ob
return true;
}
- if (obj->is<UnboxedArrayObject>()) {
- writer.guardClass(objId, GuardClassKind::UnboxedArray);
- writer.loadUnboxedArrayLengthResult(objId);
- emitted_ = true;
- return true;
- }
-
if (obj->is<ArgumentsObject>() && !obj->as<ArgumentsObject>().hasOverriddenLength()) {
if (obj->is<MappedArgumentsObject>()) {
writer.guardClass(objId, GuardClassKind::MappedArguments);
diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h
index 51e55f48b..4fd8575f0 100644
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -96,7 +96,6 @@ class ObjOperandId : public OperandId
_(LoadUnboxedPropertyResult) \
_(LoadTypedObjectResult) \
_(LoadInt32ArrayLengthResult) \
- _(LoadUnboxedArrayLengthResult) \
_(LoadArgumentsObjectLengthResult) \
_(LoadUndefinedResult)
@@ -128,7 +127,6 @@ struct StubField {
enum class GuardClassKind
{
Array,
- UnboxedArray,
MappedArguments,
UnmappedArguments,
};
@@ -327,9 +325,6 @@ class MOZ_RAII CacheIRWriter
void loadInt32ArrayLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj);
}
- void loadUnboxedArrayLengthResult(ObjOperandId obj) {
- writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
- }
void loadArgumentsObjectLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
}
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 6d1fb6b9b..e0b8a7f28 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3183,9 +3183,7 @@ CodeGenerator::visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins)
void
CodeGenerator::visitElements(LElements* lir)
{
- Address elements(ToRegister(lir->object()),
- lir->mir()->unboxed() ? UnboxedArrayObject::offsetOfElements()
- : NativeObject::offsetOfElements());
+ Address elements(ToRegister(lir->object()), NativeObject::offsetOfElements());
masm.loadPtr(elements, ToRegister(lir->output()));
}
@@ -5171,11 +5169,11 @@ static JSObject*
NewArrayWithGroup(JSContext* cx, uint32_t length, HandleObjectGroup group,
bool convertDoubleElements)
{
- JSObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
+ ArrayObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
if (!res)
return nullptr;
if (convertDoubleElements)
- res->as<ArrayObject>().setShouldConvertDoubleElements();
+ res->setShouldConvertDoubleElements();
return res;
}
@@ -5321,7 +5319,7 @@ CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir)
masm.bind(ool->rejoin());
}
-typedef JSObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
+typedef ArrayObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
static const VMFunction ArrayConstructorOneArgInfo =
FunctionInfo<ArrayConstructorOneArgFn>(ArrayConstructorOneArg, "ArrayConstructorOneArg");
@@ -5341,21 +5339,11 @@ CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength* lir)
bool canInline = true;
size_t inlineLength = 0;
- if (templateObject->is<ArrayObject>()) {
- if (templateObject->as<ArrayObject>().hasFixedElements()) {
- size_t numSlots = gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
- inlineLength = numSlots - ObjectElements::VALUES_PER_HEADER;
- } else {
- canInline = false;
- }
+ if (templateObject->as<ArrayObject>().hasFixedElements()) {
+ size_t numSlots = gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
+ inlineLength = numSlots - ObjectElements::VALUES_PER_HEADER;
} else {
- if (templateObject->as<UnboxedArrayObject>().hasInlineElements()) {
- size_t nbytes =
- templateObject->tenuredSizeOfThis() - UnboxedArrayObject::offsetOfInlineElements();
- inlineLength = nbytes / templateObject->as<UnboxedArrayObject>().elementSize();
- } else {
- canInline = false;
- }
+ canInline = false;
}
if (canInline) {
@@ -7777,7 +7765,7 @@ CodeGenerator::visitSinCos(LSinCos *lir)
masm.freeStack(sizeof(double) * 2);
}
-typedef JSObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
+typedef ArrayObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
static const VMFunction StringSplitInfo =
FunctionInfo<StringSplitFn>(js::str_split_string, "str_split_string");
@@ -7812,49 +7800,6 @@ CodeGenerator::visitSetInitializedLength(LSetInitializedLength* lir)
}
void
-CodeGenerator::visitUnboxedArrayLength(LUnboxedArrayLength* lir)
-{
- Register obj = ToRegister(lir->object());
- Register result = ToRegister(lir->output());
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), result);
-}
-
-void
-CodeGenerator::visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir)
-{
- Register obj = ToRegister(lir->object());
- Register result = ToRegister(lir->output());
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), result);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), result);
-}
-
-void
-CodeGenerator::visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir)
-{
- Register obj = ToRegister(lir->object());
- masm.add32(Imm32(1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
-}
-
-void
-CodeGenerator::visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir)
-{
- Register obj = ToRegister(lir->object());
- RegisterOrInt32Constant key = ToRegisterOrInt32Constant(lir->length());
- Register temp = ToRegister(lir->temp());
-
- Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLengthAddr, temp);
- masm.and32(Imm32(UnboxedArrayObject::CapacityMask), temp);
-
- if (key.isRegister())
- masm.or32(key.reg(), temp);
- else
- masm.or32(Imm32(key.constant()), temp);
-
- masm.store32(temp, initLengthAddr);
-}
-
-void
CodeGenerator::visitNotO(LNotO* lir)
{
MOZ_ASSERT(lir->mir()->operandMightEmulateUndefined(),
@@ -8150,46 +8095,19 @@ CodeGenerator::emitStoreElementHoleT(T* lir)
OutOfLineStoreElementHole* ool = new(alloc()) OutOfLineStoreElementHole(lir);
addOutOfLineCode(ool, lir->mir());
- Register obj = ToRegister(lir->object());
Register elements = ToRegister(lir->elements());
const LAllocation* index = lir->index();
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
- JSValueType unboxedType = lir->mir()->unboxedType();
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- Address initLength(elements, ObjectElements::offsetOfInitializedLength());
- masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
-
- if (lir->mir()->needsBarrier())
- emitPreBarrier(elements, index, 0);
-
- masm.bind(ool->rejoinStore());
- emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
- elements, index, 0);
- } else {
- Register temp = ToRegister(lir->getTemp(0));
- Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLength, temp);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp);
- masm.branch32(Assembler::BelowOrEqual, temp, key, ool->entry());
-
- ConstantOrRegister v = ToConstantOrRegister(lir->value(), lir->mir()->value()->type());
-
- if (index->isConstant()) {
- Address address(elements, ToInt32(index) * UnboxedTypeSize(unboxedType));
- EmitUnboxedPreBarrier(masm, address, unboxedType);
+ Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
- masm.bind(ool->rejoinStore());
- masm.storeUnboxedProperty(address, unboxedType, v, nullptr);
- } else {
- BaseIndex address(elements, ToRegister(index),
- ScaleFromElemWidth(UnboxedTypeSize(unboxedType)));
- EmitUnboxedPreBarrier(masm, address, unboxedType);
+ if (lir->mir()->needsBarrier())
+ emitPreBarrier(elements, index, 0);
- masm.bind(ool->rejoinStore());
- masm.storeUnboxedProperty(address, unboxedType, v, nullptr);
- }
- }
+ masm.bind(ool->rejoinStore());
+ emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
+ elements, index, 0);
masm.bind(ool->rejoin());
}
@@ -8209,47 +8127,22 @@ CodeGenerator::emitStoreElementHoleV(T* lir)
OutOfLineStoreElementHole* ool = new(alloc()) OutOfLineStoreElementHole(lir);
addOutOfLineCode(ool, lir->mir());
- Register obj = ToRegister(lir->object());
Register elements = ToRegister(lir->elements());
const LAllocation* index = lir->index();
const ValueOperand value = ToValue(lir, T::Value);
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
- JSValueType unboxedType = lir->mir()->unboxedType();
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- Address initLength(elements, ObjectElements::offsetOfInitializedLength());
- masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
-
- if (lir->mir()->needsBarrier())
- emitPreBarrier(elements, index, 0);
+ Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
- masm.bind(ool->rejoinStore());
- if (index->isConstant())
- masm.storeValue(value, Address(elements, ToInt32(index) * sizeof(js::Value)));
- else
- masm.storeValue(value, BaseIndex(elements, ToRegister(index), TimesEight));
- } else {
- Register temp = ToRegister(lir->getTemp(0));
- Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLength, temp);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp);
- masm.branch32(Assembler::BelowOrEqual, temp, key, ool->entry());
-
- if (index->isConstant()) {
- Address address(elements, ToInt32(index) * UnboxedTypeSize(unboxedType));
- EmitUnboxedPreBarrier(masm, address, unboxedType);
-
- masm.bind(ool->rejoinStore());
- masm.storeUnboxedProperty(address, unboxedType, ConstantOrRegister(value), nullptr);
- } else {
- BaseIndex address(elements, ToRegister(index),
- ScaleFromElemWidth(UnboxedTypeSize(unboxedType)));
- EmitUnboxedPreBarrier(masm, address, unboxedType);
+ if (lir->mir()->needsBarrier())
+ emitPreBarrier(elements, index, 0);
- masm.bind(ool->rejoinStore());
- masm.storeUnboxedProperty(address, unboxedType, ConstantOrRegister(value), nullptr);
- }
- }
+ masm.bind(ool->rejoinStore());
+ if (index->isConstant())
+ masm.storeValue(value, Address(elements, ToInt32(index) * sizeof(js::Value)));
+ else
+ masm.storeValue(value, BaseIndex(elements, ToRegister(index), TimesEight));
masm.bind(ool->rejoin());
}
@@ -8320,11 +8213,10 @@ CodeGenerator::visitFallibleStoreElementV(LFallibleStoreElementV* lir)
masm.bind(&isFrozen);
}
-typedef bool (*SetDenseOrUnboxedArrayElementFn)(JSContext*, HandleObject, int32_t,
- HandleValue, bool strict);
-static const VMFunction SetDenseOrUnboxedArrayElementInfo =
- FunctionInfo<SetDenseOrUnboxedArrayElementFn>(SetDenseOrUnboxedArrayElement,
- "SetDenseOrUnboxedArrayElement");
+typedef bool (*SetDenseElementFn)(JSContext*, HandleNativeObject, int32_t, HandleValue,
+ bool strict);
+static const VMFunction SetDenseElementInfo =
+ FunctionInfo<SetDenseElementFn>(jit::SetDenseElement, "SetDenseElement");
void
CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
@@ -8334,8 +8226,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
const LAllocation* index;
MIRType valueType;
ConstantOrRegister value;
- JSValueType unboxedType;
- LDefinition *temp = nullptr;
if (ins->isStoreElementHoleV()) {
LStoreElementHoleV* store = ins->toStoreElementHoleV();
@@ -8344,8 +8234,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
- unboxedType = store->mir()->unboxedType();
- temp = store->getTemp(0);
} else if (ins->isFallibleStoreElementV()) {
LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
object = ToRegister(store->object());
@@ -8353,8 +8241,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
- unboxedType = store->mir()->unboxedType();
- temp = store->getTemp(0);
} else if (ins->isStoreElementHoleT()) {
LStoreElementHoleT* store = ins->toStoreElementHoleT();
object = ToRegister(store->object());
@@ -8365,8 +8251,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
- unboxedType = store->mir()->unboxedType();
- temp = store->getTemp(0);
} else { // ins->isFallibleStoreElementT()
LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
object = ToRegister(store->object());
@@ -8377,8 +8261,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
- unboxedType = store->mir()->unboxedType();
- temp = store->getTemp(0);
}
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
@@ -8389,54 +8271,32 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
Label callStub;
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
// Had to reimplement for MIPS because there are no flags.
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- Address initLength(elements, ObjectElements::offsetOfInitializedLength());
- masm.branch32(Assembler::NotEqual, initLength, key, &callStub);
- } else {
- Address initLength(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- masm.load32(initLength, ToRegister(temp));
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), ToRegister(temp));
- masm.branch32(Assembler::NotEqual, ToRegister(temp), key, &callStub);
- }
+ Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::NotEqual, initLength, key, &callStub);
#else
masm.j(Assembler::NotEqual, &callStub);
#endif
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- // Check array capacity.
- masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
- key, &callStub);
-
- // Update initialized length. The capacity guard above ensures this won't overflow,
- // due to MAX_DENSE_ELEMENTS_COUNT.
- masm.inc32(&key);
- masm.store32(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
+ // Check array capacity.
+ masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
+ key, &callStub);
- // Update length if length < initializedLength.
- Label dontUpdate;
- masm.branch32(Assembler::AboveOrEqual, Address(elements, ObjectElements::offsetOfLength()),
- key, &dontUpdate);
- masm.store32(key, Address(elements, ObjectElements::offsetOfLength()));
- masm.bind(&dontUpdate);
-
- masm.dec32(&key);
- } else {
- // Check array capacity.
- masm.checkUnboxedArrayCapacity(object, key, ToRegister(temp), &callStub);
+ // Update initialized length. The capacity guard above ensures this won't overflow,
+ // due to MAX_DENSE_ELEMENTS_COUNT.
+ masm.inc32(&key);
+ masm.store32(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
- // Update initialized length.
- masm.add32(Imm32(1), Address(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
+ // Update length if length < initializedLength.
+ Label dontUpdate;
+ masm.branch32(Assembler::AboveOrEqual, Address(elements, ObjectElements::offsetOfLength()),
+ key, &dontUpdate);
+ masm.store32(key, Address(elements, ObjectElements::offsetOfLength()));
+ masm.bind(&dontUpdate);
- // Update length if length < initializedLength.
- Address lengthAddr(object, UnboxedArrayObject::offsetOfLength());
- Label dontUpdate;
- masm.branch32(Assembler::Above, lengthAddr, key, &dontUpdate);
- masm.add32(Imm32(1), lengthAddr);
- masm.bind(&dontUpdate);
- }
+ masm.dec32(&key);
if ((ins->isStoreElementHoleT() || ins->isFallibleStoreElementT()) &&
- unboxedType == JSVAL_TYPE_MAGIC && valueType != MIRType::Double)
+ valueType != MIRType::Double)
{
// The inline path for StoreElementHoleT and FallibleStoreElementT does not always store
// the type tag, so we do the store on the OOL path. We use MIRType::None for the element
@@ -8465,7 +8325,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
else
pushArg(ToRegister(index));
pushArg(object);
- callVM(SetDenseOrUnboxedArrayElementInfo, ins);
+ callVM(SetDenseElementInfo, ins);
restoreLive(ins);
masm.jump(ool->rejoin());
@@ -8526,9 +8386,6 @@ typedef bool (*ConvertUnboxedObjectToNativeFn)(JSContext*, JSObject*);
static const VMFunction ConvertUnboxedPlainObjectToNativeInfo =
FunctionInfo<ConvertUnboxedObjectToNativeFn>(UnboxedPlainObject::convertToNative,
"UnboxedPlainObject::convertToNative");
-static const VMFunction ConvertUnboxedArrayObjectToNativeInfo =
- FunctionInfo<ConvertUnboxedObjectToNativeFn>(UnboxedArrayObject::convertToNative,
- "UnboxedArrayObject::convertToNative");
typedef bool (*ArrayPopShiftFn)(JSContext*, HandleObject, MutableHandleValue);
static const VMFunction ArrayPopDenseInfo =
@@ -8554,20 +8411,11 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
// Load elements and length, and VM call if length != initializedLength.
RegisterOrInt32Constant key = RegisterOrInt32Constant(lengthTemp);
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
- masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
+ masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
+ masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
- Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
- masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
- } else {
- masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), elementsTemp);
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), lengthTemp);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), lengthTemp);
-
- Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
- masm.branch32(Assembler::NotEqual, lengthAddr, key, ool->entry());
- }
+ Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
// Test for length != 0. On zero length either take a VM call or generate
// an undefined value, depending on whether the call is known to produce
@@ -8579,13 +8427,10 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
// According to the spec we need to set the length 0 (which is already 0).
// This is observable when the array length is made non-writable.
- // Handle this case in the OOL. When freezing an unboxed array it is converted
- // to an normal array.
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
- Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
- masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
- }
+ // Handle this case in the OOL.
+ Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
+ Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
+ masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
masm.moveValue(UndefinedValue(), out.valueReg());
masm.jump(&done);
@@ -8597,41 +8442,25 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
masm.dec32(&key);
if (mir->mode() == MArrayPopShift::Pop) {
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- BaseIndex addr(elementsTemp, lengthTemp, TimesEight);
- masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
- } else {
- size_t elemSize = UnboxedTypeSize(mir->unboxedType());
- BaseIndex addr(elementsTemp, lengthTemp, ScaleFromElemWidth(elemSize));
- masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
- }
+ BaseIndex addr(elementsTemp, lengthTemp, TimesEight);
+ masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
} else {
MOZ_ASSERT(mir->mode() == MArrayPopShift::Shift);
Address addr(elementsTemp, 0);
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC)
- masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
- else
- masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
+ masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
}
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- // Handle the failure case when the array length is non-writable in the
- // OOL path. (Unlike in the adding-an-element cases, we can't rely on the
- // capacity <= length invariant for such arrays to avoid an explicit
- // check.)
- Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
- Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
- masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
+ // Handle the failure case when the array length is non-writable in the
+ // OOL path. (Unlike in the adding-an-element cases, we can't rely on the
+ // capacity <= length invariant for such arrays to avoid an explicit
+ // check.)
+ Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
+ Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
+ masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
- // Now adjust length and initializedLength.
- masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfLength()));
- masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
- } else {
- // Unboxed arrays always have writable lengths. Adjust length and
- // initializedLength.
- masm.store32(lengthTemp, Address(obj, UnboxedArrayObject::offsetOfLength()));
- masm.add32(Imm32(-1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
- }
+ // Now adjust length and initializedLength.
+ masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfLength()));
+ masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
if (mir->mode() == MArrayPopShift::Shift) {
// Don't save the temp registers.
@@ -8670,7 +8499,7 @@ CodeGenerator::visitArrayPopShiftT(LArrayPopShiftT* lir)
emitArrayPopShift(lir, lir->mir(), obj, elements, length, out);
}
-typedef bool (*ArrayPushDenseFn)(JSContext*, HandleObject, HandleValue, uint32_t*);
+typedef bool (*ArrayPushDenseFn)(JSContext*, HandleArrayObject, HandleValue, uint32_t*);
static const VMFunction ArrayPushDenseInfo =
FunctionInfo<ArrayPushDenseFn>(jit::ArrayPushDense, "ArrayPushDense");
@@ -8681,50 +8510,27 @@ CodeGenerator::emitArrayPush(LInstruction* lir, const MArrayPush* mir, Register
OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value), StoreRegisterTo(length));
RegisterOrInt32Constant key = RegisterOrInt32Constant(length);
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- // Load elements and length.
- masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
- masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
-
- // Guard length == initializedLength.
- Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
- masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
- // Guard length < capacity.
- Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
- masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
+ // Load elements and length.
+ masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
+ masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
- // Do the store.
- masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
- } else {
- // Load initialized length.
- masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), length);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), length);
+ // Guard length == initializedLength.
+ Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
- // Guard length == initializedLength.
- Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
- masm.branch32(Assembler::NotEqual, lengthAddr, key, ool->entry());
+ // Guard length < capacity.
+ Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
+ masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
- // Guard length < capacity.
- masm.checkUnboxedArrayCapacity(obj, key, elementsTemp, ool->entry());
-
- // Load elements and do the store.
- masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), elementsTemp);
- size_t elemSize = UnboxedTypeSize(mir->unboxedType());
- BaseIndex addr(elementsTemp, length, ScaleFromElemWidth(elemSize));
- masm.storeUnboxedProperty(addr, mir->unboxedType(), value, nullptr);
- }
+ // Do the store.
+ masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
masm.inc32(&key);
// Update length and initialized length.
- if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
- masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
- masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
- } else {
- masm.store32(length, Address(obj, UnboxedArrayObject::offsetOfLength()));
- masm.add32(Imm32(1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
- }
+ masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
+ masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
masm.bind(ool->rejoin());
}
@@ -10529,22 +10335,11 @@ CodeGenerator::visitLoadElementHole(LLoadElementHole* lir)
else
masm.branch32(Assembler::BelowOrEqual, initLength, ToRegister(lir->index()), &undefined);
- if (mir->unboxedType() != JSVAL_TYPE_MAGIC) {
- size_t width = UnboxedTypeSize(mir->unboxedType());
- if (lir->index()->isConstant()) {
- Address addr(elements, ToInt32(lir->index()) * width);
- masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
- } else {
- BaseIndex addr(elements, ToRegister(lir->index()), ScaleFromElemWidth(width));
- masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
- }
+ if (lir->index()->isConstant()) {
+ NativeObject::elementsSizeMustNotOverflow();
+ masm.loadValue(Address(elements, ToInt32(lir->index()) * sizeof(Value)), out);
} else {
- if (lir->index()->isConstant()) {
- NativeObject::elementsSizeMustNotOverflow();
- masm.loadValue(Address(elements, ToInt32(lir->index()) * sizeof(Value)), out);
- } else {
- masm.loadValue(BaseObjectElementIndex(elements, ToRegister(lir->index())), out);
- }
+ masm.loadValue(BaseObjectElementIndex(elements, ToRegister(lir->index())), out);
}
// If a hole check is needed, and the value wasn't a hole, we're done.
@@ -10922,7 +10717,7 @@ CodeGenerator::visitInArray(LInArray* lir)
}
masm.branch32(Assembler::BelowOrEqual, initLength, Imm32(index), failedInitLength);
- if (mir->needsHoleCheck() && mir->unboxedType() == JSVAL_TYPE_MAGIC) {
+ if (mir->needsHoleCheck()) {
NativeObject::elementsSizeMustNotOverflow();
Address address = Address(elements, index * sizeof(Value));
masm.branchTestMagic(Assembler::Equal, address, &falseBranch);
@@ -10935,7 +10730,7 @@ CodeGenerator::visitInArray(LInArray* lir)
failedInitLength = &negativeIntCheck;
masm.branch32(Assembler::BelowOrEqual, initLength, index, failedInitLength);
- if (mir->needsHoleCheck() && mir->unboxedType() == JSVAL_TYPE_MAGIC) {
+ if (mir->needsHoleCheck()) {
BaseIndex address = BaseIndex(elements, ToRegister(lir->index()), TimesEight);
masm.branchTestMagic(Assembler::Equal, address, &falseBranch);
}
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 292f163b5..b5f170d84 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -234,10 +234,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitSubstr(LSubstr* lir);
void visitInitializedLength(LInitializedLength* lir);
void visitSetInitializedLength(LSetInitializedLength* lir);
- void visitUnboxedArrayLength(LUnboxedArrayLength* lir);
- void visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir);
- void visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir);
- void visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir);
void visitNotO(LNotO* ins);
void visitNotV(LNotV* ins);
void visitBoundsCheck(LBoundsCheck* lir);
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index af85011be..fc864a197 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -2218,6 +2218,8 @@ IonBuilder::inspectOpcode(JSOp op)
// update that stale value.
#endif
default:
+ // Any unused opcodes and JSOP_LIMIT will end up here without having
+ // to explicitly specify
break;
}
@@ -7336,12 +7338,6 @@ IonBuilder::newArrayTryTemplateObject(bool* emitted, JSObject* templateObject, u
if (!templateObject)
return true;
- if (templateObject->is<UnboxedArrayObject>()) {
- MOZ_ASSERT(templateObject->as<UnboxedArrayObject>().capacity() >= length);
- if (!templateObject->as<UnboxedArrayObject>().hasInlineElements())
- return true;
- }
-
MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
size_t arraySlots =
@@ -7597,7 +7593,6 @@ IonBuilder::jsop_initelem_array()
// intializer, and that arrays are marked as non-packed when writing holes
// to them during initialization.
bool needStub = false;
- JSValueType unboxedType = JSVAL_TYPE_MAGIC;
if (shouldAbortOnPreliminaryGroups(obj)) {
needStub = true;
} else if (!obj->resultTypeSet() ||
@@ -7608,12 +7603,6 @@ IonBuilder::jsop_initelem_array()
} else {
MOZ_ASSERT(obj->resultTypeSet()->getObjectCount() == 1);
TypeSet::ObjectKey* initializer = obj->resultTypeSet()->getObject(0);
- if (initializer->clasp() == &UnboxedArrayObject::class_) {
- if (initializer->group()->unboxedLayout().nativeGroup())
- needStub = true;
- else
- unboxedType = initializer->group()->unboxedLayout().elementType();
- }
if (value->type() == MIRType::MagicHole) {
if (!initializer->hasFlags(constraints(), OBJECT_FLAG_NON_PACKED))
needStub = true;
@@ -7633,60 +7622,46 @@ IonBuilder::jsop_initelem_array()
return resumeAfter(store);
}
- return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true);
+ return initializeArrayElement(obj, index, value, /* addResumePoint = */ true);
}
bool
IonBuilder::initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
- JSValueType unboxedType,
bool addResumePointAndIncrementInitializedLength)
{
MConstant* id = MConstant::New(alloc(), Int32Value(index));
current->add(id);
// Get the elements vector.
- MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+ MElements* elements = MElements::New(alloc(), obj);
current->add(elements);
- if (unboxedType != JSVAL_TYPE_MAGIC) {
- // Note: storeUnboxedValue takes care of any post barriers on the value.
- storeUnboxedValue(obj, elements, 0, id, unboxedType, value, /* preBarrier = */ false);
-
- if (addResumePointAndIncrementInitializedLength) {
- MInstruction* increment = MIncrementUnboxedArrayInitializedLength::New(alloc(), obj);
- current->add(increment);
-
- if (!resumeAfter(increment))
- return false;
- }
- } else {
- if (NeedsPostBarrier(value))
- current->add(MPostWriteBarrier::New(alloc(), obj, value));
+ if (NeedsPostBarrier(value))
+ current->add(MPostWriteBarrier::New(alloc(), obj, value));
- if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) ||
- (obj->isNullarySharedStub() &&
- obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles))
- {
- MInstruction* valueDouble = MToDouble::New(alloc(), value);
- current->add(valueDouble);
- value = valueDouble;
- }
+ if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) ||
+ (obj->isNullarySharedStub() &&
+ obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles))
+ {
+ MInstruction* valueDouble = MToDouble::New(alloc(), value);
+ current->add(valueDouble);
+ value = valueDouble;
+ }
- // Store the value.
- MStoreElement* store = MStoreElement::New(alloc(), elements, id, value,
+ // Store the value.
+ MStoreElement* store = MStoreElement::New(alloc(), elements, id, value,
/* needsHoleCheck = */ false);
- current->add(store);
+ current->add(store);
- if (addResumePointAndIncrementInitializedLength) {
- // Update the initialized length. (The template object for this
- // array has the array's ultimate length, so the length field is
- // already correct: no updating needed.)
- MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id);
- current->add(initLength);
+ if (addResumePointAndIncrementInitializedLength) {
+ // Update the initialized length. (The template object for this
+ // array has the array's ultimate length, so the length field is
+ // already correct: no updating needed.)
+ MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id);
+ current->add(initLength);
- if (!resumeAfter(initLength))
- return false;
- }
+ if (!resumeAfter(initLength))
+ return false;
}
return true;
@@ -8175,8 +8150,7 @@ IonBuilder::maybeMarkEmpty(MDefinition* ins)
static bool
ClassHasEffectlessLookup(const Class* clasp)
{
- return (clasp == &UnboxedArrayObject::class_) ||
- IsTypedObjectClass(clasp) ||
+ return IsTypedObjectClass(clasp) ||
(clasp->isNative() && !clasp->getOpsLookupProperty());
}
@@ -9452,12 +9426,9 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
{
MOZ_ASSERT(*emitted == false);
- JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, index);
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- if (!ElementAccessIsDenseNative(constraints(), obj, index)) {
- trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
- return true;
- }
+ if (!ElementAccessIsDenseNative(constraints(), obj, index)) {
+ trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
+ return true;
}
// Don't generate a fast path if there have been bounds check failures
@@ -9474,7 +9445,7 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
return true;
}
- if (!jsop_getelem_dense(obj, index, unboxedType))
+ if (!jsop_getelem_dense(obj, index))
return false;
trackOptimizationSuccess();
@@ -9826,7 +9797,7 @@ IonBuilder::computeHeapType(const TemporaryTypeSet* objTypes, const jsid id)
}
bool
-IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType unboxedType)
+IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index)
{
TemporaryTypeSet* types = bytecodeTypes(pc);
@@ -9850,7 +9821,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
!ElementAccessHasExtraIndexedProperty(this, obj);
MIRType knownType = MIRType::Value;
- if (unboxedType == JSVAL_TYPE_MAGIC && barrier == BarrierKind::NoBarrier)
+ if (barrier == BarrierKind::NoBarrier)
knownType = GetElemKnownType(needsHoleCheck, types);
// Ensure index is an integer.
@@ -9859,13 +9830,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
index = idInt32;
// Get the elements vector.
- MInstruction* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+ MInstruction* elements = MElements::New(alloc(), obj);
current->add(elements);
// Note: to help GVN, use the original MElements instruction and not
// MConvertElementsToDoubles as operand. This is fine because converting
// elements to double does not change the initialized length.
- MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+ MInstruction* initLength = initializedLength(obj, elements);
// If we can load the element as a definite double, make sure to check that
// the array has been converted to homogenous doubles first.
@@ -9881,7 +9852,6 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
}
bool loadDouble =
- unboxedType == JSVAL_TYPE_MAGIC &&
barrier == BarrierKind::NoBarrier &&
loopDepth_ &&
inBounds &&
@@ -9900,18 +9870,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
// hoisting.
index = addBoundsCheck(index, initLength);
- if (unboxedType != JSVAL_TYPE_MAGIC) {
- load = loadUnboxedValue(elements, 0, index, unboxedType, barrier, types);
- } else {
- load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
- current->add(load);
- }
+ load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
+ current->add(load);
} else {
// This load may return undefined, so assume that we *can* read holes,
// or that we can read out-of-bounds accesses. In this case, the bounds
// check is part of the opcode.
- load = MLoadElementHole::New(alloc(), elements, index, initLength,
- unboxedType, needsHoleCheck);
+ load = MLoadElementHole::New(alloc(), elements, index, initLength, needsHoleCheck);
current->add(load);
// If maybeUndefined was true, the typeset must have undefined, and
@@ -9921,8 +9886,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
}
if (knownType != MIRType::Value) {
- if (unboxedType == JSVAL_TYPE_MAGIC)
- load->setResultType(knownType);
+ load->setResultType(knownType);
load->setResultTypeSet(types);
}
@@ -10369,12 +10333,9 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object,
{
MOZ_ASSERT(*emitted == false);
- JSValueType unboxedType = UnboxedArrayElementType(constraints(), object, index);
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- if (!ElementAccessIsDenseNative(constraints(), object, index)) {
- trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
- return true;
- }
+ if (!ElementAccessIsDenseNative(constraints(), object, index)) {
+ trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
+ return true;
}
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
@@ -10408,7 +10369,7 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object,
}
// Emit dense setelem variant.
- if (!jsop_setelem_dense(conversion, object, index, value, unboxedType, writeHole, emitted))
+ if (!jsop_setelem_dense(conversion, object, index, value, writeHole, emitted))
return false;
if (!*emitted) {
@@ -10498,13 +10459,11 @@ IonBuilder::setElemTryCache(bool* emitted, MDefinition* object,
bool
IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
MDefinition* obj, MDefinition* id, MDefinition* value,
- JSValueType unboxedType, bool writeHole, bool* emitted)
+ bool writeHole, bool* emitted)
{
MOZ_ASSERT(*emitted == false);
- MIRType elementType = MIRType::None;
- if (unboxedType == JSVAL_TYPE_MAGIC)
- elementType = DenseNativeElementType(constraints(), obj);
+ MIRType elementType = DenseNativeElementType(constraints(), obj);
bool packed = ElementAccessIsPacked(constraints(), obj);
// Writes which are on holes in the object do not have to bail out if they
@@ -10534,7 +10493,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
// Get the elements vector.
- MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+ MElements* elements = MElements::New(alloc(), obj);
current->add(elements);
// Ensure the value is a double, if double conversion might be needed.
@@ -10571,7 +10530,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
MInstruction* store;
MStoreElementCommon* common = nullptr;
if (writeHole && hasNoExtraIndexedProperty && !mayBeFrozen) {
- MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue, unboxedType);
+ MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue);
store = ins;
common = ins;
@@ -10583,27 +10542,23 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
bool strict = IsStrictSetPC(pc);
MFallibleStoreElement* ins = MFallibleStoreElement::New(alloc(), obj, elements, id,
- newValue, unboxedType, strict);
+ newValue, strict);
store = ins;
common = ins;
current->add(ins);
current->push(value);
} else {
- MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+ MInstruction* initLength = initializedLength(obj, elements);
id = addBoundsCheck(id, initLength);
bool needsHoleCheck = !packed && !hasNoExtraIndexedProperty;
- if (unboxedType != JSVAL_TYPE_MAGIC) {
- store = storeUnboxedValue(obj, elements, 0, id, unboxedType, newValue);
- } else {
- MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
- store = ins;
- common = ins;
+ MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
+ store = ins;
+ common = ins;
- current->add(store);
- }
+ current->add(store);
current->push(value);
}
@@ -10721,18 +10676,6 @@ IonBuilder::jsop_length_fastPath()
return true;
}
- // Compute the length for unboxed array objects.
- if (UnboxedArrayElementType(constraints(), obj, nullptr) != JSVAL_TYPE_MAGIC &&
- !objTypes->hasObjectFlags(constraints(), OBJECT_FLAG_LENGTH_OVERFLOW))
- {
- current->pop();
-
- MUnboxedArrayLength* length = MUnboxedArrayLength::New(alloc(), obj);
- current->add(length);
- current->push(length);
- return true;
- }
-
// Compute the length for array typed objects.
TypedObjectPrediction prediction = typedObjectPrediction(obj);
if (!prediction.isUseless()) {
@@ -13687,11 +13630,8 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
if (shouldAbortOnPreliminaryGroups(obj))
return true;
- JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, id);
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- if (!ElementAccessIsDenseNative(constraints(), obj, id))
- return true;
- }
+ if (!ElementAccessIsDenseNative(constraints(), obj, id))
+ return true;
if (ElementAccessHasExtraIndexedProperty(this, obj))
return true;
@@ -13706,10 +13646,10 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
id = idInt32;
// Get the elements vector.
- MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+ MElements* elements = MElements::New(alloc(), obj);
current->add(elements);
- MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+ MInstruction* initLength = initializedLength(obj, elements);
// If there are no holes, speculate the InArray check will not fail.
if (!needsHoleCheck && !failedBoundsCheck_) {
@@ -13719,8 +13659,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
}
// Check if id < initLength and elem[id] not a hole.
- MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck,
- unboxedType);
+ MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck);
current->add(ins);
current->push(ins);
@@ -14398,32 +14337,24 @@ IonBuilder::constantInt(int32_t i)
}
MInstruction*
-IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements, JSValueType unboxedType)
+IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements)
{
- MInstruction* res;
- if (unboxedType != JSVAL_TYPE_MAGIC)
- res = MUnboxedArrayInitializedLength::New(alloc(), obj);
- else
- res = MInitializedLength::New(alloc(), elements);
+ MInstruction* res = MInitializedLength::New(alloc(), elements);
current->add(res);
return res;
}
MInstruction*
-IonBuilder::setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count)
+IonBuilder::setInitializedLength(MDefinition* obj, size_t count)
{
MOZ_ASSERT(count);
- MInstruction* res;
- if (unboxedType != JSVAL_TYPE_MAGIC) {
- res = MSetUnboxedArrayInitializedLength::New(alloc(), obj, constant(Int32Value(count)));
- } else {
- // MSetInitializedLength takes the index of the last element, rather
- // than the count itself.
- MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false);
- current->add(elements);
- res = MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1)));
- }
+ // MSetInitializedLength takes the index of the last element, rather
+ // than the count itself.
+ MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false);
+ current->add(elements);
+ MInstruction* res =
+ MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1)));
current->add(res);
return res;
}
diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h
index 77528ad37..1b97c4743 100644
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -346,9 +346,8 @@ class IonBuilder
MConstant* constant(const Value& v);
MConstant* constantInt(int32_t i);
- MInstruction* initializedLength(MDefinition* obj, MDefinition* elements,
- JSValueType unboxedType);
- MInstruction* setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count);
+ MInstruction* initializedLength(MDefinition* obj, MDefinition* elements);
+ MInstruction* setInitializedLength(MDefinition* obj, size_t count);
// Improve the type information at tests
MOZ_MUST_USE bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
@@ -611,7 +610,6 @@ class IonBuilder
TypedObjectPrediction elemTypeReprs,
uint32_t elemSize);
MOZ_MUST_USE bool initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
- JSValueType unboxedType,
bool addResumePointAndIncrementInitializedLength);
// jsop_getelem() helpers.
@@ -723,15 +721,13 @@ class IonBuilder
MOZ_MUST_USE bool jsop_bindname(PropertyName* name);
MOZ_MUST_USE bool jsop_bindvar();
MOZ_MUST_USE bool jsop_getelem();
- MOZ_MUST_USE bool jsop_getelem_dense(MDefinition* obj, MDefinition* index,
- JSValueType unboxedType);
+ MOZ_MUST_USE bool jsop_getelem_dense(MDefinition* obj, MDefinition* index);
MOZ_MUST_USE bool jsop_getelem_typed(MDefinition* obj, MDefinition* index,
ScalarTypeDescr::Type arrayType);
MOZ_MUST_USE bool jsop_setelem();
MOZ_MUST_USE bool jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
MDefinition* object, MDefinition* index,
- MDefinition* value, JSValueType unboxedType,
- bool writeHole, bool* emitted);
+ MDefinition* value, bool writeHole, bool* emitted);
MOZ_MUST_USE bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
MDefinition* object, MDefinition* index,
MDefinition* value);
diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp
index 0208db6ae..81cf9d9bb 100644
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -639,9 +639,6 @@ TestMatchingReceiver(MacroAssembler& masm, IonCache::StubAttacher& attacher,
} else {
masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), failure);
}
- } else if (obj->is<UnboxedArrayObject>()) {
- MOZ_ASSERT(failure);
- masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
} else if (obj->is<TypedObject>()) {
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
Address(object, JSObject::offsetOfGroup()),
@@ -1188,39 +1185,6 @@ GenerateArrayLength(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher&
return true;
}
-static void
-GenerateUnboxedArrayLength(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
- JSObject* array, Register object, TypedOrValueRegister output,
- Label* failures)
-{
- Register outReg;
- if (output.hasValue()) {
- outReg = output.valueReg().scratchReg();
- } else {
- MOZ_ASSERT(output.type() == MIRType::Int32);
- outReg = output.typedReg().gpr();
- }
- MOZ_ASSERT(object != outReg);
-
- TestMatchingReceiver(masm, attacher, object, array, failures);
-
- // Load length.
- masm.load32(Address(object, UnboxedArrayObject::offsetOfLength()), outReg);
-
- // Check for a length that fits in an int32.
- masm.branchTest32(Assembler::Signed, outReg, outReg, failures);
-
- if (output.hasValue())
- masm.tagValue(JSVAL_TYPE_INT32, outReg, output.valueReg());
-
- // Success.
- attacher.jumpRejoin(masm);
-
- // Failure.
- masm.bind(failures);
- attacher.jumpNextStub(masm);
-}
-
// In this case, the code for TypedArray and SharedTypedArray is not the same,
// because the code embeds pointers to the respective class arrays. Code that
// caches the stub code must distinguish between the two cases.
@@ -1595,40 +1559,6 @@ GetPropertyIC::tryAttachUnboxedExpando(JSContext* cx, HandleScript outerScript,
}
bool
-GetPropertyIC::tryAttachUnboxedArrayLength(JSContext* cx, HandleScript outerScript, IonScript* ion,
- HandleObject obj, HandleId id, void* returnAddr,
- bool* emitted)
-{
- MOZ_ASSERT(canAttachStub());
- MOZ_ASSERT(!*emitted);
- MOZ_ASSERT(outerScript->ionScript() == ion);
-
- if (!obj->is<UnboxedArrayObject>())
- return true;
-
- if (!JSID_IS_ATOM(id, cx->names().length))
- return true;
-
- if (obj->as<UnboxedArrayObject>().length() > INT32_MAX)
- return true;
-
- if (!allowArrayLength(cx))
- return true;
-
- *emitted = true;
-
- MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
-
- Label failures;
- emitIdGuard(masm, id, &failures);
-
- StubAttacher attacher(*this);
- GenerateUnboxedArrayLength(cx, masm, attacher, obj, object(), output(), &failures);
- return linkAndAttachStub(cx, masm, attacher, ion, "unboxed array length",
- JS::TrackedOutcome::ICGetPropStub_UnboxedArrayLength);
-}
-
-bool
GetPropertyIC::tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript, IonScript* ion,
HandleObject obj, HandleId id, bool* emitted)
{
@@ -2203,9 +2133,6 @@ GetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript*
if (!*emitted && !tryAttachUnboxedExpando(cx, outerScript, ion, obj, id, returnAddr, emitted))
return false;
- if (!*emitted && !tryAttachUnboxedArrayLength(cx, outerScript, ion, obj, id, returnAddr, emitted))
- return false;
-
if (!*emitted && !tryAttachTypedArrayLength(cx, outerScript, ion, obj, id, emitted))
return false;
}
@@ -4026,7 +3953,7 @@ GetPropertyIC::tryAttachDenseElementHole(JSContext* cx, HandleScript outerScript
GetPropertyIC::canAttachTypedOrUnboxedArrayElement(JSObject* obj, const Value& idval,
TypedOrValueRegister output)
{
- if (!obj->is<TypedArrayObject>() && !obj->is<UnboxedArrayObject>())
+ if (!obj->is<TypedArrayObject>())
return false;
MOZ_ASSERT(idval.isInt32() || idval.isString());
@@ -4057,13 +3984,6 @@ GetPropertyIC::canAttachTypedOrUnboxedArrayElement(JSObject* obj, const Value& i
return output.hasValue() || !output.typedReg().isFloat();
}
- if (index >= obj->as<UnboxedArrayObject>().initializedLength())
- return false;
-
- JSValueType elementType = obj->as<UnboxedArrayObject>().elementType();
- if (elementType == JSVAL_TYPE_DOUBLE)
- return output.hasValue();
-
return output.hasValue() || !output.typedReg().isFloat();
}
@@ -4140,46 +4060,27 @@ GenerateGetTypedOrUnboxedArrayElement(JSContext* cx, MacroAssembler& masm,
Label popObjectAndFail;
- if (array->is<TypedArrayObject>()) {
- // Guard on the initialized length.
- Address length(object, TypedArrayObject::lengthOffset());
- masm.branch32(Assembler::BelowOrEqual, length, indexReg, &failures);
+ // Guard on the initialized length.
+ Address length(object, TypedArrayObject::lengthOffset());
+ masm.branch32(Assembler::BelowOrEqual, length, indexReg, &failures);
- // Save the object register on the stack in case of failure.
- Register elementReg = object;
- masm.push(object);
+ // Save the object register on the stack in case of failure.
+ Register elementReg = object;
+ masm.push(object);
- // Load elements vector.
- masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), elementReg);
+ // Load elements vector.
+ masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), elementReg);
- // Load the value. We use an invalid register because the destination
- // register is necessary a non double register.
- Scalar::Type arrayType = array->as<TypedArrayObject>().type();
- int width = Scalar::byteSize(arrayType);
- BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(width));
- if (output.hasValue()) {
- masm.loadFromTypedArray(arrayType, source, output.valueReg(), allowDoubleResult,
- elementReg, &popObjectAndFail);
- } else {
- masm.loadFromTypedArray(arrayType, source, output.typedReg(), elementReg, &popObjectAndFail);
- }
+ // Load the value. We use an invalid register because the destination
+ // register is necessary a non double register.
+ Scalar::Type arrayType = array->as<TypedArrayObject>().type();
+ int width = Scalar::byteSize(arrayType);
+ BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(width));
+ if (output.hasValue()) {
+ masm.loadFromTypedArray(arrayType, source, output.valueReg(), allowDoubleResult,
+ elementReg, &popObjectAndFail);
} else {
- // Save the object register on the stack in case of failure.
- masm.push(object);
-
- // Guard on the initialized length.
- masm.load32(Address(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), object);
- masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), object);
- masm.branch32(Assembler::BelowOrEqual, object, indexReg, &popObjectAndFail);
-
- // Load elements vector.
- Register elementReg = object;
- masm.loadPtr(Address(masm.getStackPointer(), 0), object);
- masm.loadPtr(Address(object, UnboxedArrayObject::offsetOfElements()), elementReg);
-
- JSValueType elementType = array->as<UnboxedArrayObject>().elementType();
- BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(UnboxedTypeSize(elementType)));
- masm.loadUnboxedProperty(source, elementType, output);
+ masm.loadFromTypedArray(arrayType, source, output.typedReg(), elementReg, &popObjectAndFail);
}
masm.pop(object);
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index aafa57c09..68417138b 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2889,32 +2889,6 @@ LIRGenerator::visitSetInitializedLength(MSetInitializedLength* ins)
}
void
-LIRGenerator::visitUnboxedArrayLength(MUnboxedArrayLength* ins)
-{
- define(new(alloc()) LUnboxedArrayLength(useRegisterAtStart(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitUnboxedArrayInitializedLength(MUnboxedArrayInitializedLength* ins)
-{
- define(new(alloc()) LUnboxedArrayInitializedLength(useRegisterAtStart(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitIncrementUnboxedArrayInitializedLength(MIncrementUnboxedArrayInitializedLength* ins)
-{
- add(new(alloc()) LIncrementUnboxedArrayInitializedLength(useRegister(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitSetUnboxedArrayInitializedLength(MSetUnboxedArrayInitializedLength* ins)
-{
- add(new(alloc()) LSetUnboxedArrayInitializedLength(useRegister(ins->object()),
- useRegisterOrConstant(ins->length()),
- temp()), ins);
-}
-
-void
LIRGenerator::visitNot(MNot* ins)
{
MDefinition* op = ins->input();
@@ -3163,22 +3137,16 @@ LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegisterOrConstant(ins->index());
- // Use a temp register when adding new elements to unboxed arrays.
- LDefinition tempDef = LDefinition::BogusTemp();
- if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
- tempDef = temp();
-
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
- lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
- tempDef);
+ lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()));
break;
default:
{
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
- lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, tempDef);
+ lir = new(alloc()) LStoreElementHoleT(object, elements, index, value);
break;
}
}
@@ -3197,20 +3165,14 @@ LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegisterOrConstant(ins->index());
- // Use a temp register when adding new elements to unboxed arrays.
- LDefinition tempDef = LDefinition::BogusTemp();
- if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
- tempDef = temp();
-
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
- lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()),
- tempDef);
+ lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()));
break;
default:
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
- lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value, tempDef);
+ lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value);
break;
}
diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
index e36620bce..b096bb143 100644
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -216,10 +216,6 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitTypedObjectDescr(MTypedObjectDescr* ins);
void visitInitializedLength(MInitializedLength* ins);
void visitSetInitializedLength(MSetInitializedLength* ins);
- void visitUnboxedArrayLength(MUnboxedArrayLength* ins);
- void visitUnboxedArrayInitializedLength(MUnboxedArrayInitializedLength* ins);
- void visitIncrementUnboxedArrayInitializedLength(MIncrementUnboxedArrayInitializedLength* ins);
- void visitSetUnboxedArrayInitializedLength(MSetUnboxedArrayInitializedLength* ins);
void visitNot(MNot* ins);
void visitBoundsCheck(MBoundsCheck* ins);
void visitBoundsCheckLower(MBoundsCheckLower* ins);
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 41ccd0ca7..0d5779cee 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -475,11 +475,6 @@ IonBuilder::inlineArray(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- if (templateObject->is<UnboxedArrayObject>()) {
- if (templateObject->group()->unboxedLayout().nativeGroup())
- return InliningStatus_NotInlined;
- }
-
// Multiple arguments imply array initialization, not just construction.
if (callInfo.argc() >= 2) {
initLength = callInfo.argc();
@@ -527,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.
@@ -542,16 +537,15 @@ IonBuilder::inlineArray(CallInfo& callInfo)
MDefinition* array = current->peek(-1);
if (callInfo.argc() >= 2) {
- JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
for (uint32_t i = 0; i < initLength; i++) {
if (!alloc().ensureBallast())
return InliningStatus_Error;
MDefinition* value = callInfo.getArg(i);
- if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
+ if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
return InliningStatus_Error;
}
- MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
+ MInstruction* setLength = setInitializedLength(array, initLength);
if (!resumeAfter(setLength))
return InliningStatus_Error;
}
@@ -584,7 +578,7 @@ IonBuilder::inlineArrayIsArray(CallInfo& callInfo)
if (!clasp || clasp->isProxy())
return InliningStatus_NotInlined;
- isArray = (clasp == &ArrayObject::class_ || clasp == &UnboxedArrayObject::class_);
+ isArray = (clasp == &ArrayObject::class_);
}
pushConstant(BooleanValue(isArray));
@@ -620,7 +614,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
if (!thisTypes)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+ if (clasp != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
@@ -632,17 +626,9 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
return InliningStatus_NotInlined;
}
- JSValueType unboxedType = JSVAL_TYPE_MAGIC;
- if (clasp == &UnboxedArrayObject::class_) {
- unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
- if (unboxedType == JSVAL_TYPE_MAGIC)
- return InliningStatus_NotInlined;
- }
-
callInfo.setImplicitlyUsedUnchecked();
- if (clasp == &ArrayObject::class_)
- obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+ obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
TemporaryTypeSet* returnTypes = getInlineReturnTypeSet();
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_NON_PACKED);
@@ -653,8 +639,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
if (barrier != BarrierKind::NoBarrier)
returnType = MIRType::Value;
- MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode,
- unboxedType, needsHoleCheck, maybeUndefined);
+ MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode, needsHoleCheck, maybeUndefined);
current->add(ins);
current->push(ins);
ins->setResultType(returnType);
@@ -761,7 +746,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
if (!thisTypes)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+ if (clasp != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -782,13 +767,6 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- JSValueType unboxedType = JSVAL_TYPE_MAGIC;
- if (clasp == &UnboxedArrayObject::class_) {
- unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
- if (unboxedType == JSVAL_TYPE_MAGIC)
- return InliningStatus_NotInlined;
- }
-
callInfo.setImplicitlyUsedUnchecked();
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles ||
@@ -799,13 +777,12 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
value = valueDouble;
}
- if (unboxedType == JSVAL_TYPE_MAGIC)
- obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+ obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
if (NeedsPostBarrier(value))
current->add(MPostWriteBarrier::New(alloc(), obj, value));
- MArrayPush* ins = MArrayPush::New(alloc(), obj, value, unboxedType);
+ MArrayPush* ins = MArrayPush::New(alloc(), obj, value);
current->add(ins);
current->push(ins);
@@ -846,7 +823,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+ if (clasp != &ArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -855,13 +832,6 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- JSValueType unboxedType = JSVAL_TYPE_MAGIC;
- if (clasp == &UnboxedArrayObject::class_) {
- unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
- if (unboxedType == JSVAL_TYPE_MAGIC)
- return InliningStatus_NotInlined;
- }
-
// Watch out for indexed properties on the prototype.
if (ArrayPrototypeHasIndexedProperty(this, script())) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
@@ -882,15 +852,8 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
if (!templateObj)
return InliningStatus_NotInlined;
- if (unboxedType == JSVAL_TYPE_MAGIC) {
- if (!templateObj->is<ArrayObject>())
- return InliningStatus_NotInlined;
- } else {
- if (!templateObj->is<UnboxedArrayObject>())
- return InliningStatus_NotInlined;
- if (templateObj->as<UnboxedArrayObject>().elementType() != unboxedType)
- return InliningStatus_NotInlined;
- }
+ if (!templateObj->is<ArrayObject>())
+ return InliningStatus_NotInlined;
callInfo.setImplicitlyUsedUnchecked();
@@ -909,16 +872,12 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
end = MArrayLength::New(alloc(), elements);
current->add(end->toInstruction());
- } else {
- end = MUnboxedArrayLength::New(alloc(), obj);
- current->add(end->toInstruction());
}
MArraySlice* ins = MArraySlice::New(alloc(), constraints(),
obj, begin, end,
templateObj,
- templateObj->group()->initialHeap(constraints()),
- unboxedType);
+ templateObj->group()->initialHeap(constraints()));
current->add(ins);
current->push(ins);
@@ -1437,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;
@@ -1463,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)
@@ -1500,8 +1459,6 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
return InliningStatus_Inlined;
}
- JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
-
// Store all values, no need to initialize the length after each as
// jsop_initelem_array is doing because we do not expect to bailout
// because the memory is supposed to be allocated by now.
@@ -1512,11 +1469,11 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
MConstant* value = arrayValues[i];
current->add(value);
- if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
+ if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
return InliningStatus_Error;
}
- MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
+ MInstruction* setLength = setInitializedLength(array, initLength);
if (!resumeAfter(setLength))
return InliningStatus_Error;
diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp
index 1f33b2174..6aa46be4b 100644
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -5823,46 +5823,6 @@ jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
return clasp && clasp->isNative() && !IsTypedArrayClass(clasp);
}
-JSValueType
-jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj,
- MDefinition* id)
-{
- if (obj->mightBeType(MIRType::String))
- return JSVAL_TYPE_MAGIC;
-
- if (id && id->type() != MIRType::Int32 && id->type() != MIRType::Double)
- return JSVAL_TYPE_MAGIC;
-
- TemporaryTypeSet* types = obj->resultTypeSet();
- if (!types || types->unknownObject())
- return JSVAL_TYPE_MAGIC;
-
- JSValueType elementType = JSVAL_TYPE_MAGIC;
- for (unsigned i = 0; i < types->getObjectCount(); i++) {
- TypeSet::ObjectKey* key = types->getObject(i);
- if (!key)
- continue;
-
- if (key->unknownProperties() || !key->isGroup())
- return JSVAL_TYPE_MAGIC;
-
- if (key->clasp() != &UnboxedArrayObject::class_)
- return JSVAL_TYPE_MAGIC;
-
- const UnboxedLayout &layout = key->group()->unboxedLayout();
-
- if (layout.nativeGroup())
- return JSVAL_TYPE_MAGIC;
-
- if (elementType == layout.elementType() || elementType == JSVAL_TYPE_MAGIC)
- elementType = layout.elementType();
- else
- return JSVAL_TYPE_MAGIC;
- }
-
- return elementType;
-}
-
bool
jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints,
MDefinition* obj, MDefinition* id,
@@ -6022,11 +5982,6 @@ ObjectSubsumes(TypeSet::ObjectKey* first, TypeSet::ObjectKey* second)
firstElements.maybeTypes()->equals(secondElements.maybeTypes());
}
- if (first->clasp() == &UnboxedArrayObject::class_) {
- return first->group()->unboxedLayout().elementType() ==
- second->group()->unboxedLayout().elementType();
- }
-
return false;
}
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 3e0421789..4bedfb268 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -375,8 +375,7 @@ class AliasSet {
Element = 1 << 1, // A Value member of obj->elements or
// a typed object.
UnboxedElement = 1 << 2, // An unboxed scalar or reference member of
- // a typed array, typed object, or unboxed
- // object.
+ // typed object or unboxed object.
DynamicSlot = 1 << 3, // A Value member of obj->slots.
FixedSlot = 1 << 4, // A Value member of obj->fixedSlots().
DOMProperty = 1 << 5, // A DOM property
@@ -433,9 +432,6 @@ class AliasSet {
MOZ_ASSERT(flags && !(flags & Store_));
return AliasSet(flags | Store_);
}
- static uint32_t BoxedOrUnboxedElements(JSValueType type) {
- return (type == JSVAL_TYPE_MAGIC) ? Element : UnboxedElement;
- }
};
typedef Vector<MDefinition*, 6, JitAllocPolicy> MDefinitionVector;
@@ -8745,102 +8741,6 @@ class MSetInitializedLength
ALLOW_CLONE(MSetInitializedLength)
};
-// Load the length from an unboxed array.
-class MUnboxedArrayLength
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- explicit MUnboxedArrayLength(MDefinition* object)
- : MUnaryInstruction(object)
- {
- setResultType(MIRType::Int32);
- setMovable();
- }
-
- public:
- INSTRUCTION_HEADER(UnboxedArrayLength)
- TRIVIAL_NEW_WRAPPERS
- NAMED_OPERANDS((0, object))
-
- bool congruentTo(const MDefinition* ins) const override {
- return congruentIfOperandsEqual(ins);
- }
- AliasSet getAliasSet() const override {
- return AliasSet::Load(AliasSet::ObjectFields);
- }
-
- ALLOW_CLONE(MUnboxedArrayLength)
-};
-
-// Load the initialized length from an unboxed array.
-class MUnboxedArrayInitializedLength
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- explicit MUnboxedArrayInitializedLength(MDefinition* object)
- : MUnaryInstruction(object)
- {
- setResultType(MIRType::Int32);
- setMovable();
- }
-
- public:
- INSTRUCTION_HEADER(UnboxedArrayInitializedLength)
- TRIVIAL_NEW_WRAPPERS
- NAMED_OPERANDS((0, object))
-
- bool congruentTo(const MDefinition* ins) const override {
- return congruentIfOperandsEqual(ins);
- }
- AliasSet getAliasSet() const override {
- return AliasSet::Load(AliasSet::ObjectFields);
- }
-
- ALLOW_CLONE(MUnboxedArrayInitializedLength)
-};
-
-// Increment the initialized length of an unboxed array object.
-class MIncrementUnboxedArrayInitializedLength
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- explicit MIncrementUnboxedArrayInitializedLength(MDefinition* obj)
- : MUnaryInstruction(obj)
- {}
-
- public:
- INSTRUCTION_HEADER(IncrementUnboxedArrayInitializedLength)
- TRIVIAL_NEW_WRAPPERS
- NAMED_OPERANDS((0, object))
-
- AliasSet getAliasSet() const override {
- return AliasSet::Store(AliasSet::ObjectFields);
- }
-
- ALLOW_CLONE(MIncrementUnboxedArrayInitializedLength)
-};
-
-// Set the initialized length of an unboxed array object.
-class MSetUnboxedArrayInitializedLength
- : public MBinaryInstruction,
- public SingleObjectPolicy::Data
-{
- explicit MSetUnboxedArrayInitializedLength(MDefinition* obj, MDefinition* length)
- : MBinaryInstruction(obj, length)
- {}
-
- public:
- INSTRUCTION_HEADER(SetUnboxedArrayInitializedLength)
- TRIVIAL_NEW_WRAPPERS
- NAMED_OPERANDS((0, object), (1, length))
-
- AliasSet getAliasSet() const override {
- return AliasSet::Store(AliasSet::ObjectFields);
- }
-
- ALLOW_CLONE(MSetUnboxedArrayInitializedLength)
-};
-
// Load the array length from an elements header.
class MArrayLength
: public MUnaryInstruction,
@@ -9334,23 +9234,19 @@ class MLoadElement
ALLOW_CLONE(MLoadElement)
};
-// Load a value from the elements vector for a dense native or unboxed array.
+// Load a value from the elements vector of a native object.
// If the index is out-of-bounds, or the indexed slot has a hole, undefined is
// returned instead.
class MLoadElementHole
: public MTernaryInstruction,
public SingleObjectPolicy::Data
{
- // Unboxed element type, JSVAL_TYPE_MAGIC for dense native elements.
- JSValueType unboxedType_;
-
bool needsNegativeIntCheck_;
bool needsHoleCheck_;
MLoadElementHole(MDefinition* elements, MDefinition* index, MDefinition* initLength,
- JSValueType unboxedType, bool needsHoleCheck)
+ bool needsHoleCheck)
: MTernaryInstruction(elements, index, initLength),
- unboxedType_(unboxedType),
needsNegativeIntCheck_(true),
needsHoleCheck_(needsHoleCheck)
{
@@ -9372,9 +9268,6 @@ class MLoadElementHole
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, elements), (1, index), (2, initLength))
- JSValueType unboxedType() const {
- return unboxedType_;
- }
bool needsNegativeIntCheck() const {
return needsNegativeIntCheck_;
}
@@ -9385,8 +9278,6 @@ class MLoadElementHole
if (!ins->isLoadElementHole())
return false;
const MLoadElementHole* other = ins->toLoadElementHole();
- if (unboxedType() != other->unboxedType())
- return false;
if (needsHoleCheck() != other->needsHoleCheck())
return false;
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
@@ -9394,7 +9285,7 @@ class MLoadElementHole
return congruentIfOperandsEqual(other);
}
AliasSet getAliasSet() const override {
- return AliasSet::Load(AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Load(AliasSet::Element);
}
void collectRangeInfoPreTrunc() override;
@@ -9574,20 +9465,17 @@ class MStoreElement
ALLOW_CLONE(MStoreElement)
};
-// Like MStoreElement, but supports indexes >= initialized length, and can
-// handle unboxed arrays. The downside is that we cannot hoist the elements
-// vector and bounds check, since this instruction may update the (initialized)
-// length and reallocate the elements vector.
+// Like MStoreElement, but supports indexes >= initialized length. The downside
+// is that we cannot hoist the elements vector and bounds check, since this
+// instruction may update the (initialized) length and reallocate the elements
+// vector.
class MStoreElementHole
: public MAryInstruction<4>,
public MStoreElementCommon,
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<3> >::Data
{
- JSValueType unboxedType_;
-
MStoreElementHole(MDefinition* object, MDefinition* elements,
- MDefinition* index, MDefinition* value, JSValueType unboxedType)
- : unboxedType_(unboxedType)
+ MDefinition* index, MDefinition* value)
{
initOperand(0, object);
initOperand(1, elements);
@@ -9602,14 +9490,10 @@ class MStoreElementHole
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
- JSValueType unboxedType() const {
- return unboxedType_;
- }
AliasSet getAliasSet() const override {
// StoreElementHole can update the initialized length, the array length
// or reallocate obj->elements.
- return AliasSet::Store(AliasSet::ObjectFields |
- AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
ALLOW_CLONE(MStoreElementHole)
@@ -9622,13 +9506,11 @@ class MFallibleStoreElement
public MStoreElementCommon,
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<3> >::Data
{
- JSValueType unboxedType_;
bool strict_;
MFallibleStoreElement(MDefinition* object, MDefinition* elements,
MDefinition* index, MDefinition* value,
- JSValueType unboxedType, bool strict)
- : unboxedType_(unboxedType)
+ bool strict)
{
initOperand(0, object);
initOperand(1, elements);
@@ -9644,12 +9526,8 @@ class MFallibleStoreElement
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
- JSValueType unboxedType() const {
- return unboxedType_;
- }
AliasSet getAliasSet() const override {
- return AliasSet::Store(AliasSet::ObjectFields |
- AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
bool strict() const {
return strict_;
@@ -9754,13 +9632,12 @@ class MArrayPopShift
private:
Mode mode_;
- JSValueType unboxedType_;
bool needsHoleCheck_;
bool maybeUndefined_;
- MArrayPopShift(MDefinition* object, Mode mode, JSValueType unboxedType,
+ MArrayPopShift(MDefinition* object, Mode mode,
bool needsHoleCheck, bool maybeUndefined)
- : MUnaryInstruction(object), mode_(mode), unboxedType_(unboxedType),
+ : MUnaryInstruction(object), mode_(mode),
needsHoleCheck_(needsHoleCheck), maybeUndefined_(maybeUndefined)
{ }
@@ -9778,12 +9655,8 @@ class MArrayPopShift
bool mode() const {
return mode_;
}
- JSValueType unboxedType() const {
- return unboxedType_;
- }
AliasSet getAliasSet() const override {
- return AliasSet::Store(AliasSet::ObjectFields |
- AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
ALLOW_CLONE(MArrayPopShift)
@@ -9794,10 +9667,8 @@ class MArrayPush
: public MBinaryInstruction,
public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1> >::Data
{
- JSValueType unboxedType_;
-
- MArrayPush(MDefinition* object, MDefinition* value, JSValueType unboxedType)
- : MBinaryInstruction(object, value), unboxedType_(unboxedType)
+ MArrayPush(MDefinition* object, MDefinition* value)
+ : MBinaryInstruction(object, value)
{
setResultType(MIRType::Int32);
}
@@ -9807,12 +9678,8 @@ class MArrayPush
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, value))
- JSValueType unboxedType() const {
- return unboxedType_;
- }
AliasSet getAliasSet() const override {
- return AliasSet::Store(AliasSet::ObjectFields |
- AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
void computeRange(TempAllocator& alloc) override;
@@ -9826,15 +9693,13 @@ class MArraySlice
{
CompilerObject templateObj_;
gc::InitialHeap initialHeap_;
- JSValueType unboxedType_;
MArraySlice(CompilerConstraintList* constraints, MDefinition* obj,
MDefinition* begin, MDefinition* end,
- JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType)
+ JSObject* templateObj, gc::InitialHeap initialHeap)
: MTernaryInstruction(obj, begin, end),
templateObj_(templateObj),
- initialHeap_(initialHeap),
- unboxedType_(unboxedType)
+ initialHeap_(initialHeap)
{
setResultType(MIRType::Object);
}
@@ -9852,10 +9717,6 @@ class MArraySlice
return initialHeap_;
}
- JSValueType unboxedType() const {
- return unboxedType_;
- }
-
bool possiblyCalls() const override {
return true;
}
@@ -12224,15 +12085,13 @@ class MInArray
{
bool needsHoleCheck_;
bool needsNegativeIntCheck_;
- JSValueType unboxedType_;
MInArray(MDefinition* elements, MDefinition* index,
MDefinition* initLength, MDefinition* object,
- bool needsHoleCheck, JSValueType unboxedType)
+ bool needsHoleCheck)
: MQuaternaryInstruction(elements, index, initLength, object),
needsHoleCheck_(needsHoleCheck),
- needsNegativeIntCheck_(true),
- unboxedType_(unboxedType)
+ needsNegativeIntCheck_(true)
{
setResultType(MIRType::Boolean);
setMovable();
@@ -12252,9 +12111,6 @@ class MInArray
bool needsNegativeIntCheck() const {
return needsNegativeIntCheck_;
}
- JSValueType unboxedType() const {
- return unboxedType_;
- }
void collectRangeInfoPreTrunc() override;
AliasSet getAliasSet() const override {
return AliasSet::Load(AliasSet::Element);
@@ -12267,8 +12123,6 @@ class MInArray
return false;
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
return false;
- if (unboxedType() != other->unboxedType())
- return false;
return congruentIfOperandsEqual(other);
}
};
@@ -14169,8 +14023,6 @@ MDefinition::maybeConstantValue()
bool ElementAccessIsDenseNative(CompilerConstraintList* constraints,
MDefinition* obj, MDefinition* id);
-JSValueType UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj,
- MDefinition* id);
bool ElementAccessIsTypedArray(CompilerConstraintList* constraints,
MDefinition* obj, MDefinition* id,
Scalar::Type* arrayType);
diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h
index b80d1baf9..ab37604b4 100644
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -198,10 +198,6 @@ namespace jit {
_(SetTypedObjectOffset) \
_(InitializedLength) \
_(SetInitializedLength) \
- _(UnboxedArrayLength) \
- _(UnboxedArrayInitializedLength) \
- _(IncrementUnboxedArrayInitializedLength) \
- _(SetUnboxedArrayInitializedLength) \
_(Not) \
_(BoundsCheck) \
_(BoundsCheckLower) \
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
index f633b9b7b..e50f68722 100644
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -705,31 +705,6 @@ template void
MacroAssembler::storeUnboxedProperty(BaseIndex address, JSValueType type,
const ConstantOrRegister& value, Label* failure);
-void
-MacroAssembler::checkUnboxedArrayCapacity(Register obj, const RegisterOrInt32Constant& index,
- Register temp, Label* failure)
-{
- Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
- Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
-
- Label capacityIsIndex, done;
- load32(initLengthAddr, temp);
- branchTest32(Assembler::NonZero, temp, Imm32(UnboxedArrayObject::CapacityMask), &capacityIsIndex);
- branch32(Assembler::BelowOrEqual, lengthAddr, index, failure);
- jump(&done);
- bind(&capacityIsIndex);
-
- // Do a partial shift so that we can get an absolute offset from the base
- // of CapacityArray to use.
- JS_STATIC_ASSERT(sizeof(UnboxedArrayObject::CapacityArray[0]) == 4);
- rshiftPtr(Imm32(UnboxedArrayObject::CapacityShift - 2), temp);
- and32(Imm32(~0x3), temp);
-
- addPtr(ImmPtr(&UnboxedArrayObject::CapacityArray), temp);
- branch32(Assembler::BelowOrEqual, Address(temp, 0), index, failure);
- bind(&done);
-}
-
// Inlined version of gc::CheckAllocatorState that checks the bare essentials
// and bails for anything that cannot be handled with our jit allocators.
void
@@ -1281,16 +1256,6 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject* templateObj,
storePtr(ImmWord(0), Address(obj, UnboxedPlainObject::offsetOfExpando()));
if (initContents)
initUnboxedObjectContents(obj, &templateObj->as<UnboxedPlainObject>());
- } else if (templateObj->is<UnboxedArrayObject>()) {
- MOZ_ASSERT(templateObj->as<UnboxedArrayObject>().hasInlineElements());
- int elementsOffset = UnboxedArrayObject::offsetOfInlineElements();
- computeEffectiveAddress(Address(obj, elementsOffset), temp);
- storePtr(temp, Address(obj, UnboxedArrayObject::offsetOfElements()));
- store32(Imm32(templateObj->as<UnboxedArrayObject>().length()),
- Address(obj, UnboxedArrayObject::offsetOfLength()));
- uint32_t capacityIndex = templateObj->as<UnboxedArrayObject>().capacityIndex();
- store32(Imm32(capacityIndex << UnboxedArrayObject::CapacityShift),
- Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
} else {
MOZ_CRASH("Unknown object");
}
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
index b6616321c..6ee989463 100644
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1626,7 +1626,7 @@ class MacroAssembler : public MacroAssemblerSpecific
void storeToTypedFloatArray(Scalar::Type arrayType, FloatRegister value, const Address& dest,
unsigned numElems = 0);
- // Load a property from an UnboxedPlainObject or UnboxedArrayObject.
+ // Load a property from an UnboxedPlainObject.
template <typename T>
void loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output);
@@ -1637,9 +1637,6 @@ class MacroAssembler : public MacroAssemblerSpecific
void storeUnboxedProperty(T address, JSValueType type,
const ConstantOrRegister& value, Label* failure);
- void checkUnboxedArrayCapacity(Register obj, const RegisterOrInt32Constant& index,
- Register temp, Label* failure);
-
Register extractString(const Address& address, Register scratch) {
return extractObject(address, scratch);
}
diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
index 6fd71f377..8fe6ee3fb 100644
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1355,7 +1355,7 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
RootedValue result(cx);
RootedObjectGroup group(cx, templateObject->group());
- JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
+ ArrayObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
if (!resultObject)
return false;
diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp
index 2065c0371..be9ceee2e 100644
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -795,11 +795,6 @@ IsArrayEscaped(MInstruction* ins)
return true;
}
- if (obj->is<UnboxedArrayObject>()) {
- JitSpew(JitSpew_Escape, "Template object is an unboxed plain object.");
- return true;
- }
-
if (length >= 16) {
JitSpew(JitSpew_Escape, "Array has too many elements");
return true;
diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp
index 2475dfb22..313957462 100644
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -286,11 +286,6 @@ ICStub::trace(JSTracer* trc)
TraceEdge(trc, &getElemStub->shape(), "baseline-getelem-dense-shape");
break;
}
- case ICStub::GetElem_UnboxedArray: {
- ICGetElem_UnboxedArray* getElemStub = toGetElem_UnboxedArray();
- TraceEdge(trc, &getElemStub->group(), "baseline-getelem-unboxed-array-group");
- break;
- }
case ICStub::GetElem_TypedArray: {
ICGetElem_TypedArray* getElemStub = toGetElem_TypedArray();
TraceEdge(trc, &getElemStub->shape(), "baseline-getelem-typedarray-shape");
@@ -2250,7 +2245,6 @@ IsCacheableProtoChain(JSObject* obj, JSObject* holder, bool isDOMProxy)
if (obj == holder)
return false;
if (!obj->is<UnboxedPlainObject>() &&
- !obj->is<UnboxedArrayObject>() &&
!obj->is<TypedObject>())
{
return false;
@@ -2582,9 +2576,6 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
} else if (curObj->is<UnboxedPlainObject>()) {
if (curObj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, NameToId(name)))
return false;
- } else if (curObj->is<UnboxedArrayObject>()) {
- if (name == cx->names().length)
- return false;
} else if (curObj->is<TypedObject>()) {
if (curObj->as<TypedObject>().typeDescr().hasProperty(cx->names(), NameToId(name)))
return false;
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 77b9e3647..297357b1e 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -318,7 +318,7 @@ ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t delet
bool
ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
{
- MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+ MOZ_ASSERT(obj->is<ArrayObject>());
AutoDetectInvalidation adi(cx, rval);
@@ -337,12 +337,11 @@ ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
}
bool
-ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
+ArrayPushDense(JSContext* cx, HandleArrayObject arr, HandleValue v, uint32_t* length)
{
- *length = GetAnyBoxedOrUnboxedArrayLength(obj);
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
- ShouldUpdateTypes::DontUpdate);
+ *length = arr->length();
+ DenseElementResult result = arr->setOrExtendDenseElements(cx, *length, v.address(), 1,
+ ShouldUpdateTypes::DontUpdate);
if (result != DenseElementResult::Incomplete) {
(*length)++;
return result == DenseElementResult::Success;
@@ -350,7 +349,7 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
JS::AutoValueArray<3> argv(cx);
argv[0].setUndefined();
- argv[1].setObject(*obj);
+ argv[1].setObject(*arr);
argv[2].set(v);
if (!js::array_push(cx, 1, argv.begin()))
return false;
@@ -362,7 +361,7 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
bool
ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
{
- MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+ MOZ_ASSERT(obj->is<ArrayObject>());
AutoDetectInvalidation adi(cx, rval);
@@ -1143,16 +1142,14 @@ Recompile(JSContext* cx)
}
bool
-SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
- HandleValue value, bool strict)
+SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index, HandleValue value, bool strict)
{
// This function is called from Ion code for StoreElementHole's OOL path.
- // In this case we know the object is native or an unboxed array and that
- // no type changes are needed.
+ // In this case we know the object is native and that no type changes are
+ // needed.
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, index, value.address(), 1,
- ShouldUpdateTypes::DontUpdate);
+ DenseElementResult result = obj->setOrExtendDenseElements(cx, index, value.address(), 1,
+ ShouldUpdateTypes::DontUpdate);
if (result != DenseElementResult::Incomplete)
return result == DenseElementResult::Success;
diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h
index 572f05373..9a2edd0f3 100644
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -622,7 +622,7 @@ template<bool Equal>
bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res);
MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
-MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length);
+MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleArrayObject obj, HandleValue v, uint32_t* length);
MOZ_MUST_USE bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep);
@@ -748,8 +748,8 @@ ForcedRecompile(JSContext* cx);
JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern,
HandleString repl);
-MOZ_MUST_USE bool SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
- HandleValue value, bool strict);
+MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index,
+ HandleValue value, bool strict);
void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj);
diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h
index f386d5256..ffa4d8367 100644
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -5165,72 +5165,6 @@ class LSetInitializedLength : public LInstructionHelper<0, 2, 0>
}
};
-class LUnboxedArrayLength : public LInstructionHelper<1, 1, 0>
-{
- public:
- LIR_HEADER(UnboxedArrayLength)
-
- explicit LUnboxedArrayLength(const LAllocation& object) {
- setOperand(0, object);
- }
-
- const LAllocation* object() {
- return getOperand(0);
- }
-};
-
-class LUnboxedArrayInitializedLength : public LInstructionHelper<1, 1, 0>
-{
- public:
- LIR_HEADER(UnboxedArrayInitializedLength)
-
- explicit LUnboxedArrayInitializedLength(const LAllocation& object) {
- setOperand(0, object);
- }
-
- const LAllocation* object() {
- return getOperand(0);
- }
-};
-
-class LIncrementUnboxedArrayInitializedLength : public LInstructionHelper<0, 1, 0>
-{
- public:
- LIR_HEADER(IncrementUnboxedArrayInitializedLength)
-
- explicit LIncrementUnboxedArrayInitializedLength(const LAllocation& object) {
- setOperand(0, object);
- }
-
- const LAllocation* object() {
- return getOperand(0);
- }
-};
-
-class LSetUnboxedArrayInitializedLength : public LInstructionHelper<0, 2, 1>
-{
- public:
- LIR_HEADER(SetUnboxedArrayInitializedLength)
-
- explicit LSetUnboxedArrayInitializedLength(const LAllocation& object,
- const LAllocation& length,
- const LDefinition& temp) {
- setOperand(0, object);
- setOperand(1, length);
- setTemp(0, temp);
- }
-
- const LAllocation* object() {
- return getOperand(0);
- }
- const LAllocation* length() {
- return getOperand(1);
- }
- const LDefinition* temp() {
- return getTemp(0);
- }
-};
-
// Load the length from an elements header.
class LArrayLength : public LInstructionHelper<1, 1, 0>
{
@@ -5735,19 +5669,17 @@ class LStoreElementT : public LInstructionHelper<0, 3, 0>
};
// Like LStoreElementV, but supports indexes >= initialized length.
-class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
+class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
{
public:
LIR_HEADER(StoreElementHoleV)
LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
- const LAllocation& index, const LBoxAllocation& value,
- const LDefinition& temp) {
+ const LAllocation& index, const LBoxAllocation& value) {
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
- setTemp(0, temp);
}
static const size_t Value = 3;
@@ -5767,19 +5699,17 @@ class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
};
// Like LStoreElementT, but supports indexes >= initialized length.
-class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
+class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
{
public:
LIR_HEADER(StoreElementHoleT)
LStoreElementHoleT(const LAllocation& object, const LAllocation& elements,
- const LAllocation& index, const LAllocation& value,
- const LDefinition& temp) {
+ const LAllocation& index, const LAllocation& value) {
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
- setTemp(0, temp);
}
const MStoreElementHole* mir() const {
@@ -5800,19 +5730,17 @@ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
};
// Like LStoreElementV, but can just ignore assignment (for eg. frozen objects)
-class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
+class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
{
public:
LIR_HEADER(FallibleStoreElementV)
LFallibleStoreElementV(const LAllocation& object, const LAllocation& elements,
- const LAllocation& index, const LBoxAllocation& value,
- const LDefinition& temp) {
+ const LAllocation& index, const LBoxAllocation& value) {
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
- setTemp(0, temp);
}
static const size_t Value = 3;
@@ -5832,19 +5760,17 @@ class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
};
// Like LStoreElementT, but can just ignore assignment (for eg. frozen objects)
-class LFallibleStoreElementT : public LInstructionHelper<0, 4, 1>
+class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
{
public:
LIR_HEADER(FallibleStoreElementT)
LFallibleStoreElementT(const LAllocation& object, const LAllocation& elements,
- const LAllocation& index, const LAllocation& value,
- const LDefinition& temp) {
+ const LAllocation& index, const LAllocation& value) {
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
- setTemp(0, temp);
}
const MFallibleStoreElement* mir() const {
diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h
index 6912e8904..deae92839 100644
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -267,10 +267,6 @@
_(PostWriteElementBarrierV) \
_(InitializedLength) \
_(SetInitializedLength) \
- _(UnboxedArrayLength) \
- _(UnboxedArrayInitializedLength) \
- _(IncrementUnboxedArrayInitializedLength) \
- _(SetUnboxedArrayInitializedLength) \
_(BoundsCheck) \
_(BoundsCheckRange) \
_(BoundsCheckLower) \
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 005d2278e..3f65dad34 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1093,7 +1093,6 @@ class JS_PUBLIC_API(ContextOptions) {
wasmAlwaysBaseline_(false),
throwOnAsmJSValidationFailure_(false),
nativeRegExp_(true),
- unboxedArrays_(false),
asyncStack_(true),
throwOnDebuggeeWouldRun_(true),
dumpStackOnDebuggeeWouldRun_(false),
@@ -1170,12 +1169,6 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
- bool unboxedArrays() const { return unboxedArrays_; }
- ContextOptions& setUnboxedArrays(bool flag) {
- unboxedArrays_ = flag;
- return *this;
- }
-
bool asyncStack() const { return asyncStack_; }
ContextOptions& setAsyncStack(bool flag) {
asyncStack_ = flag;
@@ -1238,7 +1231,6 @@ class JS_PUBLIC_API(ContextOptions) {
bool wasmAlwaysBaseline_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
bool nativeRegExp_ : 1;
- bool unboxedArrays_ : 1;
bool asyncStack_ : 1;
bool throwOnDebuggeeWouldRun_ : 1;
bool dumpStackOnDebuggeeWouldRun_ : 1;
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 3b4c957dc..5854fda4c 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -64,7 +64,7 @@ using JS::ToUint32;
bool
JS::IsArray(JSContext* cx, HandleObject obj, IsArrayAnswer* answer)
{
- if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
+ if (obj->is<ArrayObject>()) {
*answer = IsArrayAnswer::Array;
return true;
}
@@ -100,11 +100,6 @@ js::GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp)
return true;
}
- if (obj->is<UnboxedArrayObject>()) {
- *lengthp = obj->as<UnboxedArrayObject>().length();
- return true;
- }
-
if (obj->is<ArgumentsObject>()) {
ArgumentsObject& argsobj = obj->as<ArgumentsObject>();
if (!argsobj.hasOverriddenLength()) {
@@ -253,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;
+ }
}
}
@@ -283,8 +280,8 @@ ElementAdder::append(JSContext* cx, HandleValue v)
{
MOZ_ASSERT(index_ < length_);
if (resObj_) {
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
+ NativeObject* resObj = &resObj_->as<NativeObject>();
+ DenseElementResult result = resObj->setOrExtendDenseElements(cx, index_, v.address(), 1);
if (result == DenseElementResult::Failure)
return false;
if (result == DenseElementResult::Incomplete) {
@@ -336,37 +333,31 @@ js::GetElementsWithAdder(JSContext* cx, HandleObject obj, HandleObject receiver,
return true;
}
-template <JSValueType Type>
-DenseElementResult
-GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp)
+static bool
+GetDenseElements(NativeObject* aobj, uint32_t length, Value* vp)
{
MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj));
- if (length > GetBoxedOrUnboxedInitializedLength<Type>(aobj))
- return DenseElementResult::Incomplete;
+ if (length > aobj->getDenseInitializedLength())
+ return false;
for (size_t i = 0; i < length; i++) {
- vp[i] = GetBoxedOrUnboxedDenseElement<Type>(aobj, i);
+ vp[i] = aobj->getDenseElement(i);
// No other indexed properties so hole => undefined.
if (vp[i].isMagic(JS_ELEMENTS_HOLE))
vp[i] = UndefinedValue();
}
- return DenseElementResult::Success;
+ return true;
}
-DefineBoxedOrUnboxedFunctor3(GetBoxedOrUnboxedDenseElements,
- JSObject*, uint32_t, Value*);
-
bool
js::GetElements(JSContext* cx, HandleObject aobj, uint32_t length, Value* vp)
{
if (!ObjectMayHaveExtraIndexedProperties(aobj)) {
- GetBoxedOrUnboxedDenseElementsFunctor functor(aobj, length, vp);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, aobj);
- if (result != DenseElementResult::Incomplete)
- return result == DenseElementResult::Success;
+ if (GetDenseElements(&aobj->as<NativeObject>(), length, vp))
+ return true;
}
if (aobj->is<ArgumentsObject>()) {
@@ -398,9 +389,9 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
{
MOZ_ASSERT(index >= 0);
- if ((obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) && !obj->isIndexed() && index <= UINT32_MAX) {
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, uint32_t(index), v.address(), 1);
+ if (obj->is<ArrayObject>() && !obj->isIndexed() && index <= UINT32_MAX) {
+ NativeObject* nobj = &obj->as<NativeObject>();
+ DenseElementResult result = nobj->setOrExtendDenseElements(cx, uint32_t(index), v.address(), 1);
if (result != DenseElementResult::Incomplete)
return result == DenseElementResult::Success;
}
@@ -520,24 +511,6 @@ struct ReverseIndexComparator
}
};
-bool
-js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
-{
- double d;
-
- if (!ToUint32(cx, v, newLen))
- return false;
-
- if (!ToNumber(cx, v, &d))
- return false;
-
- if (d == *newLen)
- return true;
-
- JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
- return false;
-}
-
/* ES6 draft rev 34 (2015 Feb 20) 9.4.2.4 ArraySetLength */
bool
js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
@@ -559,12 +532,22 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
} else {
// Step 2 is irrelevant in our implementation.
- // Steps 3-7.
- MOZ_ASSERT_IF(attrs & JSPROP_IGNORE_VALUE, value.isUndefined());
- if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
+ // Step 3.
+ if (!ToUint32(cx, value, &newLen))
+ return false;
+
+ // Step 4.
+ double d;
+ if (!ToNumber(cx, value, &d))
return false;
- // Step 8 is irrelevant in our implementation.
+ // Step 5.
+ if (d != newLen) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
+ return false;
+ }
+
+ // Steps 6-8 are irrelevant in our implementation.
}
// Steps 9-11.
@@ -823,7 +806,7 @@ array_addProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
static inline bool
ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj)
{
- return (!obj->isNative() && !obj->is<UnboxedArrayObject>()) ||
+ return !obj->isNative() ||
obj->isIndexed() ||
obj->is<TypedArrayObject>() ||
ClassMayResolveId(*obj->runtimeFromAnyThread()->commonNames,
@@ -854,7 +837,7 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject* obj)
if (ObjectMayHaveExtraIndexedOwnProperties(obj))
return true;
- if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0)
+ if (obj->as<NativeObject>().getDenseInitializedLength() != 0)
return true;
} while (true);
}
@@ -1064,31 +1047,32 @@ struct StringSeparatorOp
}
};
-template <typename SeparatorOp, JSValueType Type>
-static DenseElementResult
-ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
+template <typename SeparatorOp>
+static bool
+ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleNativeObject obj, uint64_t length,
StringBuffer& sb, uint32_t* numProcessed)
{
// This loop handles all elements up to initializedLength. If
// length > initLength we rely on the second loop to add the
// other elements.
MOZ_ASSERT(*numProcessed == 0);
- uint32_t initLength = Min<uint32_t>(GetBoxedOrUnboxedInitializedLength<Type>(obj), length);
+ uint32_t initLength = Min<uint32_t>(obj->getDenseInitializedLength(),
+ length);
while (*numProcessed < initLength) {
if (!CheckForInterrupt(cx))
- return DenseElementResult::Failure;
+ return false;
- Value elem = GetBoxedOrUnboxedDenseElement<Type>(obj, *numProcessed);
+ Value elem = obj->as<NativeObject>().getDenseElement(*numProcessed);
if (elem.isString()) {
if (!sb.append(elem.toString()))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isNumber()) {
if (!NumberValueToStringBuffer(cx, elem, sb))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isBoolean()) {
if (!BooleanToStringBuffer(elem.toBoolean(), sb))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isObject() || elem.isSymbol()) {
/*
* Object stringifying could modify the initialized length or make
@@ -1104,33 +1088,13 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_
}
if (++(*numProcessed) != length && !sepOp(cx, sb))
- return DenseElementResult::Failure;
+ return false;
}
- return DenseElementResult::Incomplete;
+ return true;
}
template <typename SeparatorOp>
-struct ArrayJoinDenseKernelFunctor {
- JSContext* cx;
- SeparatorOp sepOp;
- HandleObject obj;
- uint32_t length;
- StringBuffer& sb;
- uint32_t* numProcessed;
-
- ArrayJoinDenseKernelFunctor(JSContext* cx, SeparatorOp sepOp, HandleObject obj,
- uint32_t length, StringBuffer& sb, uint32_t* numProcessed)
- : cx(cx), sepOp(sepOp), obj(obj), length(length), sb(sb), numProcessed(numProcessed)
- {}
-
- template <JSValueType Type>
- DenseElementResult operator()() {
- return ArrayJoinDenseKernel<SeparatorOp, Type>(cx, sepOp, obj, length, sb, numProcessed);
- }
-};
-
-template <typename SeparatorOp>
static bool
ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
StringBuffer& sb)
@@ -1138,10 +1102,10 @@ ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t len
uint32_t i = 0;
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
- ArrayJoinDenseKernelFunctor<SeparatorOp> functor(cx, sepOp, obj, length, sb, &i);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
- if (result == DenseElementResult::Failure)
+ if (!ArrayJoinDenseKernel<SeparatorOp>(cx, sepOp, obj.as<NativeObject>(), length, sb, &i))
+ {
return false;
+ }
}
if (i != length) {
@@ -1212,11 +1176,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;
+ }
}
}
@@ -1259,7 +1226,7 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
}
// Step 11
- JSString *str = sb.finishString();
+ JSString* str = sb.finishString();
if (!str)
return false;
@@ -1288,10 +1255,6 @@ array_toLocaleString(JSContext* cx, unsigned argc, Value* vp)
args.rval().setString(cx->names().empty);
return true;
}
- if (obj->is<UnboxedArrayObject>() && obj->as<UnboxedArrayObject>().length() == 0) {
- args.rval().setString(cx->names().empty);
- return true;
- }
AutoCycleDetector detector(cx, obj);
if (!detector.init())
@@ -1328,8 +1291,9 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
return false;
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, start, vector, count, updateTypes);
+ NativeObject* nobj = &obj->as<NativeObject>();
+ DenseElementResult result = nobj->setOrExtendDenseElements(cx, uint32_t(start), vector,
+ count, updateTypes);
if (result != DenseElementResult::Incomplete)
return result == DenseElementResult::Success;
}
@@ -1363,54 +1327,45 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
return true;
}
-template <JSValueType Type>
-DenseElementResult
-ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
+static DenseElementResult
+ArrayReverseDenseKernel(JSContext* cx, HandleNativeObject obj, uint32_t length)
{
/* An empty array or an array with no elements is already reversed. */
- if (length == 0 || GetBoxedOrUnboxedInitializedLength<Type>(obj) == 0)
+ if (length == 0 || obj->getDenseInitializedLength() == 0)
return DenseElementResult::Success;
- if (Type == JSVAL_TYPE_MAGIC) {
- if (obj->as<NativeObject>().denseElementsAreFrozen())
- return DenseElementResult::Incomplete;
+ if (obj->denseElementsAreFrozen())
+ return DenseElementResult::Incomplete;
- /*
- * It's actually surprisingly complicated to reverse an array due to the
- * orthogonality of array length and array capacity while handling
- * leading and trailing holes correctly. Reversing seems less likely to
- * be a common operation than other array mass-mutation methods, so for
- * now just take a probably-small memory hit (in the absence of too many
- * holes in the array at its start) and ensure that the capacity is
- * sufficient to hold all the elements in the array if it were full.
- */
- DenseElementResult result = obj->as<NativeObject>().ensureDenseElements(cx, length, 0);
- if (result != DenseElementResult::Success)
- return result;
+ /*
+ * It's actually surprisingly complicated to reverse an array due to the
+ * orthogonality of array length and array capacity while handling
+ * leading and trailing holes correctly. Reversing seems less likely to
+ * be a common operation than other array mass-mutation methods, so for
+ * now just take a probably-small memory hit (in the absence of too many
+ * holes in the array at its start) and ensure that the capacity is
+ * sufficient to hold all the elements in the array if it were full.
+ */
+ DenseElementResult result = obj->ensureDenseElements(cx, length, 0);
+ if (result != DenseElementResult::Success)
+ return result;
- /* Fill out the array's initialized length to its proper length. */
- obj->as<NativeObject>().ensureDenseInitializedLength(cx, length, 0);
- } else {
- // Unboxed arrays can only be reversed here if their initialized length
- // matches their actual length. Otherwise the reversal will place holes
- // at the beginning of the array, which we don't support.
- if (length != obj->as<UnboxedArrayObject>().initializedLength())
- return DenseElementResult::Incomplete;
- }
+ /* Fill out the array's initialized length to its proper length. */
+ obj->ensureDenseInitializedLength(cx, length, 0);
RootedValue origlo(cx), orighi(cx);
uint32_t lo = 0, hi = length - 1;
for (; lo < hi; lo++, hi--) {
- origlo = GetBoxedOrUnboxedDenseElement<Type>(obj, lo);
- orighi = GetBoxedOrUnboxedDenseElement<Type>(obj, hi);
- SetBoxedOrUnboxedDenseElementNoTypeChange<Type>(obj, lo, orighi);
+ origlo = obj->getDenseElement(lo);
+ orighi = obj->getDenseElement(hi);
+ obj->setDenseElement(lo, orighi);
if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
{
return DenseElementResult::Failure;
}
- SetBoxedOrUnboxedDenseElementNoTypeChange<Type>(obj, hi, origlo);
+ obj->setDenseElement(hi, origlo);
if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
{
@@ -1421,9 +1376,6 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
return DenseElementResult::Success;
}
-DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
- JSContext*, HandleObject, uint32_t);
-
bool
js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
{
@@ -1438,8 +1390,8 @@ js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
return false;
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
- ArrayReverseDenseKernelFunctor functor(cx, obj, len);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+ DenseElementResult result =
+ ArrayReverseDenseKernel(cx, obj.as<NativeObject>(), uint32_t(len));
if (result != DenseElementResult::Incomplete) {
/*
* Per ECMA-262, don't update the length of the array, even if the new
@@ -2082,8 +2034,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, length,
- args.array(), args.length());
+ obj->as<NativeObject>().setOrExtendDenseElements(cx, uint32_t(length),
+ args.array(), args.length());
if (result != DenseElementResult::Incomplete) {
if (result == DenseElementResult::Failure)
return false;
@@ -2091,14 +2043,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
uint32_t newlength = length + args.length();
args.rval().setNumber(newlength);
- // SetOrExtendAnyBoxedOrUnboxedDenseElements 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;
@@ -2154,42 +2100,46 @@ js::array_pop(JSContext* cx, unsigned argc, Value* vp)
return SetLengthProperty(cx, obj, index);
}
-template <JSValueType Type>
-static inline DenseElementResult
-ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
+void
+js::ArrayShiftMoveElements(NativeObject* obj)
{
- MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj));
+ MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
+
+ size_t initlen = obj->getDenseInitializedLength();
+ MOZ_ASSERT(initlen > 0);
/*
* 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<Type>(obj);
- if (Type == JSVAL_TYPE_MAGIC) {
- obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
- } else {
- uint8_t* data = obj->as<UnboxedArrayObject>().elements();
- size_t elementSize = UnboxedTypeSize(Type);
- memmove(data, data + elementSize, initlen * elementSize);
- }
-
- return DenseElementResult::Success;
+ obj->moveDenseElementsNoPreBarrier(0, 1, initlen);
}
-DefineBoxedOrUnboxedFunctor1(ShiftMoveBoxedOrUnboxedDenseElements, JSObject*);
+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);
+}
-void
-js::ArrayShiftMoveElements(JSObject* obj)
+static DenseElementResult
+MoveDenseElements(JSContext* cx, NativeObject* obj, uint32_t dstStart, uint32_t srcStart,
+ uint32_t length)
{
- MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
+ if (obj->denseElementsAreFrozen())
+ return DenseElementResult::Incomplete;
- ShiftMoveBoxedOrUnboxedDenseElementsFunctor functor(obj);
- JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
+ if (!obj->maybeCopyElementsForWrite(cx))
+ return DenseElementResult::Failure;
+ obj->moveDenseElements(dstStart, srcStart, length);
+
+ return DenseElementResult::Success;
}
-template <JSValueType Type>
-DenseElementResult
+static DenseElementResult
ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
{
if (ObjectMayHaveExtraIndexedProperties(obj))
@@ -2202,25 +2152,22 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED)))
return DenseElementResult::Incomplete;
- size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
+ size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
if (initlen == 0)
return DenseElementResult::Incomplete;
- rval.set(GetBoxedOrUnboxedDenseElement<Type>(obj, 0));
+ rval.set(obj->as<NativeObject>().getDenseElement(0));
if (rval.isMagic(JS_ELEMENTS_HOLE))
rval.setUndefined();
- DenseElementResult result = MoveBoxedOrUnboxedDenseElements<Type>(cx, obj, 0, 1, initlen - 1);
+ DenseElementResult result = MoveDenseElements(cx, &obj->as<NativeObject>(), 0, 1, initlen - 1);
if (result != DenseElementResult::Success)
return result;
- SetBoxedOrUnboxedInitializedLength<Type>(cx, obj, initlen - 1);
+ SetInitializedLength(cx, obj.as<NativeObject>(), initlen - 1);
return DenseElementResult::Success;
}
-DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
- JSContext*, HandleObject, MutableHandleValue);
-
/* ES5 15.4.4.9 */
bool
js::array_shift(JSContext* cx, unsigned argc, Value* vp)
@@ -2252,8 +2199,7 @@ js::array_shift(JSContext* cx, unsigned argc, Value* vp)
uint32_t newlen = len - 1;
/* Fast paths. */
- ArrayShiftDenseKernelFunctor functor(cx, obj, args.rval());
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+ DenseElementResult result = ArrayShiftDenseKernel(cx, obj, args.rval());
if (result != DenseElementResult::Incomplete) {
if (result == DenseElementResult::Failure)
return false;
@@ -2307,9 +2253,6 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
if (args.length() > 0) {
/* Slide up the array to make room for all args at the bottom. */
if (length > 0) {
- // Only include a fast path for boxed arrays. Unboxed arrays can'nt
- // be optimized here because unshifting temporarily places holes at
- // the start of the array.
bool optimized = false;
do {
if (!obj->is<ArrayObject>())
@@ -2369,10 +2312,10 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
}
/*
- * Returns true if this is a dense or unboxed array whose |count| properties
- * starting from |startingIndex| may be accessed (get, set, delete) directly
- * through its contiguous vector of elements without fear of getters, setters,
- * etc. along the prototype chain, or of enumerators requiring notification of
+ * Returns true if this is a dense array whose properties ending at |endIndex|
+ * (exclusive) may be accessed (get, set, delete) directly through its
+ * contiguous vector of elements without fear of getters, setters, etc. along
+ * the prototype chain, or of enumerators requiring notification of
* modifications.
*/
static inline bool
@@ -2383,11 +2326,11 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
return false;
/* There's no optimizing possible if it's not an array. */
- if (!arr->is<ArrayObject>() && !arr->is<UnboxedArrayObject>())
+ if (!arr->is<ArrayObject>())
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;
/*
@@ -2419,7 +2362,23 @@ 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();
+}
+
+static inline DenseElementResult
+CopyDenseElements(JSContext* cx, NativeObject* dst, NativeObject* src,
+ uint32_t dstStart, uint32_t srcStart, uint32_t length)
+{
+ MOZ_ASSERT(dst->getDenseInitializedLength() == dstStart);
+ MOZ_ASSERT(src->getDenseInitializedLength() >= srcStart + length);
+ MOZ_ASSERT(dst->getDenseCapacity() >= dstStart + length);
+
+ dst->setDenseInitializedLength(dstStart + length);
+
+ const Value* vp = src->getDenseElements() + srcStart;
+ dst->initDenseElements(dstStart, vp, length);
+
+ return DenseElementResult::Success;
}
/* ES 2016 draft Mar 25, 2016 22.1.3.26. */
@@ -2520,7 +2479,9 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
/* Steps 10-11. */
DebugOnly<DenseElementResult> result =
- CopyAnyBoxedOrUnboxedDenseElements(cx, arr, obj, 0, actualStart, actualDeleteCount);
+ CopyDenseElements(cx, &arr->as<NativeObject>(),
+ &obj->as<NativeObject>(), 0,
+ actualStart, actualDeleteCount);
MOZ_ASSERT(result.value == DenseElementResult::Success);
/* Step 12 (implicit). */
@@ -2557,14 +2518,13 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
if (CanOptimizeForDenseStorage(obj, 0, len, cx)) {
/* Steps 15.a-b. */
DenseElementResult result =
- MoveAnyBoxedOrUnboxedDenseElements(cx, obj, targetIndex, sourceIndex,
- len - sourceIndex);
+ MoveDenseElements(cx, &obj->as<NativeObject>(), targetIndex, sourceIndex, len - sourceIndex);
MOZ_ASSERT(result != DenseElementResult::Incomplete);
if (result == DenseElementResult::Failure)
return false;
/* Steps 15.c-d. */
- SetAnyBoxedOrUnboxedInitializedLength(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
@@ -2644,15 +2604,15 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
DenseElementResult result =
- MoveAnyBoxedOrUnboxedDenseElements(cx, obj, actualStart + itemCount,
- actualStart + actualDeleteCount,
- len - (actualStart + actualDeleteCount));
+ MoveDenseElements(cx, &obj->as<NativeObject>(), actualStart + itemCount,
+ actualStart + actualDeleteCount,
+ len - (actualStart + actualDeleteCount));
MOZ_ASSERT(result != DenseElementResult::Incomplete);
if (result == DenseElementResult::Failure)
return false;
/* Steps 16.a-b. */
- SetAnyBoxedOrUnboxedInitializedLength(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--) {
@@ -2824,7 +2784,7 @@ SliceSlowly(JSContext* cx, HandleObject obj, HandleObject receiver,
}
static bool
-SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleObject result)
+SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleArrayObject result)
{
MOZ_ASSERT(begin <= end);
@@ -2874,26 +2834,28 @@ 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);
- RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
+ RootedArrayObject 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 =
- CopyAnyBoxedOrUnboxedDenseElements(cx, narr, obj, 0, begin, count);
+ CopyDenseElements(cx, &narr->as<NativeObject>(), &obj->as<NativeObject>(), 0, begin, count);
MOZ_ASSERT(result.value == DenseElementResult::Success);
}
arr.set(narr);
return true;
}
- RootedObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
+ RootedArrayObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
if (!narr)
return false;
@@ -3010,11 +2972,10 @@ js::array_slice(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-template <JSValueType Type>
-DenseElementResult
-ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result)
+static bool
+ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, int32_t beginArg, int32_t endArg, ArrayObject* result)
{
- int32_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
+ int32_t length = arr->length();
uint32_t begin = NormalizeSliceTerm(beginArg, length);
uint32_t end = NormalizeSliceTerm(endArg, length);
@@ -3022,33 +2983,33 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
if (begin > end)
begin = end;
- size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
+ size_t initlen = arr->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<Type>(cx, result, count);
- if (rv != DenseElementResult::Success)
- return rv;
- CopyBoxedOrUnboxedDenseElements<Type, Type>(cx, result, obj, 0, begin, count);
+ if (!result->ensureElements(cx, count))
+ return false;
+ CopyDenseElements(cx, &result->as<NativeObject>(), &arr->as<NativeObject>(), 0, begin, count);
}
}
- SetAnyBoxedOrUnboxedArrayLength(cx, result, end - begin);
- return DenseElementResult::Success;
-}
+ MOZ_ASSERT(count >= result->length());
+ result->setLength(cx, count);
-DefineBoxedOrUnboxedFunctor5(ArraySliceDenseKernel,
- JSContext*, JSObject*, int32_t, int32_t, JSObject*);
+ return true;
+}
JSObject*
js::array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end,
HandleObject result)
{
if (result && IsArraySpecies(cx, obj)) {
- ArraySliceDenseKernelFunctor functor(cx, obj, begin, end, result);
- DenseElementResult rv = CallBoxedOrUnboxedSpecialization(functor, result);
- MOZ_ASSERT(rv != DenseElementResult::Incomplete);
- return rv == DenseElementResult::Success ? result : nullptr;
+ if (!ArraySliceDenseKernel(cx, &obj->as<ArrayObject>(), begin, end,
+ &result->as<ArrayObject>()))
+ {
+ return nullptr;
+ }
+ return result;
}
// Slower path if the JIT wasn't able to allocate an object inline.
@@ -3079,7 +3040,7 @@ array_isArray(JSContext* cx, unsigned argc, Value* vp)
static bool
ArrayFromCallArgs(JSContext* cx, CallArgs& args, HandleObject proto = nullptr)
{
- JSObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
+ ArrayObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
if (!obj)
return false;
@@ -3244,7 +3205,7 @@ ArrayConstructorImpl(JSContext* cx, CallArgs& args, bool isConstructor)
}
}
- JSObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
+ ArrayObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
if (!obj)
return false;
@@ -3270,7 +3231,7 @@ js::array_construct(JSContext* cx, unsigned argc, Value* vp)
return ArrayConstructorImpl(cx, args, /* isConstructor = */ false);
}
-JSObject*
+ArrayObject*
js::ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt)
{
if (lengthInt < 0) {
@@ -3565,7 +3526,7 @@ js::NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSOb
return arr;
}
-JSObject*
+ArrayObject*
js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap)
{
MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
@@ -3578,30 +3539,21 @@ js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc
return arr;
}
-// Return a new boxed or unboxed array with the specified length and allocated
-// capacity (up to maxLength), using the specified group if possible. If the
-// specified group cannot be used, ensure that the created array at least has
-// the given [[Prototype]].
+// Return a new array with the specified length and allocated capacity (up to
+// maxLength), using the specified group if possible. If the specified group
+// cannot be used, ensure that the created array at least has the given
+// [[Prototype]].
template <uint32_t maxLength>
-static inline JSObject*
+static inline ArrayObject*
NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind = GenericObject)
{
MOZ_ASSERT(newKind != SingletonObject);
- if (group->maybePreliminaryObjects())
- group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
-
- if (group->shouldPreTenure() || group->maybePreliminaryObjects())
+ if (group->shouldPreTenure())
newKind = TenuredObject;
RootedObject proto(cx, group->proto().toObject());
- if (group->maybeUnboxedLayout()) {
- if (length > UnboxedArrayObject::MaximumCapacity)
- return NewArray<maxLength>(cx, length, proto, newKind);
- return UnboxedArrayObject::create(cx, group, length, newKind, maxLength);
- }
-
ArrayObject* res = NewArray<maxLength>(cx, length, proto, newKind);
if (!res)
return nullptr;
@@ -3613,20 +3565,17 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
if (res->length() > INT32_MAX)
res->setLength(cx, res->length());
- if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
- preliminaryObjects->registerNewObject(res);
-
return res;
}
-JSObject*
+ArrayObject*
js::NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind)
{
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
}
-JSObject*
+ArrayObject*
js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length)
{
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
@@ -3635,16 +3584,13 @@ js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup g
// Return a new array with the default prototype and specified allocated
// capacity and length. If possible, try to reuse the group of the input
// object. The resulting array will either reuse the input object's group or
-// will have unknown property types. Additionally, the result will have the
-// same boxed/unboxed elements representation as the input object, unless
-// |length| is larger than the input object's initialized length (in which case
-// UnboxedArrayObject::MaximumCapacity might be exceeded).
+// will have unknown property types.
template <uint32_t maxLength>
-static inline JSObject*
+static inline ArrayObject*
NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind = GenericObject)
{
- if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>())
+ if (!obj->is<ArrayObject>())
return NewArray<maxLength>(cx, length, nullptr, newKind);
if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype())
@@ -3657,20 +3603,20 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
return NewArrayTryUseGroup<maxLength>(cx, group, length, newKind);
}
-JSObject*
+ArrayObject*
js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind)
{
return NewArrayTryReuseGroup<UINT32_MAX>(cx, obj, length, newKind);
}
-JSObject*
+ArrayObject*
js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length)
{
return NewArrayTryReuseGroup<ArrayObject::EagerAllocationMaxLength>(cx, obj, length);
}
-JSObject*
+ArrayObject*
js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
NewObjectKind newKind)
{
@@ -3680,7 +3626,7 @@ js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
}
-JSObject*
+ArrayObject*
js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto)
{
RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto));
@@ -3689,68 +3635,23 @@ js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
}
-bool
-js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
- const Value* vp, size_t length)
-{
- static const size_t EagerPreliminaryObjectAnalysisThreshold = 800;
-
- // Force analysis to see if an unboxed array can be used when making a
- // sufficiently large array, to avoid excessive analysis and copying later
- // on. If this is the first array of its group that is being created, first
- // make a dummy array with the initial elements of the array we are about
- // to make, so there is some basis for the unboxed array analysis.
- if (length > EagerPreliminaryObjectAnalysisThreshold) {
- if (PreliminaryObjectArrayWithTemplate* objects = group->maybePreliminaryObjects()) {
- if (objects->empty()) {
- size_t nlength = Min<size_t>(length, 100);
- JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, nlength);
- if (!obj)
- return false;
- DebugOnly<DenseElementResult> result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength,
- ShouldUpdateTypes::Update);
- MOZ_ASSERT(result.value == DenseElementResult::Success);
- }
- objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true);
- }
- }
- return true;
-}
-
-JSObject*
+ArrayObject*
js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length, NewObjectKind newKind,
ShouldUpdateTypes updateTypes)
{
- if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
- return nullptr;
-
- JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
+ ArrayObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
if (!obj)
return nullptr;
- DenseElementResult result =
- SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, 0, vp, length, updateTypes);
- if (result == DenseElementResult::Failure)
- return nullptr;
- if (result == DenseElementResult::Success)
- return obj;
-
- MOZ_ASSERT(obj->is<UnboxedArrayObject>());
- if (!UnboxedArrayObject::convertToNative(cx->asJSContext(), obj))
- return nullptr;
-
- result = SetOrExtendBoxedOrUnboxedDenseElements<JSVAL_TYPE_MAGIC>(cx, obj, 0, vp, length,
- updateTypes);
- MOZ_ASSERT(result != DenseElementResult::Incomplete);
+ DenseElementResult result = obj->setOrExtendDenseElements(cx->asJSContext(), 0, vp, length, updateTypes);
if (result == DenseElementResult::Failure)
return nullptr;
-
+ MOZ_ASSERT(result == DenseElementResult::Success);
return obj;
}
-JSObject*
+ArrayObject*
js::NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
HandleObject proto /* = nullptr */)
{
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index e22cde881..ec2e4f514 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -72,49 +72,37 @@ extern ArrayObject*
NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
/* Create a dense array with the same copy-on-write elements as another object. */
-extern JSObject*
+extern ArrayObject*
NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
-// The methods below can create either boxed or unboxed arrays.
-
-extern JSObject*
+extern ArrayObject*
NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind = GenericObject);
-extern JSObject*
+extern ArrayObject*
NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
-extern JSObject*
+extern ArrayObject*
NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind = GenericObject);
-extern JSObject*
+extern ArrayObject*
NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
-extern JSObject*
+extern ArrayObject*
NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
NewObjectKind newKind = GenericObject);
-extern JSObject*
+extern ArrayObject*
NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
-enum class ShouldUpdateTypes
-{
- Update,
- DontUpdate
-};
-
-extern bool
-MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
- const Value* vp, size_t length);
-
-extern JSObject*
+extern ArrayObject*
NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length,
NewObjectKind newKind = GenericObject,
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
-extern JSObject*
+extern ArrayObject*
NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
HandleObject proto = nullptr);
@@ -129,13 +117,6 @@ NewValuePair(JSContext* cx, const Value& val1, const Value& val2, MutableHandleV
extern bool
WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
-/*
- * Canonicalize |vp| to a uint32_t value potentially suitable for use as an
- * array length.
- */
-extern bool
-CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* canonicalized);
-
extern bool
GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
@@ -172,7 +153,7 @@ extern bool
array_join(JSContext* cx, unsigned argc, js::Value* vp);
extern void
-ArrayShiftMoveElements(JSObject* obj);
+ArrayShiftMoveElements(NativeObject* obj);
extern bool
array_shift(JSContext* cx, unsigned argc, js::Value* vp);
@@ -202,7 +183,7 @@ array_splice(JSContext* cx, unsigned argc, js::Value* vp);
extern bool
NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
-extern JSObject*
+extern ArrayObject*
ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
#ifdef DEBUG
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index f5cd56a9b..1fd9d1d28 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -271,7 +271,7 @@ js::GetBuiltinClass(JSContext* cx, HandleObject obj, ESClass* cls)
if (obj->is<PlainObject>() || obj->is<UnboxedPlainObject>())
*cls = ESClass::Object;
- else if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>())
+ else if (obj->is<ArrayObject>())
*cls = ESClass::Array;
else if (obj->is<NumberObject>())
*cls = ESClass::Number;
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index f22ecb445..deaa1d53e 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -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>() || obj->is<UnboxedArrayObject>());
- 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;
}
@@ -1207,13 +1206,12 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
MOZ_ASSERT_IF(obj->isSingleton(),
cx->compartment()->behaviors().getSingletonsAsTemplates());
MOZ_ASSERT(obj->is<PlainObject>() ||
- obj->is<ArrayObject>() ||
- obj->is<UnboxedArrayObject>());
+ obj->is<ArrayObject>());
MOZ_ASSERT(newKind != SingletonObject);
- if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
+ 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.
@@ -1327,9 +1325,8 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
{
if (mode == XDR_ENCODE) {
MOZ_ASSERT(obj->is<PlainObject>() ||
- obj->is<ArrayObject>() ||
- obj->is<UnboxedArrayObject>());
- isArray = (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) ? 1 : 0;
+ obj->is<ArrayObject>());
+ isArray = obj->is<ArrayObject>() ? 1 : 0;
}
if (!xdr->codeUint32(&isArray))
@@ -1341,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)
@@ -2312,11 +2312,6 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
// us the resolve hook won't define a property with this id.
if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
return false;
- } else if (obj->is<UnboxedArrayObject>()) {
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- MarkNonNativePropertyFound<NoGC>(propp);
- return true;
- }
} else if (obj->is<TypedObject>()) {
if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
MarkNonNativePropertyFound<NoGC>(propp);
@@ -3680,16 +3675,6 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
if (IsProxy(this))
return as<ProxyObject>().allocKindForTenure();
- // Unboxed arrays use inline data if their size is small enough.
- if (is<UnboxedArrayObject>()) {
- const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
- size_t nbytes = UnboxedArrayObject::offsetOfInlineElements() +
- nobj->capacity() * nobj->elementSize();
- if (nbytes <= JSObject::MAX_BYTE_SIZE)
- return GetGCObjectKindForBytes(nbytes);
- return AllocKind::OBJECT0;
- }
-
// Inlined typed objects are followed by their data, so make sure we copy
// it all over to the new object.
if (is<InlineTypedObject>()) {
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index 6be4d0d28..26f9eacce 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -40,8 +40,6 @@ MaybeConvertUnboxedObjectToNative(ExclusiveContext* cx, JSObject* obj)
{
if (obj->is<UnboxedPlainObject>())
return UnboxedPlainObject::convertToNative(cx->asJSContext(), obj);
- if (obj->is<UnboxedArrayObject>())
- return UnboxedArrayObject::convertToNative(cx->asJSContext(), obj);
return true;
}
diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
index 7765b1197..d7db5129d 100644
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2369,7 +2369,7 @@ js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString patt
}
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
-static JSObject*
+static ArrayObject*
SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearString sep,
HandleObjectGroup group)
{
@@ -2466,7 +2466,7 @@ SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearS
}
// Fast-path for splitting a string into a character array via split("").
-static JSObject*
+static ArrayObject*
CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObjectGroup group)
{
size_t strLength = str->length();
@@ -2491,7 +2491,7 @@ CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObj
}
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
-JSObject*
+ArrayObject*
js::str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep, uint32_t limit)
{
diff --git a/js/src/jsstr.h b/js/src/jsstr.h
index 38fbfa85e..68175c826 100644
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -465,7 +465,7 @@ FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote)
return res;
}
-JSObject*
+ArrayObject*
str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep,
uint32_t limit);
diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
index 193d8d22b..29cbd9762 100644
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -320,7 +320,6 @@ static bool enableIon = false;
static bool enableAsmJS = false;
static bool enableWasm = false;
static bool enableNativeRegExp = false;
-static bool enableUnboxedArrays = false;
static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
static bool enableWasmAlwaysBaseline = false;
static bool enableArrayProtoValues = true;
@@ -7260,7 +7259,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
enableAsmJS = !op.getBoolOption("no-asmjs");
enableWasm = !op.getBoolOption("no-wasm");
enableNativeRegExp = !op.getBoolOption("no-native-regexp");
- enableUnboxedArrays = op.getBoolOption("unboxed-arrays");
enableWasmAlwaysBaseline = op.getBoolOption("wasm-always-baseline");
enableArrayProtoValues = !op.getBoolOption("no-array-proto-values");
@@ -7270,7 +7268,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
.setWasm(enableWasm)
.setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
.setNativeRegExp(enableNativeRegExp)
- .setUnboxedArrays(enableUnboxedArrays)
.setArrayProtoValues(enableArrayProtoValues);
if (op.getBoolOption("wasm-check-bce"))
@@ -7710,7 +7707,6 @@ main(int argc, char** argv, char** envp)
|| !op.addBoolOption('\0', "no-wasm", "Disable WebAssembly compilation")
|| !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
|| !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
- || !op.addBoolOption('\0', "unboxed-arrays", "Allow creating unboxed arrays")
|| !op.addBoolOption('\0', "wasm-always-baseline", "Enable wasm baseline compiler when possible")
|| !op.addBoolOption('\0', "wasm-check-bce", "Always generate wasm bounds check, even redundant ones.")
|| !op.addBoolOption('\0', "no-array-proto-values", "Remove Array.prototype.values")
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 710f1d89b..a2c8e220a 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -593,7 +593,7 @@ InitArrayElemOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t
JSOp op = JSOp(*pc);
MOZ_ASSERT(op == JSOP_INITELEM_ARRAY || op == JSOP_INITELEM_INC);
- MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+ MOZ_ASSERT(obj->is<ArrayObject>());
if (op == JSOP_INITELEM_INC && index == INT32_MAX) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SPREAD_TOO_LARGE);
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 3cf2deb83..74a1ef3e9 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1916,6 +1916,7 @@ CASE(EnableInterruptsPseudoOpcode)
/* Various 1-byte no-ops. */
CASE(JSOP_NOP)
CASE(JSOP_NOP_DESTRUCTURING)
+CASE(JSOP_UNUSED126)
CASE(JSOP_UNUSED192)
CASE(JSOP_UNUSED209)
CASE(JSOP_UNUSED210)
@@ -3636,7 +3637,6 @@ CASE(JSOP_NEWINIT)
END_CASE(JSOP_NEWINIT)
CASE(JSOP_NEWARRAY)
-CASE(JSOP_SPREADCALLARRAY)
{
uint32_t length = GET_UINT32(REGS.pc);
JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length);
@@ -4933,7 +4933,7 @@ js::NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
newKind = TenuredObject;
}
- RootedObject obj(cx);
+ RootedPlainObject obj(cx);
if (*pc == JSOP_NEWOBJECT) {
RootedPlainObject baseObject(cx, &script->getObject(pc)->as<PlainObject>());
@@ -5001,9 +5001,6 @@ js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32
if (group->shouldPreTenure() || group->maybePreliminaryObjects())
newKind = TenuredObject;
-
- if (group->maybeUnboxedLayout())
- return UnboxedArrayObject::create(cx, group, length, newKind);
}
ArrayObject* obj = NewDenseFullyAllocatedArray(cx, length, nullptr, newKind);
@@ -5014,9 +5011,6 @@ js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32
MOZ_ASSERT(obj->isSingleton());
} else {
obj->setGroup(group);
-
- if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
- preliminaryObjects->registerNewObject(obj);
}
return obj;
@@ -5029,12 +5023,6 @@ js::NewArrayOperationWithTemplate(JSContext* cx, HandleObject templateObject)
NewObjectKind newKind = templateObject->group()->shouldPreTenure() ? TenuredObject : GenericObject;
- if (templateObject->is<UnboxedArrayObject>()) {
- uint32_t length = templateObject->as<UnboxedArrayObject>().length();
- RootedObjectGroup group(cx, templateObject->group());
- return UnboxedArrayObject::create(cx, group, length, newKind);
- }
-
ArrayObject* obj = NewDenseFullyAllocatedArray(cx, templateObject->as<ArrayObject>().length(),
nullptr, newKind);
if (!obj)
diff --git a/js/src/vm/JSONParser.cpp b/js/src/vm/JSONParser.cpp
index 01883bb15..e50da3bc4 100644
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -606,8 +606,8 @@ JSONParserBase::finishArray(MutableHandleValue vp, ElementVector& elements)
{
MOZ_ASSERT(&elements == &stack.back().elements());
- JSObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
- GenericObject);
+ ArrayObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
+ GenericObject);
if (!obj)
return false;
diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h
index 48a42a8db..052a3385c 100644
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -235,6 +235,38 @@ NativeObject::ensureDenseElements(ExclusiveContext* cx, uint32_t index, uint32_t
return DenseElementResult::Success;
}
+inline DenseElementResult
+NativeObject::setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp,
+ uint32_t count,
+ ShouldUpdateTypes updateTypes)
+{
+ if (denseElementsAreFrozen())
+ return DenseElementResult::Incomplete;
+
+ if (is<ArrayObject>() &&
+ !as<ArrayObject>().lengthIsWritable() &&
+ start + count >= as<ArrayObject>().length())
+ {
+ return DenseElementResult::Incomplete;
+ }
+
+ DenseElementResult result = ensureDenseElements(cx, start, count);
+ if (result != DenseElementResult::Success)
+ return result;
+
+ if (is<ArrayObject>() && start + count >= as<ArrayObject>().length())
+ as<ArrayObject>().setLengthInt32(start + count);
+
+ if (updateTypes == ShouldUpdateTypes::DontUpdate && !shouldConvertDoubleElements()) {
+ copyDenseElements(start, vp, count);
+ } else {
+ for (size_t i = 0; i < count; i++)
+ setDenseElementWithType(cx, start + i, vp[i]);
+ }
+
+ return DenseElementResult::Success;
+}
+
inline Value
NativeObject::getDenseOrTypedArrayElement(uint32_t idx)
{
diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 4dbc167ab..da4f873a6 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -339,16 +339,19 @@ IsObjectValueInCompartment(const Value& v, JSCompartment* comp);
#endif
// Operations which change an object's dense elements can either succeed, fail,
-// or be unable to complete. For native objects, the latter is used when the
-// object's elements must become sparse instead. The enum below is used for
-// such operations, and for similar operations on unboxed arrays and methods
-// that work on both kinds of objects.
+// or be unable to complete. The latter is used when the object's elements must
+// become sparse instead. The enum below is used for such operations.
enum class DenseElementResult {
Failure,
Success,
Incomplete
};
+enum class ShouldUpdateTypes {
+ Update,
+ DontUpdate
+};
+
/*
* NativeObject specifies the internal implementation of a native object.
*
@@ -1147,6 +1150,10 @@ class NativeObject : public ShapedObject
elementsRangeWriteBarrierPost(dstStart, count);
}
+ inline DenseElementResult
+ setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp, uint32_t count,
+ ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
+
bool shouldConvertDoubleElements() {
return getElementsHeader()->shouldConvertDoubleElements();
}
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index 46159a972..63ac33eea 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -774,7 +774,7 @@ GetValueTypeForTable(const Value& v)
return type;
}
-/* static */ JSObject*
+/* static */ ArrayObject*
ObjectGroup::newArrayObject(ExclusiveContext* cx,
const Value* vp, size_t length,
NewObjectKind newKind, NewArrayKind arrayKind)
@@ -838,56 +838,13 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType);
- if (elementType != TypeSet::UnknownType()) {
- // Keep track of the initial objects we create with this type.
- // If the initial ones have a consistent shape and property types, we
- // will try to use an unboxed layout for the group.
- PreliminaryObjectArrayWithTemplate* preliminaryObjects =
- cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
- if (!preliminaryObjects)
- return nullptr;
- group->setPreliminaryObjects(preliminaryObjects);
- }
-
if (!p.add(cx, *table, ObjectGroupCompartment::ArrayObjectKey(elementType), group))
return nullptr;
}
// The type of the elements being added will already be reflected in type
- // information, but make sure when creating an unboxed array that the
- // common element type is suitable for the unboxed representation.
+ // information.
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate;
- if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
- return nullptr;
- if (group->maybePreliminaryObjects())
- group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
- if (group->maybeUnboxedLayout()) {
- switch (group->unboxedLayout().elementType()) {
- case JSVAL_TYPE_BOOLEAN:
- if (elementType != TypeSet::BooleanType())
- updateTypes = ShouldUpdateTypes::Update;
- break;
- case JSVAL_TYPE_INT32:
- if (elementType != TypeSet::Int32Type())
- updateTypes = ShouldUpdateTypes::Update;
- break;
- case JSVAL_TYPE_DOUBLE:
- if (elementType != TypeSet::Int32Type() && elementType != TypeSet::DoubleType())
- updateTypes = ShouldUpdateTypes::Update;
- break;
- case JSVAL_TYPE_STRING:
- if (elementType != TypeSet::StringType())
- updateTypes = ShouldUpdateTypes::Update;
- break;
- case JSVAL_TYPE_OBJECT:
- if (elementType != TypeSet::NullType() && !elementType.get().isObjectUnchecked())
- updateTypes = ShouldUpdateTypes::Update;
- break;
- default:
- MOZ_CRASH();
- }
- }
-
return NewCopiedArrayTryUseGroup(cx, group, vp, length, newKind, updateTypes);
}
@@ -897,49 +854,15 @@ GiveObjectGroup(ExclusiveContext* cx, JSObject* source, JSObject* target)
{
MOZ_ASSERT(source->group() != target->group());
- if (!target->is<ArrayObject>() && !target->is<UnboxedArrayObject>())
+ if (!target->is<ArrayObject>() || !source->is<ArrayObject>()) {
return true;
-
- if (target->group()->maybePreliminaryObjects()) {
- bool force = IsInsideNursery(source);
- target->group()->maybePreliminaryObjects()->maybeAnalyze(cx, target->group(), force);
}
- if (target->is<ArrayObject>()) {
- ObjectGroup* sourceGroup = source->group();
+ source->setGroup(target->group());
- if (source->is<UnboxedArrayObject>()) {
- Shape* shape = target->as<ArrayObject>().lastProperty();
- if (!UnboxedArrayObject::convertToNativeWithGroup(cx, source, target->group(), shape))
- return false;
- } else if (source->is<ArrayObject>()) {
- source->setGroup(target->group());
- } else {
- return true;
- }
-
- if (sourceGroup->maybePreliminaryObjects())
- sourceGroup->maybePreliminaryObjects()->unregisterObject(source);
- if (target->group()->maybePreliminaryObjects())
- target->group()->maybePreliminaryObjects()->registerNewObject(source);
-
- for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
- Value v = source->as<ArrayObject>().getDenseElement(i);
- AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
- }
-
- return true;
- }
-
- if (target->is<UnboxedArrayObject>()) {
- if (!source->is<UnboxedArrayObject>())
- return true;
- if (source->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_INT32)
- return true;
- if (target->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_DOUBLE)
- return true;
-
- return source->as<UnboxedArrayObject>().convertInt32ToDouble(cx, target->group());
+ for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
+ Value v = source->as<ArrayObject>().getDenseElement(i);
+ AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
}
return true;
@@ -1503,18 +1426,6 @@ ObjectGroup::allocationSiteGroup(JSContext* cx, JSScript* scriptArg, jsbytecode*
}
}
- if (kind == JSProto_Array &&
- (JSOp(*pc) == JSOP_NEWARRAY || IsCallPC(pc)) &&
- cx->options().unboxedArrays())
- {
- PreliminaryObjectArrayWithTemplate* preliminaryObjects =
- cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
- if (preliminaryObjects)
- res->setPreliminaryObjects(preliminaryObjects);
- else
- cx->recoverFromOutOfMemory();
- }
-
if (!table->add(p, key, res)) {
ReportOutOfMemory(cx);
return nullptr;
diff --git a/js/src/vm/ObjectGroup.h b/js/src/vm/ObjectGroup.h
index 4e24de9f1..553cb8366 100644
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -505,11 +505,11 @@ class ObjectGroup : public gc::TenuredCell
UnknownIndex // Make an array with an unknown element type.
};
- // Create an ArrayObject or UnboxedArrayObject with the specified elements
- // and a group specialized for the elements.
- static JSObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
- NewObjectKind newKind,
- NewArrayKind arrayKind = NewArrayKind::Normal);
+ // Create an ArrayObject with the specified elements and a group specialized
+ // for the elements.
+ static ArrayObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
+ NewObjectKind newKind,
+ NewArrayKind arrayKind = NewArrayKind::Normal);
// Create a PlainObject or UnboxedPlainObject with the specified properties
// and a group specialized for those properties.
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index 4b044c8d8..095ef57ae 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1281,17 +1281,7 @@
* Stack: receiver, obj, propval => obj[propval]
*/ \
macro(JSOP_GETELEM_SUPER, 125, "getelem-super", NULL, 1, 3, 1, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC) \
- /*
- * Pushes newly created array for a spread call onto the stack. This has
- * the same semantics as JSOP_NEWARRAY, but is distinguished to avoid
- * using unboxed arrays in spread calls, which would make compiling spread
- * calls in baseline more complex.
- * Category: Literals
- * Type: Array
- * Operands: uint32_t length
- * Stack: => obj
- */ \
- macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 5, 0, 1, JOF_UINT32) \
+ macro(JSOP_UNUSED126, 126, "unused126", NULL, 5, 0, 1, JOF_UINT32) \
\
/*
* Defines the given function on the current scope.
diff --git a/js/src/vm/ReceiverGuard.cpp b/js/src/vm/ReceiverGuard.cpp
index 11c2d0727..e37bf8ee5 100644
--- a/js/src/vm/ReceiverGuard.cpp
+++ b/js/src/vm/ReceiverGuard.cpp
@@ -19,7 +19,7 @@ ReceiverGuard::ReceiverGuard(JSObject* obj)
group = obj->group();
if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
shape = expando->lastProperty();
- } else if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
+ } else if (obj->is<TypedObject>()) {
group = obj->group();
} else {
shape = obj->maybeShape();
@@ -34,7 +34,7 @@ ReceiverGuard::ReceiverGuard(ObjectGroup* group, Shape* shape)
const Class* clasp = group->clasp();
if (clasp == &UnboxedPlainObject::class_) {
// Keep both group and shape.
- } else if (clasp == &UnboxedArrayObject::class_ || IsTypedObjectClass(clasp)) {
+ } else if (IsTypedObjectClass(clasp)) {
this->shape = nullptr;
} else {
this->group = nullptr;
@@ -49,8 +49,8 @@ HeapReceiverGuard::keyBits(JSObject* obj)
// Both the group and shape need to be guarded for unboxed plain objects.
return obj->as<UnboxedPlainObject>().maybeExpando() ? 0 : 1;
}
- if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
- // Only the group needs to be guarded for unboxed arrays and typed objects.
+ if (obj->is<TypedObject>()) {
+ // Only the group needs to be guarded for typed objects.
return 2;
}
// Other objects only need the shape to be guarded.
diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp
index 87e95c893..c5f2cf5f3 100644
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -82,7 +82,7 @@ InterpreterFrame::isNonGlobalEvalFrame() const
return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
}
-JSObject*
+ArrayObject*
InterpreterFrame::createRestParameter(JSContext* cx)
{
MOZ_ASSERT(script()->hasRest());
diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h
index 552738d89..dc9306c99 100644
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -523,7 +523,7 @@ class InterpreterFrame
ArgumentsObject& argsObj() const;
void initArgsObj(ArgumentsObject& argsobj);
- JSObject* createRestParameter(JSContext* cx);
+ ArrayObject* createRestParameter(JSContext* cx);
/*
* Environment chain
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 9e0342382..0551e2c58 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -2505,7 +2505,7 @@ TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList* constraints, jsid
bool
js::ClassCanHaveExtraProperties(const Class* clasp)
{
- if (clasp == &UnboxedPlainObject::class_ || clasp == &UnboxedArrayObject::class_)
+ if (clasp == &UnboxedPlainObject::class_)
return false;
return clasp->getResolve()
|| clasp->getOpsLookupProperty()
@@ -3393,7 +3393,7 @@ JSFunction::setTypeForScriptedFunction(ExclusiveContext* cx, HandleFunction fun,
/////////////////////////////////////////////////////////////////////
void
-PreliminaryObjectArray::registerNewObject(JSObject* res)
+PreliminaryObjectArray::registerNewObject(PlainObject* res)
{
// The preliminary object pointers are weak, and won't be swept properly
// during nursery collections, so the preliminary objects need to be
@@ -3411,7 +3411,7 @@ PreliminaryObjectArray::registerNewObject(JSObject* res)
}
void
-PreliminaryObjectArray::unregisterObject(JSObject* obj)
+PreliminaryObjectArray::unregisterObject(PlainObject* obj)
{
for (size_t i = 0; i < COUNT; i++) {
if (objects[i] == obj) {
diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
index 04fed448c..94ce7e871 100644
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -814,8 +814,8 @@ class PreliminaryObjectArray
public:
PreliminaryObjectArray() = default;
- void registerNewObject(JSObject* res);
- void unregisterObject(JSObject* obj);
+ void registerNewObject(PlainObject* res);
+ void unregisterObject(PlainObject* obj);
JSObject* get(size_t i) const {
MOZ_ASSERT(i < COUNT);
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 93ad7bf28..c1468a5b1 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -172,669 +172,6 @@ UnboxedPlainObject::layout() const
return group()->unboxedLayout();
}
-/////////////////////////////////////////////////////////////////////
-// UnboxedArrayObject
-/////////////////////////////////////////////////////////////////////
-
-inline const UnboxedLayout&
-UnboxedArrayObject::layout() const
-{
- return group()->unboxedLayout();
-}
-
-inline void
-UnboxedArrayObject::setLength(ExclusiveContext* cx, uint32_t length)
-{
- if (length > INT32_MAX) {
- // Track objects with overflowing lengths in type information.
- MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
- }
-
- length_ = length;
-}
-
-inline void
-UnboxedArrayObject::setInitializedLength(uint32_t initlen)
-{
- if (initlen < initializedLength()) {
- switch (elementType()) {
- case JSVAL_TYPE_STRING:
- for (size_t i = initlen; i < initializedLength(); i++)
- triggerPreBarrier<JSVAL_TYPE_STRING>(i);
- break;
- case JSVAL_TYPE_OBJECT:
- for (size_t i = initlen; i < initializedLength(); i++)
- triggerPreBarrier<JSVAL_TYPE_OBJECT>(i);
- break;
- default:
- MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(elementType()));
- }
- }
- setInitializedLengthNoBarrier(initlen);
-}
-
-template <JSValueType Type>
-inline bool
-UnboxedArrayObject::setElementSpecific(ExclusiveContext* cx, size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- MOZ_ASSERT(Type == elementType());
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
- return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ true);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::setElementNoTypeChangeSpecific(size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- MOZ_ASSERT(Type == elementType());
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
- return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ true);
-}
-
-template <JSValueType Type>
-inline bool
-UnboxedArrayObject::initElementSpecific(ExclusiveContext* cx, size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- MOZ_ASSERT(Type == elementType());
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
- return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ false);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::initElementNoTypeChangeSpecific(size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- MOZ_ASSERT(Type == elementType());
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
- return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ false);
-}
-
-template <JSValueType Type>
-inline Value
-UnboxedArrayObject::getElementSpecific(size_t index)
-{
- MOZ_ASSERT(index < initializedLength());
- MOZ_ASSERT(Type == elementType());
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
- return GetUnboxedValue(p, Type, /* maybeUninitialized = */ false);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::triggerPreBarrier(size_t index)
-{
- MOZ_ASSERT(UnboxedTypeNeedsPreBarrier(Type));
-
- uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-
- switch (Type) {
- case JSVAL_TYPE_STRING: {
- JSString** np = reinterpret_cast<JSString**>(p);
- JSString::writeBarrierPre(*np);
- break;
- }
-
- case JSVAL_TYPE_OBJECT: {
- JSObject** np = reinterpret_cast<JSObject**>(p);
- JSObject::writeBarrierPre(*np);
- break;
- }
-
- default:
- MOZ_CRASH("Bad type");
- }
-}
-
-/////////////////////////////////////////////////////////////////////
-// Combined methods for NativeObject and UnboxedArrayObject accesses.
-/////////////////////////////////////////////////////////////////////
-
-static inline bool
-HasAnyBoxedOrUnboxedDenseElements(JSObject* obj)
-{
- return obj->isNative() || obj->is<UnboxedArrayObject>();
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedInitializedLength(JSObject* obj)
-{
- if (obj->isNative())
- return obj->as<NativeObject>().getDenseInitializedLength();
- if (obj->is<UnboxedArrayObject>())
- return obj->as<UnboxedArrayObject>().initializedLength();
- return 0;
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedCapacity(JSObject* obj)
-{
- if (obj->isNative())
- return obj->as<NativeObject>().getDenseCapacity();
- if (obj->is<UnboxedArrayObject>())
- return obj->as<UnboxedArrayObject>().capacity();
- return 0;
-}
-
-static inline Value
-GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
-{
- if (obj->isNative())
- return obj->as<NativeObject>().getDenseElement(index);
- return obj->as<UnboxedArrayObject>().getElement(index);
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedArrayLength(JSObject* obj)
-{
- if (obj->is<ArrayObject>())
- return obj->as<ArrayObject>().length();
- return obj->as<UnboxedArrayObject>().length();
-}
-
-static inline void
-SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length)
-{
- if (obj->is<ArrayObject>()) {
- MOZ_ASSERT(length >= obj->as<ArrayObject>().length());
- obj->as<ArrayObject>().setLength(cx, length);
- } else {
- MOZ_ASSERT(length >= obj->as<UnboxedArrayObject>().length());
- obj->as<UnboxedArrayObject>().setLength(cx, length);
- }
-}
-
-static inline bool
-SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
- if (obj->isNative()) {
- obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
- return true;
- }
- return obj->as<UnboxedArrayObject>().setElement(cx, index, value);
-}
-
-static inline bool
-InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
- if (obj->isNative()) {
- obj->as<NativeObject>().initDenseElementWithType(cx, index, value);
- return true;
- }
- return obj->as<UnboxedArrayObject>().initElement(cx, index, value);
-}
-
-/////////////////////////////////////////////////////////////////////
-// Template methods for NativeObject and UnboxedArrayObject accesses.
-/////////////////////////////////////////////////////////////////////
-
-static inline JSValueType
-GetBoxedOrUnboxedType(JSObject* obj)
-{
- if (obj->isNative())
- return JSVAL_TYPE_MAGIC;
- return obj->as<UnboxedArrayObject>().elementType();
-}
-
-template <JSValueType Type>
-static inline bool
-HasBoxedOrUnboxedDenseElements(JSObject* obj)
-{
- if (Type == JSVAL_TYPE_MAGIC)
- return obj->isNative();
- return obj->is<UnboxedArrayObject>() && obj->as<UnboxedArrayObject>().elementType() == Type;
-}
-
-template <JSValueType Type>
-static inline size_t
-GetBoxedOrUnboxedInitializedLength(JSObject* obj)
-{
- if (Type == JSVAL_TYPE_MAGIC)
- return obj->as<NativeObject>().getDenseInitializedLength();
- return obj->as<UnboxedArrayObject>().initializedLength();
-}
-
-template <JSValueType Type>
-static inline DenseElementResult
-SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
-{
- size_t oldInitlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
- if (Type == JSVAL_TYPE_MAGIC) {
- obj->as<NativeObject>().setDenseInitializedLength(initlen);
- if (initlen < oldInitlen)
- obj->as<NativeObject>().shrinkElements(cx, initlen);
- } else {
- obj->as<UnboxedArrayObject>().setInitializedLength(initlen);
- if (initlen < oldInitlen)
- obj->as<UnboxedArrayObject>().shrinkElements(cx, initlen);
- }
- return DenseElementResult::Success;
-}
-
-template <JSValueType Type>
-static inline size_t
-GetBoxedOrUnboxedCapacity(JSObject* obj)
-{
- if (Type == JSVAL_TYPE_MAGIC)
- return obj->as<NativeObject>().getDenseCapacity();
- return obj->as<UnboxedArrayObject>().capacity();
-}
-
-template <JSValueType Type>
-static inline Value
-GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
-{
- if (Type == JSVAL_TYPE_MAGIC)
- return obj->as<NativeObject>().getDenseElement(index);
- return obj->as<UnboxedArrayObject>().getElementSpecific<Type>(index);
-}
-
-template <JSValueType Type>
-static inline void
-SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value)
-{
- if (Type == JSVAL_TYPE_MAGIC)
- obj->as<NativeObject>().setDenseElement(index, value);
- else
- obj->as<UnboxedArrayObject>().setElementNoTypeChangeSpecific<Type>(index, value);
-}
-
-template <JSValueType Type>
-static inline bool
-SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
- if (Type == JSVAL_TYPE_MAGIC) {
- obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
- return true;
- }
- return obj->as<UnboxedArrayObject>().setElementSpecific<Type>(cx, index, value);
-}
-
-template <JSValueType Type>
-static inline DenseElementResult
-EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count)
-{
- if (Type == JSVAL_TYPE_MAGIC) {
- if (!obj->as<ArrayObject>().ensureElements(cx, count))
- return DenseElementResult::Failure;
- } else {
- if (obj->as<UnboxedArrayObject>().capacity() < count) {
- if (!obj->as<UnboxedArrayObject>().growElements(cx, count))
- return DenseElementResult::Failure;
- }
- }
- return DenseElementResult::Success;
-}
-
-template <JSValueType Type>
-static inline DenseElementResult
-SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
- uint32_t start, const Value* vp, uint32_t count,
- ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update)
-{
- if (Type == JSVAL_TYPE_MAGIC) {
- NativeObject* nobj = &obj->as<NativeObject>();
-
- if (nobj->denseElementsAreFrozen())
- return DenseElementResult::Incomplete;
-
- if (obj->is<ArrayObject>() &&
- !obj->as<ArrayObject>().lengthIsWritable() &&
- start + count >= obj->as<ArrayObject>().length())
- {
- return DenseElementResult::Incomplete;
- }
-
- DenseElementResult result = nobj->ensureDenseElements(cx, start, count);
- if (result != DenseElementResult::Success)
- return result;
-
- if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length())
- obj->as<ArrayObject>().setLengthInt32(start + count);
-
- if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) {
- nobj->copyDenseElements(start, vp, count);
- } else {
- for (size_t i = 0; i < count; i++)
- nobj->setDenseElementWithType(cx, start + i, vp[i]);
- }
-
- return DenseElementResult::Success;
- }
-
- UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
-
- if (start > nobj->initializedLength())
- return DenseElementResult::Incomplete;
-
- if (start + count >= UnboxedArrayObject::MaximumCapacity)
- return DenseElementResult::Incomplete;
-
- if (start + count > nobj->capacity() && !nobj->growElements(cx, start + count))
- return DenseElementResult::Failure;
-
- size_t oldInitlen = nobj->initializedLength();
-
- // Overwrite any existing elements covered by the new range. If we fail
- // after this point due to some incompatible type being written to the
- // object's elements, afterwards the contents will be different from when
- // we started. The caller must retry the operation using a generic path,
- // which will overwrite the already-modified elements as well as the ones
- // that were left alone.
- size_t i = 0;
- if (updateTypes == ShouldUpdateTypes::DontUpdate) {
- for (size_t j = start; i < count && j < oldInitlen; i++, j++)
- nobj->setElementNoTypeChangeSpecific<Type>(j, vp[i]);
- } else {
- for (size_t j = start; i < count && j < oldInitlen; i++, j++) {
- if (!nobj->setElementSpecific<Type>(cx, j, vp[i]))
- return DenseElementResult::Incomplete;
- }
- }
-
- if (i != count) {
- obj->as<UnboxedArrayObject>().setInitializedLength(start + count);
- if (updateTypes == ShouldUpdateTypes::DontUpdate) {
- for (; i < count; i++)
- nobj->initElementNoTypeChangeSpecific<Type>(start + i, vp[i]);
- } else {
- for (; i < count; i++) {
- if (!nobj->initElementSpecific<Type>(cx, start + i, vp[i])) {
- nobj->setInitializedLengthNoBarrier(oldInitlen);
- return DenseElementResult::Incomplete;
- }
- }
- }
- }
-
- if (start + count >= nobj->length())
- nobj->setLength(cx, start + count);
-
- return DenseElementResult::Success;
-}
-
-template <JSValueType Type>
-static inline DenseElementResult
-MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart,
- uint32_t length)
-{
- MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj));
-
- if (Type == JSVAL_TYPE_MAGIC) {
- if (obj->as<NativeObject>().denseElementsAreFrozen())
- return DenseElementResult::Incomplete;
-
- if (!obj->as<NativeObject>().maybeCopyElementsForWrite(cx))
- return DenseElementResult::Failure;
- obj->as<NativeObject>().moveDenseElements(dstStart, srcStart, length);
- } else {
- uint8_t* data = obj->as<UnboxedArrayObject>().elements();
- size_t elementSize = UnboxedTypeSize(Type);
-
- if (UnboxedTypeNeedsPreBarrier(Type) &&
- JS::shadow::Zone::asShadowZone(obj->zone())->needsIncrementalBarrier())
- {
- // Trigger pre barriers on any elements we are overwriting. See
- // NativeObject::moveDenseElements. No post barrier is needed as
- // only whole cell post barriers are used with unboxed objects.
- for (size_t i = 0; i < length; i++)
- obj->as<UnboxedArrayObject>().triggerPreBarrier<Type>(dstStart + i);
- }
-
- memmove(data + dstStart * elementSize,
- data + srcStart * elementSize,
- length * elementSize);
- }
-
- return DenseElementResult::Success;
-}
-
-template <JSValueType DstType, JSValueType SrcType>
-static inline DenseElementResult
-CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
- uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
- MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<SrcType>(src));
- MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<DstType>(dst));
- MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<DstType>(dst) == dstStart);
- MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<SrcType>(src) >= srcStart + length);
- MOZ_ASSERT(GetBoxedOrUnboxedCapacity<DstType>(dst) >= dstStart + length);
-
- SetBoxedOrUnboxedInitializedLength<DstType>(cx, dst, dstStart + length);
-
- if (DstType == JSVAL_TYPE_MAGIC) {
- if (SrcType == JSVAL_TYPE_MAGIC) {
- const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
- dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
- } else {
- for (size_t i = 0; i < length; i++) {
- Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
- dst->as<NativeObject>().initDenseElement(dstStart + i, v);
- }
- }
- } else if (DstType == SrcType) {
- uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
- uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
- size_t elementSize = UnboxedTypeSize(DstType);
-
- memcpy(dstData + dstStart * elementSize,
- srcData + srcStart * elementSize,
- length * elementSize);
-
- // Add a store buffer entry if we might have copied a nursery pointer to dst.
- if (UnboxedTypeNeedsPostBarrier(DstType) && !IsInsideNursery(dst))
- dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCell(dst);
- } else if (DstType == JSVAL_TYPE_DOUBLE && SrcType == JSVAL_TYPE_INT32) {
- uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
- uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
-
- for (size_t i = 0; i < length; i++) {
- int32_t v = *reinterpret_cast<int32_t*>(srcData + (srcStart + i) * sizeof(int32_t));
- *reinterpret_cast<double*>(dstData + (dstStart + i) * sizeof(double)) = v;
- }
- } else {
- for (size_t i = 0; i < length; i++) {
- Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
- dst->as<UnboxedArrayObject>().initElementNoTypeChangeSpecific<DstType>(dstStart + i, v);
- }
- }
-
- return DenseElementResult::Success;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Dispatch to specialized methods based on the type of an object.
-/////////////////////////////////////////////////////////////////////
-
-// Goop to fix MSVC. See DispatchTraceKindTyped in TraceKind.h.
-// The clang-cl front end defines _MSC_VER, but still requires the explicit
-// template declaration, so we must test for __clang__ here as well.
-#if defined(_MSC_VER) && !defined(__clang__)
-# define DEPENDENT_TEMPLATE_HINT
-#else
-# define DEPENDENT_TEMPLATE_HINT template
-#endif
-
-// Function to dispatch a method specialized to whatever boxed or unboxed dense
-// elements which an input object has.
-template <typename F>
-DenseElementResult
-CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
-{
- if (!HasAnyBoxedOrUnboxedDenseElements(obj))
- return DenseElementResult::Incomplete;
- switch (GetBoxedOrUnboxedType(obj)) {
- case JSVAL_TYPE_MAGIC:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
- case JSVAL_TYPE_BOOLEAN:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_BOOLEAN>();
- case JSVAL_TYPE_INT32:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_INT32>();
- case JSVAL_TYPE_DOUBLE:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_DOUBLE>();
- case JSVAL_TYPE_STRING:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_STRING>();
- case JSVAL_TYPE_OBJECT:
- return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_OBJECT>();
- default:
- MOZ_CRASH();
- }
-}
-
-// As above, except the specialization can reflect the unboxed type of two objects.
-template <typename F>
-DenseElementResult
-CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2)
-{
- if (!HasAnyBoxedOrUnboxedDenseElements(obj1) || !HasAnyBoxedOrUnboxedDenseElements(obj2))
- return DenseElementResult::Incomplete;
-
-#define SPECIALIZE_OBJ2(TYPE) \
- switch (GetBoxedOrUnboxedType(obj2)) { \
- case JSVAL_TYPE_MAGIC: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_MAGIC>(); \
- case JSVAL_TYPE_BOOLEAN: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_BOOLEAN>(); \
- case JSVAL_TYPE_INT32: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_INT32>(); \
- case JSVAL_TYPE_DOUBLE: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_DOUBLE>(); \
- case JSVAL_TYPE_STRING: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_STRING>(); \
- case JSVAL_TYPE_OBJECT: \
- return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_OBJECT>(); \
- default: \
- MOZ_CRASH(); \
- }
-
- switch (GetBoxedOrUnboxedType(obj1)) {
- case JSVAL_TYPE_MAGIC:
- SPECIALIZE_OBJ2(JSVAL_TYPE_MAGIC)
- case JSVAL_TYPE_BOOLEAN:
- SPECIALIZE_OBJ2(JSVAL_TYPE_BOOLEAN)
- case JSVAL_TYPE_INT32:
- SPECIALIZE_OBJ2(JSVAL_TYPE_INT32)
- case JSVAL_TYPE_DOUBLE:
- SPECIALIZE_OBJ2(JSVAL_TYPE_DOUBLE)
- case JSVAL_TYPE_STRING:
- SPECIALIZE_OBJ2(JSVAL_TYPE_STRING)
- case JSVAL_TYPE_OBJECT:
- SPECIALIZE_OBJ2(JSVAL_TYPE_OBJECT)
- default:
- MOZ_CRASH();
- }
-
-#undef SPECIALIZE_OBJ2
-}
-
-#undef DEPENDENT_TEMPLATE_HINT
-
-#define DefineBoxedOrUnboxedFunctor1(Signature, A) \
-struct Signature ## Functor { \
- A a; \
- explicit Signature ## Functor(A a) \
- : a(a) \
- {} \
- template <JSValueType Type> \
- DenseElementResult operator()() { \
- return Signature<Type>(a); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctor3(Signature, A, B, C) \
-struct Signature ## Functor { \
- A a; B b; C c; \
- Signature ## Functor(A a, B b, C c) \
- : a(a), b(b), c(c) \
- {} \
- template <JSValueType Type> \
- DenseElementResult operator()() { \
- return Signature<Type>(a, b, c); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctor4(Signature, A, B, C, D) \
-struct Signature ## Functor { \
- A a; B b; C c; D d; \
- Signature ## Functor(A a, B b, C c, D d) \
- : a(a), b(b), c(c), d(d) \
- {} \
- template <JSValueType Type> \
- DenseElementResult operator()() { \
- return Signature<Type>(a, b, c, d); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctorPair4(Signature, A, B, C, D) \
-struct Signature ## Functor { \
- A a; B b; C c; D d; \
- Signature ## Functor(A a, B b, C c, D d) \
- : a(a), b(b), c(c), d(d) \
- {} \
- template <JSValueType TypeOne, JSValueType TypeTwo> \
- DenseElementResult operator()() { \
- return Signature<TypeOne, TypeTwo>(a, b, c, d); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctor5(Signature, A, B, C, D, E) \
-struct Signature ## Functor { \
- A a; B b; C c; D d; E e; \
- Signature ## Functor(A a, B b, C c, D d, E e) \
- : a(a), b(b), c(c), d(d), e(e) \
- {} \
- template <JSValueType Type> \
- DenseElementResult operator()() { \
- return Signature<Type>(a, b, c, d, e); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctor6(Signature, A, B, C, D, E, F) \
-struct Signature ## Functor { \
- A a; B b; C c; D d; E e; F f; \
- Signature ## Functor(A a, B b, C c, D d, E e, F f) \
- : a(a), b(b), c(c), d(d), e(e), f(f) \
- {} \
- template <JSValueType Type> \
- DenseElementResult operator()() { \
- return Signature<Type>(a, b, c, d, e, f); \
- } \
-}
-
-#define DefineBoxedOrUnboxedFunctorPair6(Signature, A, B, C, D, E, F) \
-struct Signature ## Functor { \
- A a; B b; C c; D d; E e; F f; \
- Signature ## Functor(A a, B b, C c, D d, E e, F f) \
- : a(a), b(b), c(c), d(d), e(e), f(f) \
- {} \
- template <JSValueType TypeOne, JSValueType TypeTwo> \
- DenseElementResult operator()() { \
- return Signature<TypeOne, TypeTwo>(a, b, c, d, e, f); \
- } \
-}
-
-DenseElementResult
-SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
- uint32_t start, const Value* vp, uint32_t count,
- ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
-
-DenseElementResult
-MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
- uint32_t dstStart, uint32_t srcStart, uint32_t length);
-
-DenseElementResult
-CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
- uint32_t dstStart, uint32_t srcStart, uint32_t length);
-
-void
-SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen);
-
-DenseElementResult
-EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count);
-
} // namespace js
#endif // vm_UnboxedObject_inl_h
diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp
index d7ad91de4..806a9db81 100644
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -417,8 +417,6 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
RootedObjectGroup replacementGroup(cx);
- const Class* clasp = layout.isArray() ? &ArrayObject::class_ : &PlainObject::class_;
-
// Immediately clear any new script on the group. This is done by replacing
// the existing new script with one for a replacement default new group.
// This is done so that the size of the replacment group's objects is the
@@ -426,8 +424,6 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
// slot accesses later on for sites that see converted objects from this
// group and objects that were allocated using the replacement new group.
if (layout.newScript()) {
- MOZ_ASSERT(!layout.isArray());
-
replacementGroup = ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto);
if (!replacementGroup)
return false;
@@ -453,15 +449,14 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
RootedScript script(cx, layout.allocationScript());
jsbytecode* pc = layout.allocationPc();
- replacementGroup = ObjectGroupCompartment::makeGroup(cx, clasp, proto);
+ replacementGroup = ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto);
if (!replacementGroup)
return false;
PlainObject* templateObject = &script->getObject(pc)->as<PlainObject>();
replacementGroup->addDefiniteProperties(cx, templateObject->lastProperty());
- JSProtoKey key = layout.isArray() ? JSProto_Array : JSProto_Object;
- cx->compartment()->objectGroups.replaceAllocationSiteGroup(script, pc, key,
+ cx->compartment()->objectGroups.replaceAllocationSiteGroup(script, pc, JSProto_Object,
replacementGroup);
// Clear any baseline information at this opcode which might use the old group.
@@ -477,22 +472,12 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
}
}
- size_t nfixed = layout.isArray() ? 0 : gc::GetGCKindSlots(layout.getAllocKind());
-
- if (layout.isArray()) {
- // The length shape to use for arrays is cached via a modified initial
- // shape for array objects. Create an array now to make sure this entry
- // is instantiated.
- if (!NewDenseEmptyArray(cx))
- return false;
- }
+ size_t nfixed = gc::GetGCKindSlots(layout.getAllocKind());
- RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, proto, nfixed, 0));
+ RootedShape shape(cx, EmptyShape::getInitialShape(cx, &PlainObject::class_, proto, nfixed, 0));
if (!shape)
return false;
- MOZ_ASSERT_IF(layout.isArray(), !shape->isEmptyShape() && shape->slotSpan() == 0);
-
// Add shapes for each property, if this is for a plain object.
for (size_t i = 0; i < layout.properties().length(); i++) {
const UnboxedLayout::Property& property = layout.properties()[i];
@@ -505,7 +490,7 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
}
ObjectGroup* nativeGroup =
- ObjectGroupCompartment::makeGroup(cx, clasp, proto,
+ ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto,
group->flags() & OBJECT_FLAG_DYNAMIC_MASK);
if (!nativeGroup)
return false;
@@ -513,24 +498,19 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
// No sense propagating if we don't know what we started with.
if (!group->unknownProperties()) {
// Propagate all property types from the old group to the new group.
- if (layout.isArray()) {
- if (!PropagatePropertyTypes(cx, JSID_VOID, group, nativeGroup))
+ for (size_t i = 0; i < layout.properties().length(); i++) {
+ const UnboxedLayout::Property& property = layout.properties()[i];
+ jsid id = NameToId(property.name);
+ if (!PropagatePropertyTypes(cx, id, group, nativeGroup))
return false;
- } else {
- for (size_t i = 0; i < layout.properties().length(); i++) {
- const UnboxedLayout::Property& property = layout.properties()[i];
- jsid id = NameToId(property.name);
- if (!PropagatePropertyTypes(cx, id, group, nativeGroup))
- return false;
- // If we are OOM we may not be able to propagate properties.
- if (nativeGroup->unknownProperties())
- break;
+ // If we are OOM we may not be able to propagate properties.
+ if (nativeGroup->unknownProperties())
+ break;
- HeapTypeSet* nativeProperty = nativeGroup->maybeGetProperty(id);
- if (nativeProperty && nativeProperty->canSetDefinite(i))
- nativeProperty->setDefinite(i);
- }
+ HeapTypeSet* nativeProperty = nativeGroup->maybeGetProperty(id);
+ if (nativeProperty && nativeProperty->canSetDefinite(i))
+ nativeProperty->setDefinite(i);
}
} else {
// If we skip, though, the new group had better agree.
@@ -956,702 +936,6 @@ const Class UnboxedPlainObject::class_ = {
};
/////////////////////////////////////////////////////////////////////
-// UnboxedArrayObject
-/////////////////////////////////////////////////////////////////////
-
-template <JSValueType Type>
-DenseElementResult
-AppendUnboxedDenseElements(UnboxedArrayObject* obj, uint32_t initlen,
- MutableHandle<GCVector<Value>> values)
-{
- for (size_t i = 0; i < initlen; i++)
- values.infallibleAppend(obj->getElementSpecific<Type>(i));
- return DenseElementResult::Success;
-}
-
-DefineBoxedOrUnboxedFunctor3(AppendUnboxedDenseElements,
- UnboxedArrayObject*, uint32_t, MutableHandle<GCVector<Value>>);
-
-/* static */ bool
-UnboxedArrayObject::convertToNativeWithGroup(ExclusiveContext* cx, JSObject* obj,
- ObjectGroup* group, Shape* shape)
-{
- size_t length = obj->as<UnboxedArrayObject>().length();
- size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
-
- Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
- if (!values.reserve(initlen))
- return false;
-
- AppendUnboxedDenseElementsFunctor functor(&obj->as<UnboxedArrayObject>(), initlen, &values);
- DebugOnly<DenseElementResult> result = CallBoxedOrUnboxedSpecialization(functor, obj);
- MOZ_ASSERT(result.value == DenseElementResult::Success);
-
- obj->setGroup(group);
-
- ArrayObject* aobj = &obj->as<ArrayObject>();
- aobj->setLastPropertyMakeNative(cx, shape);
-
- // Make sure there is at least one element, so that this array does not
- // use emptyObjectElements / emptyObjectElementsShared.
- if (!aobj->ensureElements(cx, Max<size_t>(initlen, 1)))
- return false;
-
- MOZ_ASSERT(!aobj->getDenseInitializedLength());
- aobj->setDenseInitializedLength(initlen);
- aobj->initDenseElements(0, values.begin(), initlen);
- aobj->setLengthInt32(length);
-
- return true;
-}
-
-/* static */ bool
-UnboxedArrayObject::convertToNative(JSContext* cx, JSObject* obj)
-{
- const UnboxedLayout& layout = obj->as<UnboxedArrayObject>().layout();
-
- if (!layout.nativeGroup()) {
- if (!UnboxedLayout::makeNativeGroup(cx, obj->group()))
- return false;
- }
-
- return convertToNativeWithGroup(cx, obj, layout.nativeGroup(), layout.nativeShape());
-}
-
-bool
-UnboxedArrayObject::convertInt32ToDouble(ExclusiveContext* cx, ObjectGroup* group)
-{
- MOZ_ASSERT(elementType() == JSVAL_TYPE_INT32);
- MOZ_ASSERT(group->unboxedLayout().elementType() == JSVAL_TYPE_DOUBLE);
-
- Vector<int32_t> values(cx);
- if (!values.reserve(initializedLength()))
- return false;
- for (size_t i = 0; i < initializedLength(); i++)
- values.infallibleAppend(getElementSpecific<JSVAL_TYPE_INT32>(i).toInt32());
-
- uint8_t* newElements;
- if (hasInlineElements()) {
- newElements = AllocateObjectBuffer<uint8_t>(cx, this, capacity() * sizeof(double));
- } else {
- newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
- capacity() * sizeof(int32_t),
- capacity() * sizeof(double));
- }
- if (!newElements)
- return false;
-
- setGroup(group);
- elements_ = newElements;
-
- for (size_t i = 0; i < initializedLength(); i++)
- setElementNoTypeChangeSpecific<JSVAL_TYPE_DOUBLE>(i, DoubleValue(values[i]));
-
- return true;
-}
-
-/* static */ UnboxedArrayObject*
-UnboxedArrayObject::create(ExclusiveContext* cx, HandleObjectGroup group, uint32_t length,
- NewObjectKind newKind, uint32_t maxLength)
-{
- MOZ_ASSERT(length <= MaximumCapacity);
-
- MOZ_ASSERT(group->clasp() == &class_);
- uint32_t elementSize = UnboxedTypeSize(group->unboxedLayout().elementType());
- uint32_t capacity = Min(length, maxLength);
- uint32_t nbytes = offsetOfInlineElements() + elementSize * capacity;
-
- UnboxedArrayObject* res;
- if (nbytes <= JSObject::MAX_BYTE_SIZE) {
- gc::AllocKind allocKind = gc::GetGCObjectKindForBytes(nbytes);
-
- // If there was no provided length information, pick an allocation kind
- // to accommodate small arrays (as is done for normal native arrays).
- if (capacity == 0)
- allocKind = gc::AllocKind::OBJECT8;
-
- res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, allocKind, newKind);
- if (!res)
- return nullptr;
- res->setInitializedLengthNoBarrier(0);
- res->setInlineElements();
-
- size_t actualCapacity = (GetGCKindBytes(allocKind) - offsetOfInlineElements()) / elementSize;
- MOZ_ASSERT(actualCapacity >= capacity);
- res->setCapacityIndex(exactCapacityIndex(actualCapacity));
- } else {
- res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, gc::AllocKind::OBJECT0, newKind);
- if (!res)
- return nullptr;
- res->setInitializedLengthNoBarrier(0);
-
- uint32_t capacityIndex = (capacity == length)
- ? CapacityMatchesLengthIndex
- : chooseCapacityIndex(capacity, length);
- uint32_t actualCapacity = computeCapacity(capacityIndex, length);
-
- res->elements_ = AllocateObjectBuffer<uint8_t>(cx, res, actualCapacity * elementSize);
- if (!res->elements_) {
- // Make the object safe for GC.
- res->setInlineElements();
- return nullptr;
- }
-
- res->setCapacityIndex(capacityIndex);
- }
-
- res->setLength(cx, length);
- return res;
-}
-
-bool
-UnboxedArrayObject::setElement(ExclusiveContext* cx, size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- uint8_t* p = elements() + index * elementSize();
- return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ true);
-}
-
-bool
-UnboxedArrayObject::initElement(ExclusiveContext* cx, size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- uint8_t* p = elements() + index * elementSize();
- return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ false);
-}
-
-void
-UnboxedArrayObject::initElementNoTypeChange(size_t index, const Value& v)
-{
- MOZ_ASSERT(index < initializedLength());
- uint8_t* p = elements() + index * elementSize();
- if (UnboxedTypeNeedsPreBarrier(elementType()))
- *reinterpret_cast<void**>(p) = nullptr;
- SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ false);
-}
-
-Value
-UnboxedArrayObject::getElement(size_t index)
-{
- MOZ_ASSERT(index < initializedLength());
- uint8_t* p = elements() + index * elementSize();
- return GetUnboxedValue(p, elementType(), /* maybeUninitialized = */ false);
-}
-
-/* static */ void
-UnboxedArrayObject::trace(JSTracer* trc, JSObject* obj)
-{
- JSValueType type = obj->as<UnboxedArrayObject>().elementType();
- if (!UnboxedTypeNeedsPreBarrier(type))
- return;
-
- MOZ_ASSERT(obj->as<UnboxedArrayObject>().elementSize() == sizeof(uintptr_t));
- size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
- void** elements = reinterpret_cast<void**>(obj->as<UnboxedArrayObject>().elements());
-
- switch (type) {
- case JSVAL_TYPE_OBJECT:
- for (size_t i = 0; i < initlen; i++) {
- GCPtrObject* heap = reinterpret_cast<GCPtrObject*>(elements + i);
- TraceNullableEdge(trc, heap, "unboxed_object");
- }
- break;
-
- case JSVAL_TYPE_STRING:
- for (size_t i = 0; i < initlen; i++) {
- GCPtrString* heap = reinterpret_cast<GCPtrString*>(elements + i);
- TraceEdge(trc, heap, "unboxed_string");
- }
- break;
-
- default:
- MOZ_CRASH();
- }
-}
-
-/* static */ void
-UnboxedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
-{
- UnboxedArrayObject& dst = obj->as<UnboxedArrayObject>();
- const UnboxedArrayObject& src = old->as<UnboxedArrayObject>();
-
- // Fix up possible inline data pointer.
- if (src.hasInlineElements())
- dst.setInlineElements();
-}
-
-/* static */ void
-UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
-{
- MOZ_ASSERT(!IsInsideNursery(obj));
- if (!obj->as<UnboxedArrayObject>().hasInlineElements())
- js_free(obj->as<UnboxedArrayObject>().elements());
-}
-
-/* static */ size_t
-UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
- gc::AllocKind allocKind)
-{
- UnboxedArrayObject* ndst = &dst->as<UnboxedArrayObject>();
- UnboxedArrayObject* nsrc = &src->as<UnboxedArrayObject>();
- MOZ_ASSERT(ndst->elements() == nsrc->elements());
-
- Nursery& nursery = trc->runtime()->gc.nursery;
-
- if (!nursery.isInside(nsrc->elements())) {
- nursery.removeMallocedBuffer(nsrc->elements());
- return 0;
- }
-
- // Determine if we can use inline data for the target array. If this is
- // possible, the nursery will have picked an allocation size that is large
- // enough.
- size_t nbytes = nsrc->capacity() * nsrc->elementSize();
- if (offsetOfInlineElements() + nbytes <= GetGCKindBytes(allocKind)) {
- ndst->setInlineElements();
- } else {
- MOZ_ASSERT(allocKind == gc::AllocKind::OBJECT0);
-
- AutoEnterOOMUnsafeRegion oomUnsafe;
- uint8_t* data = nsrc->zone()->pod_malloc<uint8_t>(nbytes);
- if (!data)
- oomUnsafe.crash("Failed to allocate unboxed array elements while tenuring.");
- ndst->elements_ = data;
- }
-
- PodCopy(ndst->elements(), nsrc->elements(), nsrc->initializedLength() * nsrc->elementSize());
-
- // Set a forwarding pointer for the element buffers in case they were
- // preserved on the stack by Ion.
- bool direct = nsrc->capacity() * nsrc->elementSize() >= sizeof(uintptr_t);
- nursery.maybeSetForwardingPointer(trc, nsrc->elements(), ndst->elements(), direct);
-
- return ndst->hasInlineElements() ? 0 : nbytes;
-}
-
-// Possible capacities for unboxed arrays. Some of these capacities might seem
-// a little weird, but were chosen to allow the inline data of objects of each
-// size to be fully utilized for arrays of the various types on both 32 bit and
-// 64 bit platforms.
-//
-// To find the possible inline capacities, the following script was used:
-//
-// var fixedSlotCapacities = [0, 2, 4, 8, 12, 16];
-// var dataSizes = [1, 4, 8];
-// var header32 = 4 * 2 + 4 * 2;
-// var header64 = 8 * 2 + 4 * 2;
-//
-// for (var i = 0; i < fixedSlotCapacities.length; i++) {
-// var nfixed = fixedSlotCapacities[i];
-// var size32 = 4 * 4 + 8 * nfixed - header32;
-// var size64 = 8 * 4 + 8 * nfixed - header64;
-// for (var j = 0; j < dataSizes.length; j++) {
-// print(size32 / dataSizes[j]);
-// print(size64 / dataSizes[j]);
-// }
-// }
-//
-/* static */ const uint32_t
-UnboxedArrayObject::CapacityArray[] = {
- UINT32_MAX, // For CapacityMatchesLengthIndex.
- 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 16, 17, 18, 24, 26, 32, 34, 40, 64, 72, 96, 104, 128, 136,
- 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288,
- 1048576, 2097152, 3145728, 4194304, 5242880, 6291456, 7340032, 8388608, 9437184, 11534336,
- 13631488, 15728640, 17825792, 20971520, 24117248, 27262976, 31457280, 35651584, 40894464,
- 46137344, 52428800, 59768832, MaximumCapacity
-};
-
-static const uint32_t
-Pow2CapacityIndexes[] = {
- 2, // 1
- 3, // 2
- 5, // 4
- 8, // 8
- 13, // 16
- 18, // 32
- 21, // 64
- 25, // 128
- 27, // 256
- 28, // 512
- 29, // 1024
- 30, // 2048
- 31, // 4096
- 32, // 8192
- 33, // 16384
- 34, // 32768
- 35, // 65536
- 36, // 131072
- 37, // 262144
- 38, // 524288
- 39 // 1048576
-};
-
-static const uint32_t MebiCapacityIndex = 39;
-
-/* static */ uint32_t
-UnboxedArrayObject::chooseCapacityIndex(uint32_t capacity, uint32_t length)
-{
- // Note: the structure and behavior of this method follow along with
- // NativeObject::goodAllocated. Changes to the allocation strategy in one
- // should generally be matched by the other.
-
- // Make sure we have enough space to store all possible values for the capacity index.
- // This ought to be a static_assert, but MSVC doesn't like that.
- MOZ_ASSERT(mozilla::ArrayLength(CapacityArray) - 1 <= (CapacityMask >> CapacityShift));
-
- // The caller should have ensured the capacity is possible for an unboxed array.
- MOZ_ASSERT(capacity <= MaximumCapacity);
-
- static const uint32_t Mebi = 1024 * 1024;
-
- if (capacity <= Mebi) {
- capacity = mozilla::RoundUpPow2(capacity);
-
- // When the required capacity is close to the array length, then round
- // up to the array length itself, as for NativeObject.
- if (length >= capacity && capacity > (length / 3) * 2)
- return CapacityMatchesLengthIndex;
-
- if (capacity < MinimumDynamicCapacity)
- capacity = MinimumDynamicCapacity;
-
- uint32_t bit = mozilla::FloorLog2Size(capacity);
- MOZ_ASSERT(capacity == uint32_t(1 << bit));
- MOZ_ASSERT(bit <= 20);
- MOZ_ASSERT(mozilla::ArrayLength(Pow2CapacityIndexes) == 21);
-
- uint32_t index = Pow2CapacityIndexes[bit];
- MOZ_ASSERT(CapacityArray[index] == capacity);
-
- return index;
- }
-
- MOZ_ASSERT(CapacityArray[MebiCapacityIndex] == Mebi);
-
- for (uint32_t i = MebiCapacityIndex + 1;; i++) {
- if (CapacityArray[i] >= capacity)
- return i;
- }
-
- MOZ_CRASH("Invalid capacity");
-}
-
-/* static */ uint32_t
-UnboxedArrayObject::exactCapacityIndex(uint32_t capacity)
-{
- for (size_t i = CapacityMatchesLengthIndex + 1; i < ArrayLength(CapacityArray); i++) {
- if (CapacityArray[i] == capacity)
- return i;
- }
- MOZ_CRASH();
-}
-
-bool
-UnboxedArrayObject::growElements(ExclusiveContext* cx, size_t cap)
-{
- // The caller should have checked if this capacity is possible for an
- // unboxed array, so the only way this call can fail is from OOM.
- MOZ_ASSERT(cap <= MaximumCapacity);
-
- uint32_t oldCapacity = capacity();
- uint32_t newCapacityIndex = chooseCapacityIndex(cap, length());
- uint32_t newCapacity = computeCapacity(newCapacityIndex, length());
-
- MOZ_ASSERT(oldCapacity < cap);
- MOZ_ASSERT(cap <= newCapacity);
-
- // The allocation size computation below cannot have integer overflows.
- JS_STATIC_ASSERT(MaximumCapacity < UINT32_MAX / sizeof(double));
-
- uint8_t* newElements;
- if (hasInlineElements()) {
- newElements = AllocateObjectBuffer<uint8_t>(cx, this, newCapacity * elementSize());
- if (!newElements)
- return false;
- js_memcpy(newElements, elements(), initializedLength() * elementSize());
- } else {
- newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
- oldCapacity * elementSize(),
- newCapacity * elementSize());
- if (!newElements)
- return false;
- }
-
- elements_ = newElements;
- setCapacityIndex(newCapacityIndex);
-
- return true;
-}
-
-void
-UnboxedArrayObject::shrinkElements(ExclusiveContext* cx, size_t cap)
-{
- if (hasInlineElements())
- return;
-
- uint32_t oldCapacity = capacity();
- uint32_t newCapacityIndex = chooseCapacityIndex(cap, 0);
- uint32_t newCapacity = computeCapacity(newCapacityIndex, 0);
-
- MOZ_ASSERT(cap < oldCapacity);
- MOZ_ASSERT(cap <= newCapacity);
-
- if (newCapacity >= oldCapacity)
- return;
-
- uint8_t* newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
- oldCapacity * elementSize(),
- newCapacity * elementSize());
- if (!newElements)
- return;
-
- elements_ = newElements;
- setCapacityIndex(newCapacityIndex);
-}
-
-bool
-UnboxedArrayObject::containsProperty(ExclusiveContext* cx, jsid id)
-{
- if (JSID_IS_INT(id) && uint32_t(JSID_TO_INT(id)) < initializedLength())
- return true;
- if (JSID_IS_ATOM(id) && JSID_TO_ATOM(id) == cx->names().length)
- return true;
- return false;
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
- HandleId id, MutableHandleObject objp,
- MutableHandleShape propp)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- MarkNonNativePropertyFound<CanGC>(propp);
- objp.set(obj);
- return true;
- }
-
- RootedObject proto(cx, obj->staticPrototype());
- if (!proto) {
- objp.set(nullptr);
- propp.set(nullptr);
- return true;
- }
-
- return LookupProperty(cx, proto, id, objp, propp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result)
-{
- if (JSID_IS_INT(id) && !desc.getter() && !desc.setter() && desc.attributes() == JSPROP_ENUMERATE) {
- UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
-
- uint32_t index = JSID_TO_INT(id);
- if (index < nobj->initializedLength()) {
- if (nobj->setElement(cx, index, desc.value()))
- return result.succeed();
- } else if (index == nobj->initializedLength() && index < MaximumCapacity) {
- if (nobj->initializedLength() == nobj->capacity()) {
- if (!nobj->growElements(cx, index + 1))
- return false;
- }
- nobj->setInitializedLength(index + 1);
- if (nobj->initElement(cx, index, desc.value())) {
- if (nobj->length() <= index)
- nobj->setLengthInt32(index + 1);
- return result.succeed();
- }
- nobj->setInitializedLengthNoBarrier(index);
- }
- }
-
- if (!convertToNative(cx, obj))
- return false;
-
- return DefineProperty(cx, obj, id, desc, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- *foundp = true;
- return true;
- }
-
- RootedObject proto(cx, obj->staticPrototype());
- if (!proto) {
- *foundp = false;
- return true;
- }
-
- return HasProperty(cx, proto, id, foundp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
- HandleId id, MutableHandleValue vp)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- if (JSID_IS_INT(id))
- vp.set(obj->as<UnboxedArrayObject>().getElement(JSID_TO_INT(id)));
- else
- vp.set(Int32Value(obj->as<UnboxedArrayObject>().length()));
- return true;
- }
-
- RootedObject proto(cx, obj->staticPrototype());
- if (!proto) {
- vp.setUndefined();
- return true;
- }
-
- return GetProperty(cx, proto, receiver, id, vp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- if (receiver.isObject() && obj == &receiver.toObject()) {
- if (JSID_IS_INT(id)) {
- if (obj->as<UnboxedArrayObject>().setElement(cx, JSID_TO_INT(id), v))
- return result.succeed();
- } else {
- uint32_t len;
- if (!CanonicalizeArrayLengthValue(cx, v, &len))
- return false;
- UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
- if (len < nobj->initializedLength()) {
- nobj->setInitializedLength(len);
- nobj->shrinkElements(cx, len);
- }
- nobj->setLength(cx, len);
- return result.succeed();
- }
-
- if (!convertToNative(cx, obj))
- return false;
- return SetProperty(cx, obj, id, v, receiver, result);
- }
-
- return SetPropertyByDefining(cx, id, v, receiver, result);
- }
-
- return SetPropertyOnProto(cx, obj, id, v, receiver, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandle<PropertyDescriptor> desc)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- if (JSID_IS_INT(id)) {
- desc.value().set(obj->as<UnboxedArrayObject>().getElement(JSID_TO_INT(id)));
- desc.setAttributes(JSPROP_ENUMERATE);
- } else {
- desc.value().set(Int32Value(obj->as<UnboxedArrayObject>().length()));
- desc.setAttributes(JSPROP_PERMANENT);
- }
- desc.object().set(obj);
- return true;
- }
-
- desc.object().set(nullptr);
- return true;
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
- ObjectOpResult& result)
-{
- if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
- size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
- if (JSID_IS_INT(id) && JSID_TO_INT(id) == int32_t(initlen - 1)) {
- obj->as<UnboxedArrayObject>().setInitializedLength(initlen - 1);
- obj->as<UnboxedArrayObject>().shrinkElements(cx, initlen - 1);
- return result.succeed();
- }
- }
-
- if (!convertToNative(cx, obj))
- return false;
- return DeleteProperty(cx, obj, id, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable)
-{
- if (!convertToNative(cx, obj))
- return false;
- return WatchProperty(cx, obj, id, callable);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
- bool enumerableOnly)
-{
- for (size_t i = 0; i < obj->as<UnboxedArrayObject>().initializedLength(); i++) {
- if (!properties.append(INT_TO_JSID(i)))
- return false;
- }
-
- if (!enumerableOnly && !properties.append(NameToId(cx->names().length)))
- return false;
-
- return true;
-}
-
-static const ClassOps UnboxedArrayObjectClassOps = {
- nullptr, /* addProperty */
- nullptr, /* delProperty */
- nullptr, /* getProperty */
- nullptr, /* setProperty */
- nullptr, /* enumerate */
- nullptr, /* resolve */
- nullptr, /* mayResolve */
- UnboxedArrayObject::finalize,
- nullptr, /* call */
- nullptr, /* hasInstance */
- nullptr, /* construct */
- UnboxedArrayObject::trace,
-};
-
-static const ClassExtension UnboxedArrayObjectClassExtension = {
- nullptr, /* weakmapKeyDelegateOp */
- UnboxedArrayObject::objectMoved
-};
-
-static const ObjectOps UnboxedArrayObjectObjectOps = {
- UnboxedArrayObject::obj_lookupProperty,
- UnboxedArrayObject::obj_defineProperty,
- UnboxedArrayObject::obj_hasProperty,
- UnboxedArrayObject::obj_getProperty,
- UnboxedArrayObject::obj_setProperty,
- UnboxedArrayObject::obj_getOwnPropertyDescriptor,
- UnboxedArrayObject::obj_deleteProperty,
- UnboxedArrayObject::obj_watch,
- nullptr, /* No unwatch needed, as watch() converts the object to native */
- nullptr, /* getElements */
- UnboxedArrayObject::obj_enumerate,
- nullptr /* funToString */
-};
-
-const Class UnboxedArrayObject::class_ = {
- "Array",
- Class::NON_NATIVE |
- JSCLASS_SKIP_NURSERY_FINALIZE |
- JSCLASS_BACKGROUND_FINALIZE,
- &UnboxedArrayObjectClassOps,
- JS_NULL_CLASS_SPEC,
- &UnboxedArrayObjectClassExtension,
- &UnboxedArrayObjectObjectOps
-};
-
-/////////////////////////////////////////////////////////////////////
// API
/////////////////////////////////////////////////////////////////////
@@ -1662,31 +946,6 @@ NextValue(Handle<GCVector<Value>> values, size_t* valueCursor)
}
void
-UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
- Handle<GCVector<Value>> values, size_t* valueCursor)
-{
- MOZ_ASSERT(CapacityArray[1] == 0);
- setCapacityIndex(1);
- setInitializedLengthNoBarrier(0);
- setInlineElements();
-
- setLength(cx, NextValue(values, valueCursor).toInt32());
-
- int32_t initlen = NextValue(values, valueCursor).toInt32();
- if (!initlen)
- return;
-
- AutoEnterOOMUnsafeRegion oomUnsafe;
- if (!growElements(cx, initlen))
- oomUnsafe.crash("UnboxedArrayObject::fillAfterConvert");
-
- setInitializedLength(initlen);
-
- for (size_t i = 0; i < size_t(initlen); i++)
- JS_ALWAYS_TRUE(initElement(cx, i, NextValue(values, valueCursor)));
-}
-
-void
UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
Handle<GCVector<Value>> values, size_t* valueCursor)
{
@@ -1695,58 +954,3 @@ UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
for (size_t i = 0; i < layout().properties().length(); i++)
JS_ALWAYS_TRUE(setValue(cx, layout().properties()[i], NextValue(values, valueCursor)));
}
-
-DefineBoxedOrUnboxedFunctor6(SetOrExtendBoxedOrUnboxedDenseElements,
- ExclusiveContext*, JSObject*, uint32_t, const Value*, uint32_t,
- ShouldUpdateTypes);
-
-DenseElementResult
-js::SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
- uint32_t start, const Value* vp, uint32_t count,
- ShouldUpdateTypes updateTypes)
-{
- SetOrExtendBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, start, vp, count, updateTypes);
- return CallBoxedOrUnboxedSpecialization(functor, obj);
-};
-
-DefineBoxedOrUnboxedFunctor5(MoveBoxedOrUnboxedDenseElements,
- JSContext*, JSObject*, uint32_t, uint32_t, uint32_t);
-
-DenseElementResult
-js::MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
- uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
- MoveBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, dstStart, srcStart, length);
- return CallBoxedOrUnboxedSpecialization(functor, obj);
-}
-
-DefineBoxedOrUnboxedFunctorPair6(CopyBoxedOrUnboxedDenseElements,
- JSContext*, JSObject*, JSObject*, uint32_t, uint32_t, uint32_t);
-
-DenseElementResult
-js::CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
- uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
- CopyBoxedOrUnboxedDenseElementsFunctor functor(cx, dst, src, dstStart, srcStart, length);
- return CallBoxedOrUnboxedSpecialization(functor, dst, src);
-}
-
-DefineBoxedOrUnboxedFunctor3(SetBoxedOrUnboxedInitializedLength,
- JSContext*, JSObject*, size_t);
-
-void
-js::SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
-{
- SetBoxedOrUnboxedInitializedLengthFunctor functor(cx, obj, initlen);
- JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
-}
-
-DefineBoxedOrUnboxedFunctor3(EnsureBoxedOrUnboxedDenseElements,
- JSContext*, JSObject*, size_t);
-
-DenseElementResult
-js::EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t initlen)
-{
- EnsureBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, initlen);
- return CallBoxedOrUnboxedSpecialization(functor, obj);
-}
diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h
index 779dd14c7..ba66434bc 100644
--- a/js/src/vm/UnboxedObject.h
+++ b/js/src/vm/UnboxedObject.h
@@ -96,17 +96,11 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
// from an array of values.
GCPtrJitCode constructorCode_;
- // The following members are only used for unboxed arrays.
-
- // The type of array elements.
- JSValueType elementType_;
-
public:
UnboxedLayout()
: nativeGroup_(nullptr), nativeShape_(nullptr),
allocationScript_(nullptr), allocationPc_(nullptr), replacementGroup_(nullptr),
- size_(0), newScript_(nullptr), traceList_(nullptr), constructorCode_(nullptr),
- elementType_(JSVAL_TYPE_MAGIC)
+ size_(0), newScript_(nullptr), traceList_(nullptr), constructorCode_(nullptr)
{}
bool initProperties(const PropertyVector& properties, size_t size) {
@@ -114,10 +108,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
return properties_.appendAll(properties);
}
- void initArray(JSValueType elementType) {
- elementType_ = elementType;
- }
-
~UnboxedLayout() {
if (newScript_)
newScript_->clear();
@@ -130,10 +120,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
constructorCode_.init(nullptr);
}
- bool isArray() const {
- return elementType_ != JSVAL_TYPE_MAGIC;
- }
-
void detachFromCompartment();
const PropertyVector& properties() const {
@@ -201,10 +187,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
constructorCode_ = code;
}
- JSValueType elementType() const {
- return elementType_;
- }
-
inline gc::AllocKind getAllocKind() const;
void trace(JSTracer* trc);
@@ -324,193 +306,6 @@ UnboxedLayout::getAllocKind() const
return gc::GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + size());
}
-// Class for an array object using an unboxed representation.
-class UnboxedArrayObject : public JSObject
-{
- // Elements pointer for the object.
- uint8_t* elements_;
-
- // The nominal array length. This always fits in an int32_t.
- uint32_t length_;
-
- // Value indicating the allocated capacity and initialized length of the
- // array. The top CapacityBits bits are an index into CapacityArray, which
- // indicates the elements capacity. The low InitializedLengthBits store the
- // initialized length of the array.
- uint32_t capacityIndexAndInitializedLength_;
-
- // If the elements are inline, they will point here.
- uint8_t inlineElements_[1];
-
- public:
- static const uint32_t CapacityBits = 6;
- static const uint32_t CapacityShift = 26;
-
- static const uint32_t CapacityMask = uint32_t(-1) << CapacityShift;
- static const uint32_t InitializedLengthMask = (1 << CapacityShift) - 1;
-
- static const uint32_t MaximumCapacity = InitializedLengthMask;
- static const uint32_t MinimumDynamicCapacity = 8;
-
- static const uint32_t CapacityArray[];
-
- // Capacity index which indicates the array's length is also its capacity.
- static const uint32_t CapacityMatchesLengthIndex = 0;
-
- private:
- static inline uint32_t computeCapacity(uint32_t index, uint32_t length) {
- if (index == CapacityMatchesLengthIndex)
- return length;
- return CapacityArray[index];
- }
-
- static uint32_t chooseCapacityIndex(uint32_t capacity, uint32_t length);
- static uint32_t exactCapacityIndex(uint32_t capacity);
-
- public:
- static const Class class_;
-
- static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
- HandleId id, MutableHandleObject objp,
- MutableHandleShape propp);
-
- static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
- Handle<PropertyDescriptor> desc,
- ObjectOpResult& result);
-
- static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
-
- static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
- HandleId id, MutableHandleValue vp);
-
- static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result);
-
- static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandle<PropertyDescriptor> desc);
-
- static bool obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
- ObjectOpResult& result);
-
- static bool obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
- bool enumerableOnly);
- static bool obj_watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable);
-
- inline const UnboxedLayout& layout() const;
-
- const UnboxedLayout& layoutDontCheckGeneration() const {
- return group()->unboxedLayoutDontCheckGeneration();
- }
-
- JSValueType elementType() const {
- return layoutDontCheckGeneration().elementType();
- }
-
- uint32_t elementSize() const {
- return UnboxedTypeSize(elementType());
- }
-
- static bool convertToNative(JSContext* cx, JSObject* obj);
- static UnboxedArrayObject* create(ExclusiveContext* cx, HandleObjectGroup group,
- uint32_t length, NewObjectKind newKind,
- uint32_t maxLength = MaximumCapacity);
-
- static bool convertToNativeWithGroup(ExclusiveContext* cx, JSObject* obj,
- ObjectGroup* group, Shape* shape);
- bool convertInt32ToDouble(ExclusiveContext* cx, ObjectGroup* group);
-
- void fillAfterConvert(ExclusiveContext* cx,
- Handle<GCVector<Value>> values, size_t* valueCursor);
-
- static void trace(JSTracer* trc, JSObject* object);
- static void objectMoved(JSObject* obj, const JSObject* old);
- static void finalize(FreeOp* fop, JSObject* obj);
-
- static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
- gc::AllocKind allocKind);
-
- uint8_t* elements() {
- return elements_;
- }
-
- bool hasInlineElements() const {
- return elements_ == &inlineElements_[0];
- }
-
- uint32_t length() const {
- return length_;
- }
-
- uint32_t initializedLength() const {
- return capacityIndexAndInitializedLength_ & InitializedLengthMask;
- }
-
- uint32_t capacityIndex() const {
- return (capacityIndexAndInitializedLength_ & CapacityMask) >> CapacityShift;
- }
-
- uint32_t capacity() const {
- return computeCapacity(capacityIndex(), length());
- }
-
- bool containsProperty(ExclusiveContext* cx, jsid id);
-
- bool setElement(ExclusiveContext* cx, size_t index, const Value& v);
- bool initElement(ExclusiveContext* cx, size_t index, const Value& v);
- void initElementNoTypeChange(size_t index, const Value& v);
- Value getElement(size_t index);
-
- template <JSValueType Type> inline bool setElementSpecific(ExclusiveContext* cx, size_t index,
- const Value& v);
- template <JSValueType Type> inline void setElementNoTypeChangeSpecific(size_t index, const Value& v);
- template <JSValueType Type> inline bool initElementSpecific(ExclusiveContext* cx, size_t index,
- const Value& v);
- template <JSValueType Type> inline void initElementNoTypeChangeSpecific(size_t index, const Value& v);
- template <JSValueType Type> inline Value getElementSpecific(size_t index);
- template <JSValueType Type> inline void triggerPreBarrier(size_t index);
-
- bool growElements(ExclusiveContext* cx, size_t cap);
- void shrinkElements(ExclusiveContext* cx, size_t cap);
-
- static uint32_t offsetOfElements() {
- return offsetof(UnboxedArrayObject, elements_);
- }
- static uint32_t offsetOfLength() {
- return offsetof(UnboxedArrayObject, length_);
- }
- static uint32_t offsetOfCapacityIndexAndInitializedLength() {
- return offsetof(UnboxedArrayObject, capacityIndexAndInitializedLength_);
- }
- static uint32_t offsetOfInlineElements() {
- return offsetof(UnboxedArrayObject, inlineElements_);
- }
-
- void setLengthInt32(uint32_t length) {
- MOZ_ASSERT(length <= INT32_MAX);
- length_ = length;
- }
-
- inline void setLength(ExclusiveContext* cx, uint32_t len);
- inline void setInitializedLength(uint32_t initlen);
-
- inline void setInitializedLengthNoBarrier(uint32_t initlen) {
- MOZ_ASSERT(initlen <= InitializedLengthMask);
- capacityIndexAndInitializedLength_ =
- (capacityIndexAndInitializedLength_ & CapacityMask) | initlen;
- }
-
- private:
- void setInlineElements() {
- elements_ = &inlineElements_[0];
- }
-
- void setCapacityIndex(uint32_t index) {
- MOZ_ASSERT(index <= (CapacityMask >> CapacityShift));
- capacityIndexAndInitializedLength_ =
- (index << CapacityShift) | initializedLength();
- }
-};
-
} // namespace js
namespace JS {