summaryrefslogtreecommitdiffstats
path: root/js/src/jit
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-06-29 22:58:52 +0200
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-06-29 22:58:52 +0200
commite09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51 (patch)
treef8d4d2b62b2bcd2f5b37ce7cbf6fa873cff185b0 /js/src/jit
parentbfb36627c66ff8a27da7c1bace60496352fd096b (diff)
parente4b2fa17baea1d35d80de19ffb90d9ba2a1033f8 (diff)
downloadUXP-e09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51.tar
UXP-e09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51.tar.gz
UXP-e09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51.tar.lz
UXP-e09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51.tar.xz
UXP-e09746b2f34ce69c7bc4c86b1f90f62b7c8d9c51.zip
Merge branch 'master' into Pale_Moon-release
# Conflicts: # application/palemoon/config/version.txt # security/manager/ssl/nsSTSPreloadList.errors # security/manager/ssl/nsSTSPreloadList.inc
Diffstat (limited to 'js/src/jit')
-rw-r--r--js/src/jit/AliasAnalysisShared.cpp6
-rw-r--r--js/src/jit/BaselineCacheIR.cpp68
-rw-r--r--js/src/jit/BaselineCompiler.cpp12
-rw-r--r--js/src/jit/BaselineCompiler.h1
-rw-r--r--js/src/jit/BaselineIC.cpp482
-rw-r--r--js/src/jit/BaselineIC.h78
-rw-r--r--js/src/jit/BaselineInspector.cpp79
-rw-r--r--js/src/jit/BaselineInspector.h11
-rw-r--r--js/src/jit/CacheIR.cpp79
-rw-r--r--js/src/jit/CacheIR.h25
-rw-r--r--js/src/jit/CodeGenerator.cpp474
-rw-r--r--js/src/jit/CodeGenerator.h7
-rw-r--r--js/src/jit/IonAnalysis.cpp2
-rw-r--r--js/src/jit/IonBuilder.cpp654
-rw-r--r--js/src/jit/IonBuilder.h35
-rw-r--r--js/src/jit/IonCaches.cpp470
-rw-r--r--js/src/jit/IonCaches.h12
-rw-r--r--js/src/jit/JitOptions.cpp3
-rw-r--r--js/src/jit/JitOptions.h3
-rw-r--r--js/src/jit/Lowering.cpp72
-rw-r--r--js/src/jit/Lowering.h7
-rw-r--r--js/src/jit/MCallOptimize.cpp113
-rw-r--r--js/src/jit/MIR.cpp220
-rw-r--r--js/src/jit/MIR.h345
-rw-r--r--js/src/jit/MOpcodes.h7
-rw-r--r--js/src/jit/MacroAssembler.cpp309
-rw-r--r--js/src/jit/MacroAssembler.h17
-rw-r--r--js/src/jit/OptimizationTracking.cpp2
-rw-r--r--js/src/jit/Recover.cpp37
-rw-r--r--js/src/jit/ScalarReplacement.cpp150
-rw-r--r--js/src/jit/SharedIC.cpp40
-rw-r--r--js/src/jit/VMFunctions.cpp29
-rw-r--r--js/src/jit/VMFunctions.h6
-rw-r--r--js/src/jit/arm/Assembler-arm.cpp7
-rw-r--r--js/src/jit/arm/MacroAssembler-arm.cpp5
-rw-r--r--js/src/jit/shared/LIR-shared.h138
-rw-r--r--js/src/jit/shared/LOpcodes-shared.h7
37 files changed, 407 insertions, 3605 deletions
diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp
index 81c0fd067..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:
@@ -114,8 +110,6 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_GuardObjectGroup:
case MDefinition::Op_GuardObjectIdentity:
case MDefinition::Op_GuardClass:
- case MDefinition::Op_GuardUnboxedExpando:
- case MDefinition::Op_LoadUnboxedExpando:
case MDefinition::Op_LoadSlot:
case MDefinition::Op_StoreSlot:
case MDefinition::Op_InArray:
diff --git a/js/src/jit/BaselineCacheIR.cpp b/js/src/jit/BaselineCacheIR.cpp
index bf96932d1..67c80473b 100644
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -16,7 +16,7 @@ using namespace js;
using namespace js::jit;
// OperandLocation represents the location of an OperandId. The operand is
-// either in a register or on the stack, and is either boxed or unboxed.
+// either in a register or on the stack.
class OperandLocation
{
public:
@@ -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;
@@ -818,36 +815,6 @@ BaselineCacheIRCompiler::emitGuardSpecificObject()
}
bool
-BaselineCacheIRCompiler::emitGuardNoUnboxedExpando()
-{
- Register obj = allocator.useRegister(masm, reader.objOperandId());
-
- FailurePath* failure;
- if (!addFailurePath(&failure))
- return false;
-
- Address expandoAddr(obj, UnboxedPlainObject::offsetOfExpando());
- masm.branchPtr(Assembler::NotEqual, expandoAddr, ImmWord(0), failure->label());
- return true;
-}
-
-bool
-BaselineCacheIRCompiler::emitGuardAndLoadUnboxedExpando()
-{
- Register obj = allocator.useRegister(masm, reader.objOperandId());
- Register output = allocator.defineRegister(masm, reader.objOperandId());
-
- FailurePath* failure;
- if (!addFailurePath(&failure))
- return false;
-
- Address expandoAddr(obj, UnboxedPlainObject::offsetOfExpando());
- masm.loadPtr(expandoAddr, output);
- masm.branchTestPtr(Assembler::Zero, output, output, failure->label());
- return true;
-}
-
-bool
BaselineCacheIRCompiler::emitLoadFixedSlotResult()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
@@ -874,26 +841,6 @@ BaselineCacheIRCompiler::emitLoadDynamicSlotResult()
}
bool
-BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
-{
- Register obj = allocator.useRegister(masm, reader.objOperandId());
- AutoScratchRegister scratch(allocator, masm);
-
- JSValueType fieldType = reader.valueType();
-
- Address fieldOffset(stubAddress(reader.stubOffset()));
- masm.load32(fieldOffset, scratch);
- masm.loadUnboxedProperty(BaseIndex(obj, scratch, TimesOne), fieldType, R0);
-
- if (fieldType == JSVAL_TYPE_OBJECT)
- emitEnterTypeMonitorIC();
- else
- emitReturnFromIC();
-
- return true;
-}
-
-bool
BaselineCacheIRCompiler::emitGuardNoDetachedTypedObjects()
{
FailurePath* failure;
@@ -1004,19 +951,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..d95d08edc 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -42,8 +42,8 @@
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/EnvironmentObject-inl.h"
#include "vm/Interpreter-inl.h"
+#include "vm/NativeObject-inl.h"
#include "vm/StringObject-inl.h"
-#include "vm/UnboxedObject-inl.h"
using mozilla::DebugOnly;
@@ -732,11 +732,6 @@ LastPropertyForSetProp(JSObject* obj)
if (obj->isNative())
return obj->as<NativeObject>().lastProperty();
- if (obj->is<UnboxedPlainObject>()) {
- UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
- return expando ? expando->lastProperty() : nullptr;
- }
-
return nullptr;
}
@@ -1153,56 +1148,6 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
- if (obj->is<UnboxedPlainObject>() && holder == obj) {
- const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
-
- // Once unboxed objects support symbol-keys, we need to change the following accordingly
- MOZ_ASSERT_IF(!keyVal.isString(), !property);
-
- if (property) {
- if (!cx->runtime()->jitSupportsFloatingPoint)
- return true;
-
- RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
- ICGetElemNativeCompiler<PropertyName*> compiler(cx, ICStub::GetElem_UnboxedPropertyName,
- monitorStub, obj, holder,
- name,
- ICGetElemNativeStub::UnboxedProperty,
- needsAtomize, property->offset +
- UnboxedPlainObject::offsetOfData(),
- property->type);
- ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
- if (!newStub)
- return false;
-
- stub->addNewStub(newStub);
- *attached = true;
- return true;
- }
-
- Shape* shape = obj->as<UnboxedPlainObject>().maybeExpando()->lookup(cx, id);
- if (!shape->hasDefaultGetter() || !shape->hasSlot())
- return true;
-
- bool isFixedSlot;
- uint32_t offset;
- GetFixedOrDynamicSlotOffset(shape, &isFixedSlot, &offset);
-
- ICGetElemNativeStub::AccessType acctype =
- isFixedSlot ? ICGetElemNativeStub::FixedSlot
- : ICGetElemNativeStub::DynamicSlot;
- ICGetElemNativeCompiler<T> compiler(cx, getGetElemStubKind<T>(ICStub::GetElem_NativeSlotName),
- monitorStub, obj, holder, key,
- acctype, needsAtomize, offset);
- ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
- if (!newStub)
- return false;
-
- stub->addNewStub(newStub);
- *attached = true;
- return true;
- }
-
if (!holder->isNative())
return true;
@@ -1366,7 +1311,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;
@@ -1450,7 +1395,7 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
}
// Check for NativeObject[id] and UnboxedPlainObject[id] shape-optimizable accesses.
- if (obj->isNative() || obj->is<UnboxedPlainObject>()) {
+ if (obj->isNative()) {
RootedScript rootedScript(cx, script);
if (rhs.isString()) {
if (!TryAttachNativeOrUnboxedGetValueElemStub<PropertyName*>(cx, rootedScript, pc, stub,
@@ -1470,20 +1415,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() &&
@@ -1876,14 +1807,6 @@ ICGetElemNativeCompiler<T>::generateStubCode(MacroAssembler& masm)
Register holderReg;
if (obj_ == holder_) {
holderReg = objReg;
-
- if (obj_->is<UnboxedPlainObject>() && acctype_ != ICGetElemNativeStub::UnboxedProperty) {
- // The property will be loaded off the unboxed expando.
- masm.push(R1.scratchReg());
- popR1 = true;
- holderReg = R1.scratchReg();
- masm.loadPtr(Address(objReg, UnboxedPlainObject::offsetOfExpando()), holderReg);
- }
} else {
// Shape guard holder.
if (regs.empty()) {
@@ -1934,13 +1857,6 @@ ICGetElemNativeCompiler<T>::generateStubCode(MacroAssembler& masm)
if (popR1)
masm.addToStackPtr(ImmWord(sizeof(size_t)));
- } else if (acctype_ == ICGetElemNativeStub::UnboxedProperty) {
- masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub<T>::offsetOfOffset()),
- scratchReg);
- masm.loadUnboxedProperty(BaseIndex(objReg, scratchReg, TimesOne), unboxedType_,
- TypedOrValueRegister(R0));
- if (popR1)
- masm.addToStackPtr(ImmWord(sizeof(size_t)));
} else {
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::NativeGetter ||
acctype_ == ICGetElemNativeStub::ScriptedGetter);
@@ -2090,56 +2006,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 +2303,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 +2313,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 +2394,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) {
@@ -2741,18 +2603,6 @@ BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
// SetElem_DenseOrUnboxedArray
//
-template <typename T>
-void
-EmitUnboxedPreBarrierForBaseline(MacroAssembler &masm, T address, JSValueType type)
-{
- if (type == JSVAL_TYPE_OBJECT)
- EmitPreBarrier(masm, address, MIRType::Object);
- else if (type == JSVAL_TYPE_STRING)
- EmitPreBarrier(masm, address, MIRType::String);
- else
- MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(type));
-}
-
bool
ICSetElem_DenseOrUnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
{
@@ -2871,29 +2721,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 +2914,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);
@@ -4256,18 +4049,7 @@ TryAttachSetValuePropStub(JSContext* cx, HandleScript script, jsbytecode* pc, IC
return true;
if (!obj->isNative()) {
- if (obj->is<UnboxedPlainObject>()) {
- UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
- if (expando) {
- shape = expando->lookup(cx, name);
- if (!shape)
- return true;
- } else {
- return true;
- }
- } else {
- return true;
- }
+ return true;
}
size_t chainDepth;
@@ -4418,40 +4200,6 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
}
static bool
-TryAttachUnboxedSetPropStub(JSContext* cx, HandleScript script,
- ICSetProp_Fallback* stub, HandleId id,
- HandleObject obj, HandleValue rhs, bool* attached)
-{
- MOZ_ASSERT(!*attached);
-
- if (!cx->runtime()->jitSupportsFloatingPoint)
- return true;
-
- if (!obj->is<UnboxedPlainObject>())
- return true;
-
- const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
- if (!property)
- return true;
-
- ICSetProp_Unboxed::Compiler compiler(cx, obj->group(),
- property->offset + UnboxedPlainObject::offsetOfData(),
- property->type);
- ICUpdatedStub* newStub = compiler.getStub(compiler.getStubSpace(script));
- if (!newStub)
- return false;
- if (compiler.needsUpdateStubs() && !newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
- return false;
-
- stub->addNewStub(newStub);
-
- StripPreliminaryObjectStubs(cx, stub);
-
- *attached = true;
- return true;
-}
-
-static bool
TryAttachTypedObjectSetPropStub(JSContext* cx, HandleScript script,
ICSetProp_Fallback* stub, HandleId id,
HandleObject obj, HandleValue rhs, bool* attached)
@@ -4534,12 +4282,6 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
return false;
RootedReceiverGuard oldGuard(cx, ReceiverGuard(obj));
- if (obj->is<UnboxedPlainObject>()) {
- MOZ_ASSERT(!oldShape);
- if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
- oldShape = expando->lastProperty();
- }
-
bool attached = false;
// There are some reasons we can fail to attach a stub that are temporary.
// We want to avoid calling noteUnoptimizableAccess() if the reason we
@@ -4612,15 +4354,6 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
if (!attached &&
lhs.isObject() &&
- !TryAttachUnboxedSetPropStub(cx, script, stub, id, obj, rhs, &attached))
- {
- return false;
- }
- if (attached)
- return true;
-
- if (!attached &&
- lhs.isObject() &&
!TryAttachTypedObjectSetPropStub(cx, script, stub, id, obj, rhs, &attached))
{
return false;
@@ -4703,20 +4436,7 @@ GuardGroupAndShapeMaybeUnboxedExpando(MacroAssembler& masm, JSObject* obj,
// Guard against shape or expando shape.
masm.loadPtr(Address(ICStubReg, offsetOfShape), scratch);
- if (obj->is<UnboxedPlainObject>()) {
- Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
- masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failure);
- Label done;
- masm.push(object);
- masm.loadPtr(expandoAddress, object);
- masm.branchTestObjShape(Assembler::Equal, object, scratch, &done);
- masm.pop(object);
- masm.jump(failure);
- masm.bind(&done);
- masm.pop(object);
- } else {
- masm.branchTestObjShape(Assembler::NotEqual, object, scratch, failure);
- }
+ masm.branchTestObjShape(Assembler::NotEqual, object, scratch, failure);
}
bool
@@ -4755,13 +4475,7 @@ ICSetProp_Native::Compiler::generateStubCode(MacroAssembler& masm)
regs.takeUnchecked(objReg);
Register holderReg;
- if (obj_->is<UnboxedPlainObject>()) {
- // We are loading off the expando object, so use that for the holder.
- holderReg = regs.takeAny();
- masm.loadPtr(Address(objReg, UnboxedPlainObject::offsetOfExpando()), holderReg);
- if (!isFixedSlot_)
- masm.loadPtr(Address(holderReg, NativeObject::offsetOfSlots()), holderReg);
- } else if (isFixedSlot_) {
+ if (isFixedSlot_) {
holderReg = objReg;
} else {
holderReg = regs.takeAny();
@@ -4898,31 +4612,17 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler& masm)
regs.add(R0);
regs.takeUnchecked(objReg);
- if (obj_->is<UnboxedPlainObject>()) {
- holderReg = regs.takeAny();
- masm.loadPtr(Address(objReg, UnboxedPlainObject::offsetOfExpando()), holderReg);
-
- // Write the expando object's new shape.
- Address shapeAddr(holderReg, ShapedObject::offsetOfShape());
- EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
- masm.loadPtr(Address(ICStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
- masm.storePtr(scratch, shapeAddr);
+ // Write the object's new shape.
+ Address shapeAddr(objReg, ShapedObject::offsetOfShape());
+ EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
+ masm.loadPtr(Address(ICStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
+ masm.storePtr(scratch, shapeAddr);
- if (!isFixedSlot_)
- masm.loadPtr(Address(holderReg, NativeObject::offsetOfSlots()), holderReg);
+ if (isFixedSlot_) {
+ holderReg = objReg;
} else {
- // Write the object's new shape.
- Address shapeAddr(objReg, ShapedObject::offsetOfShape());
- EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
- masm.loadPtr(Address(ICStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
- masm.storePtr(scratch, shapeAddr);
-
- if (isFixedSlot_) {
- holderReg = objReg;
- } else {
- holderReg = regs.takeAny();
- masm.loadPtr(Address(objReg, NativeObject::offsetOfSlots()), holderReg);
- }
+ holderReg = regs.takeAny();
+ masm.loadPtr(Address(objReg, NativeObject::offsetOfSlots()), holderReg);
}
// Perform the store. No write barrier required since this is a new
@@ -4954,70 +4654,6 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler& masm)
}
bool
-ICSetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm)
-{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
- Label failure;
-
- // Guard input is an object.
- masm.branchTestObject(Assembler::NotEqual, R0, &failure);
-
- AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
- Register scratch = regs.takeAny();
-
- // Unbox and group guard.
- Register object = masm.extractObject(R0, ExtractTemp0);
- masm.loadPtr(Address(ICStubReg, ICSetProp_Unboxed::offsetOfGroup()), scratch);
- masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfGroup()), scratch,
- &failure);
-
- if (needsUpdateStubs()) {
- // Stow both R0 and R1 (object and value).
- EmitStowICValues(masm, 2);
-
- // Move RHS into R0 for TypeUpdate check.
- masm.moveValue(R1, R0);
-
- // Call the type update stub.
- if (!callTypeUpdateIC(masm, sizeof(Value)))
- return false;
-
- // Unstow R0 and R1 (object and key)
- EmitUnstowICValues(masm, 2);
-
- // The TypeUpdate IC may have smashed object. Rederive it.
- masm.unboxObject(R0, object);
-
- // Trigger post barriers here on the values being written. Fields which
- // objects can be written to also need update stubs.
- LiveGeneralRegisterSet saveRegs;
- saveRegs.add(R0);
- saveRegs.add(R1);
- saveRegs.addUnchecked(object);
- saveRegs.add(ICStubReg);
- emitPostWriteBarrierSlot(masm, object, R1, scratch, saveRegs);
- }
-
- // Compute the address being written to.
- masm.load32(Address(ICStubReg, ICSetProp_Unboxed::offsetOfFieldOffset()), scratch);
- BaseIndex address(object, scratch, TimesOne);
-
- EmitUnboxedPreBarrierForBaseline(masm, address, fieldType_);
- masm.storeUnboxedProperty(address, fieldType_,
- ConstantOrRegister(TypedOrValueRegister(R1)), &failure);
-
- // The RHS has to be in R0.
- masm.moveValue(R1, R0);
-
- EmitReturnFromIC(masm);
-
- masm.bind(&failure);
- EmitStubGuardFailure(masm);
- return true;
-}
-
-bool
ICSetProp_TypedObject::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
@@ -5490,13 +5126,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 +5157,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 +5183,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 +5200,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) {
@@ -5793,7 +5413,7 @@ TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script, jsb
if (!thisObject)
return false;
- if (thisObject->is<PlainObject>() || thisObject->is<UnboxedPlainObject>())
+ if (thisObject->is<PlainObject>())
templateObject = thisObject;
}
@@ -5887,15 +5507,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 +5555,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 +6455,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 +7926,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 +8301,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..98f0e1c59 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -22,7 +22,6 @@
#include "jit/SharedICRegisters.h"
#include "js/GCVector.h"
#include "vm/ArrayObject.h"
-#include "vm/UnboxedObject.h"
namespace js {
namespace jit {
@@ -892,54 +891,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 +1066,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 +1174,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>
@@ -1875,8 +1822,7 @@ class ICSetProp_Native : public ICUpdatedStub
virtual int32_t getKey() const {
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
- (static_cast<int32_t>(isFixedSlot_) << 17) |
- (static_cast<int32_t>(obj_->is<UnboxedPlainObject>()) << 18);
+ (static_cast<int32_t>(isFixedSlot_) << 17);
}
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
@@ -1981,7 +1927,6 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(isFixedSlot_) << 17) |
- (static_cast<int32_t>(obj_->is<UnboxedPlainObject>()) << 18) |
(static_cast<int32_t>(protoChainDepth_) << 19);
}
@@ -2006,10 +1951,7 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler
newGroup = nullptr;
RootedShape newShape(cx);
- if (obj_->isNative())
- newShape = obj_->as<NativeObject>().lastProperty();
- else
- newShape = obj_->as<UnboxedPlainObject>().maybeExpando()->lastProperty();
+ newShape = obj_->as<NativeObject>().lastProperty();
return newStub<ICSetProp_NativeAddImpl<ProtoChainDepth>>(
space, getStubCode(), oldGroup_, shapes, newShape, newGroup, offset_);
@@ -2870,10 +2812,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 +2842,7 @@ class ICCall_StringSplit : public ICMonitoredStub
return expectedSep_;
}
- GCPtrObject& templateObject() {
+ GCPtrArrayObject& templateObject() {
return templateObject_;
}
@@ -2910,7 +2852,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 +2863,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 c9e09bed7..3b852debf 100644
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -96,32 +96,19 @@ VectorAppendNoDuplicate(S& list, T value)
static bool
AddReceiver(const ReceiverGuard& receiver,
- BaselineInspector::ReceiverVector& receivers,
- BaselineInspector::ObjectGroupVector& convertUnboxedGroups)
+ BaselineInspector::ReceiverVector& receivers)
{
- if (receiver.group && receiver.group->maybeUnboxedLayout()) {
- if (receiver.group->unboxedLayout().nativeGroup())
- return VectorAppendNoDuplicate(convertUnboxedGroups, receiver.group);
- }
return VectorAppendNoDuplicate(receivers, receiver);
}
static bool
GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* receiver)
{
- // We match either:
+ // We match:
//
// GuardIsObject 0
// GuardShape 0
// LoadFixedSlotResult 0 or LoadDynamicSlotResult 0
- //
- // or
- //
- // GuardIsObject 0
- // GuardGroup 0
- // 1: GuardAndLoadUnboxedExpando 0
- // GuardShape 1
- // LoadFixedSlotResult 1 or LoadDynamicSlotResult 1
*receiver = ReceiverGuard();
CacheIRReader reader(stub->stubInfo());
@@ -130,14 +117,6 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re
if (!reader.matchOp(CacheOp::GuardIsObject, objId))
return false;
- if (reader.matchOp(CacheOp::GuardGroup, objId)) {
- receiver->group = stub->stubInfo()->getStubField<ObjectGroup*>(stub, reader.stubOffset());
-
- if (!reader.matchOp(CacheOp::GuardAndLoadUnboxedExpando, objId))
- return false;
- objId = reader.objOperandId();
- }
-
if (reader.matchOp(CacheOp::GuardShape, objId)) {
receiver->shape = stub->stubInfo()->getStubField<Shape*>(stub, reader.stubOffset());
return reader.matchOpEither(CacheOp::LoadFixedSlotResult, CacheOp::LoadDynamicSlotResult);
@@ -146,40 +125,13 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re
return false;
}
-static bool
-GetCacheIRReceiverForUnboxedProperty(ICCacheIR_Monitored* stub, ReceiverGuard* receiver)
-{
- // We match:
- //
- // GuardIsObject 0
- // GuardGroup 0
- // LoadUnboxedPropertyResult 0 ..
-
- *receiver = ReceiverGuard();
- CacheIRReader reader(stub->stubInfo());
-
- ObjOperandId objId = ObjOperandId(0);
- if (!reader.matchOp(CacheOp::GuardIsObject, objId))
- return false;
-
- if (!reader.matchOp(CacheOp::GuardGroup, objId))
- return false;
- receiver->group = stub->stubInfo()->getStubField<ObjectGroup*>(stub, reader.stubOffset());
-
- return reader.matchOp(CacheOp::LoadUnboxedPropertyResult, objId);
-}
-
bool
-BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups)
+BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers)
{
// Return a list of the receivers seen by the baseline IC for the current
// op. Empty lists indicate no receivers are known, or there was an
- // uncacheable access. convertUnboxedGroups is used for unboxed object
- // groups which have been seen, but have had instances converted to native
- // objects and should be eagerly converted by Ion.
+ // uncacheable access.
MOZ_ASSERT(receivers.empty());
- MOZ_ASSERT(convertUnboxedGroups.empty());
if (!hasBaselineScript())
return true;
@@ -191,8 +143,7 @@ BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receiv
while (stub->next()) {
ReceiverGuard receiver;
if (stub->isCacheIR_Monitored()) {
- if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver) &&
- !GetCacheIRReceiverForUnboxedProperty(stub->toCacheIR_Monitored(), &receiver))
+ if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver))
{
receivers.clear();
return true;
@@ -200,14 +151,12 @@ BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receiv
} else if (stub->isSetProp_Native()) {
receiver = ReceiverGuard(stub->toSetProp_Native()->group(),
stub->toSetProp_Native()->shape());
- } else if (stub->isSetProp_Unboxed()) {
- receiver = ReceiverGuard(stub->toSetProp_Unboxed()->group(), nullptr);
} else {
receivers.clear();
return true;
}
- if (!AddReceiver(receiver, receivers, convertUnboxedGroups))
+ if (!AddReceiver(receiver, receivers))
return false;
stub = stub->next();
@@ -589,7 +538,7 @@ BaselineInspector::getTemplateObjectForNative(jsbytecode* pc, Native native)
bool
BaselineInspector::isOptimizableCallStringSplit(jsbytecode* pc, JSString** strOut, JSString** sepOut,
- JSObject** objOut)
+ ArrayObject** objOut)
{
if (!hasBaselineScript())
return false;
@@ -700,14 +649,12 @@ bool
BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
JSFunction** commonGetter, Shape** globalShape,
bool* isOwnProperty,
- ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups)
+ ReceiverVector& receivers)
{
if (!hasBaselineScript())
return false;
MOZ_ASSERT(receivers.empty());
- MOZ_ASSERT(convertUnboxedGroups.empty());
*holder = nullptr;
const ICEntry& entry = icEntryFromPC(pc);
@@ -719,7 +666,7 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
{
ICGetPropCallGetter* nstub = static_cast<ICGetPropCallGetter*>(stub);
bool isOwn = nstub->isOwnGetter();
- if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers, convertUnboxedGroups))
+ if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers))
return false;
if (!*holder) {
@@ -751,21 +698,19 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
if (!*holder)
return false;
- MOZ_ASSERT(*isOwnProperty == (receivers.empty() && convertUnboxedGroups.empty()));
+ MOZ_ASSERT(*isOwnProperty == (receivers.empty()));
return true;
}
bool
BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
JSFunction** commonSetter, bool* isOwnProperty,
- ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups)
+ ReceiverVector& receivers)
{
if (!hasBaselineScript())
return false;
MOZ_ASSERT(receivers.empty());
- MOZ_ASSERT(convertUnboxedGroups.empty());
*holder = nullptr;
const ICEntry& entry = icEntryFromPC(pc);
@@ -774,7 +719,7 @@ BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shap
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
ICSetPropCallSetter* nstub = static_cast<ICSetPropCallSetter*>(stub);
bool isOwn = nstub->isOwnSetter();
- if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers, convertUnboxedGroups))
+ if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers))
return false;
if (!*holder) {
diff --git a/js/src/jit/BaselineInspector.h b/js/src/jit/BaselineInspector.h
index 961df18aa..1ed4b5547 100644
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -95,8 +95,7 @@ class BaselineInspector
public:
typedef Vector<ReceiverGuard, 4, JitAllocPolicy> ReceiverVector;
typedef Vector<ObjectGroup*, 4, JitAllocPolicy> ObjectGroupVector;
- MOZ_MUST_USE bool maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups);
+ MOZ_MUST_USE bool maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers);
SetElemICInspector setElemICInspector(jsbytecode* pc) {
return makeICInspector<SetElemICInspector>(pc, ICStub::SetElem_Fallback);
@@ -114,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);
@@ -131,12 +130,10 @@ class BaselineInspector
MOZ_MUST_USE bool commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
JSFunction** commonGetter, Shape** globalShape,
- bool* isOwnProperty, ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups);
+ bool* isOwnProperty, ReceiverVector& receivers);
MOZ_MUST_USE bool commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
JSFunction** commonSetter, bool* isOwnProperty,
- ReceiverVector& receivers,
- ObjectGroupVector& convertUnboxedGroups);
+ ReceiverVector& receivers);
MOZ_MUST_USE bool instanceOfData(jsbytecode* pc, Shape** shape, uint32_t* slot,
JSObject** prototypeObject);
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
index f1061af70..d184ea40c 100644
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -10,8 +10,7 @@
#include "jit/IonCaches.h"
#include "jsobjinlines.h"
-
-#include "vm/UnboxedObject-inl.h"
+#include "vm/NativeObject-inl.h"
using namespace js;
using namespace js::jit;
@@ -60,10 +59,6 @@ GetPropIRGenerator::tryAttachStub(Maybe<CacheIRWriter>& writer)
return false;
if (!emitted_ && !tryAttachNative(*writer, obj, objId))
return false;
- if (!emitted_ && !tryAttachUnboxed(*writer, obj, objId))
- return false;
- if (!emitted_ && !tryAttachUnboxedExpando(*writer, obj, objId))
- return false;
if (!emitted_ && !tryAttachTypedObject(*writer, obj, objId))
return false;
if (!emitted_ && !tryAttachModuleNamespace(*writer, obj, objId))
@@ -163,19 +158,9 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
}
static void
-TestMatchingReceiver(CacheIRWriter& writer, JSObject* obj, Shape* shape, ObjOperandId objId,
- Maybe<ObjOperandId>* expandoId)
+TestMatchingReceiver(CacheIRWriter& writer, JSObject* obj, Shape* shape, ObjOperandId objId)
{
- if (obj->is<UnboxedPlainObject>()) {
- writer.guardGroup(objId, obj->group());
-
- if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
- expandoId->emplace(writer.guardAndLoadUnboxedExpando(objId));
- writer.guardShape(expandoId->ref(), expando->lastProperty());
- } else {
- writer.guardNoUnboxedExpando(objId);
- }
- } else if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
+ if (obj->is<TypedObject>()) {
writer.guardGroup(objId, obj->group());
} else {
Shape* shape = obj->maybeShape();
@@ -188,8 +173,7 @@ static void
EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
Shape* shape, ObjOperandId objId)
{
- Maybe<ObjOperandId> expandoId;
- TestMatchingReceiver(writer, obj, shape, objId, &expandoId);
+ TestMatchingReceiver(writer, obj, shape, objId);
ObjOperandId holderId;
if (obj != holder) {
@@ -212,9 +196,6 @@ EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
lastObjId = protoId;
}
}
- } else if (obj->is<UnboxedPlainObject>()) {
- holder = obj->as<UnboxedPlainObject>().maybeExpando();
- holderId = *expandoId;
} else {
holderId = objId;
}
@@ -266,51 +247,6 @@ GetPropIRGenerator::tryAttachNative(CacheIRWriter& writer, HandleObject obj, Obj
}
bool
-GetPropIRGenerator::tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
-{
- MOZ_ASSERT(!emitted_);
-
- if (!obj->is<UnboxedPlainObject>())
- return true;
-
- const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(name_);
- if (!property)
- return true;
-
- if (!cx_->runtime()->jitSupportsFloatingPoint)
- return true;
-
- writer.guardGroup(objId, obj->group());
- writer.loadUnboxedPropertyResult(objId, property->type,
- UnboxedPlainObject::offsetOfData() + property->offset);
- emitted_ = true;
- preliminaryObjectAction_ = PreliminaryObjectAction::Unlink;
- return true;
-}
-
-bool
-GetPropIRGenerator::tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
-{
- MOZ_ASSERT(!emitted_);
-
- if (!obj->is<UnboxedPlainObject>())
- return true;
-
- UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
- if (!expando)
- return true;
-
- Shape* shape = expando->lookup(cx_, NameToId(name_));
- if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
- return true;
-
- emitted_ = true;
-
- EmitReadSlotResult(writer, obj, obj, shape, objId);
- return true;
-}
-
-bool
GetPropIRGenerator::tryAttachTypedObject(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
{
MOZ_ASSERT(!emitted_);
@@ -368,13 +304,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..ae55cfebb 100644
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -87,16 +87,12 @@ class ObjOperandId : public OperandId
_(GuardClass) \
_(GuardSpecificObject) \
_(GuardNoDetachedTypedObjects) \
- _(GuardNoUnboxedExpando) \
- _(GuardAndLoadUnboxedExpando) \
_(LoadObject) \
_(LoadProto) \
_(LoadFixedSlotResult) \
_(LoadDynamicSlotResult) \
- _(LoadUnboxedPropertyResult) \
_(LoadTypedObjectResult) \
_(LoadInt32ArrayLengthResult) \
- _(LoadUnboxedArrayLengthResult) \
_(LoadArgumentsObjectLengthResult) \
_(LoadUndefinedResult)
@@ -128,7 +124,6 @@ struct StubField {
enum class GuardClassKind
{
Array,
- UnboxedArray,
MappedArguments,
UnmappedArguments,
};
@@ -276,15 +271,6 @@ class MOZ_RAII CacheIRWriter
void guardNoDetachedTypedObjects() {
writeOp(CacheOp::GuardNoDetachedTypedObjects);
}
- void guardNoUnboxedExpando(ObjOperandId obj) {
- writeOpWithOperandId(CacheOp::GuardNoUnboxedExpando, obj);
- }
- ObjOperandId guardAndLoadUnboxedExpando(ObjOperandId obj) {
- ObjOperandId res(nextOperandId_++);
- writeOpWithOperandId(CacheOp::GuardAndLoadUnboxedExpando, obj);
- writeOperandId(res);
- return res;
- }
ObjOperandId loadObject(JSObject* obj) {
ObjOperandId res(nextOperandId_++);
@@ -310,11 +296,6 @@ class MOZ_RAII CacheIRWriter
writeOpWithOperandId(CacheOp::LoadDynamicSlotResult, obj);
addStubWord(offset, StubField::GCType::NoGCThing);
}
- void loadUnboxedPropertyResult(ObjOperandId obj, JSValueType type, size_t offset) {
- writeOpWithOperandId(CacheOp::LoadUnboxedPropertyResult, obj);
- buffer_.writeByte(uint32_t(type));
- addStubWord(offset, StubField::GCType::NoGCThing);
- }
void loadTypedObjectResult(ObjOperandId obj, uint32_t offset, TypedThingLayout layout,
uint32_t typeDescr) {
MOZ_ASSERT(uint32_t(layout) <= UINT8_MAX);
@@ -327,9 +308,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);
}
@@ -411,9 +389,6 @@ class MOZ_RAII GetPropIRGenerator
PreliminaryObjectAction preliminaryObjectAction_;
MOZ_MUST_USE bool tryAttachNative(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);
- MOZ_MUST_USE bool tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);
- MOZ_MUST_USE bool tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj,
- ObjOperandId objId);
MOZ_MUST_USE bool tryAttachTypedObject(CacheIRWriter& writer, HandleObject obj,
ObjOperandId objId);
MOZ_MUST_USE bool tryAttachObjectLength(CacheIRWriter& writer, HandleObject obj,
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 16d026092..fcb711237 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -25,6 +25,7 @@
#include "builtin/Eval.h"
#include "builtin/TypedObject.h"
#include "gc/Nursery.h"
+#include "gc/StoreBuffer-inl.h"
#include "irregexp/NativeRegExpMacroAssembler.h"
#include "jit/AtomicOperations.h"
#include "jit/BaselineCompiler.h"
@@ -3027,19 +3028,10 @@ CodeGenerator::visitStoreSlotV(LStoreSlotV* lir)
static void
GuardReceiver(MacroAssembler& masm, const ReceiverGuard& guard,
- Register obj, Register scratch, Label* miss, bool checkNullExpando)
+ Register obj, Register scratch, Label* miss)
{
if (guard.group) {
masm.branchTestObjGroup(Assembler::NotEqual, obj, guard.group, miss);
-
- Address expandoAddress(obj, UnboxedPlainObject::offsetOfExpando());
- if (guard.shape) {
- masm.loadPtr(expandoAddress, scratch);
- masm.branchPtr(Assembler::Equal, scratch, ImmWord(0), miss);
- masm.branchTestObjShape(Assembler::NotEqual, scratch, guard.shape, miss);
- } else if (checkNullExpando) {
- masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), miss);
- }
} else {
masm.branchTestObjShape(Assembler::NotEqual, obj, guard.shape, miss);
}
@@ -3058,13 +3050,11 @@ CodeGenerator::emitGetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
Label next;
masm.comment("GuardReceiver");
- GuardReceiver(masm, receiver, obj, scratch, &next, /* checkNullExpando = */ false);
+ GuardReceiver(masm, receiver, obj, scratch, &next);
if (receiver.shape) {
masm.comment("loadTypedOrValue");
- // If this is an unboxed expando access, GuardReceiver loaded the
- // expando object into scratch.
- Register target = receiver.group ? scratch : obj;
+ Register target = obj;
Shape* shape = mir->shape(i);
if (shape->slot() < shape->numFixedSlots()) {
@@ -3077,13 +3067,6 @@ CodeGenerator::emitGetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
masm.loadPtr(Address(target, NativeObject::offsetOfSlots()), scratch);
masm.loadTypedOrValue(Address(scratch, offset), output);
}
- } else {
- masm.comment("loadUnboxedProperty");
- const UnboxedLayout::Property* property =
- receiver.group->unboxedLayout().lookup(mir->name());
- Address propertyAddr(obj, UnboxedPlainObject::offsetOfData() + property->offset);
-
- masm.loadUnboxedProperty(propertyAddr, property->type, output);
}
if (i == mir->numReceivers() - 1) {
@@ -3124,8 +3107,6 @@ EmitUnboxedPreBarrier(MacroAssembler &masm, T address, JSValueType type)
masm.patchableCallPreBarrier(address, MIRType::Object);
else if (type == JSVAL_TYPE_STRING)
masm.patchableCallPreBarrier(address, MIRType::String);
- else
- MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(type));
}
void
@@ -3139,12 +3120,10 @@ CodeGenerator::emitSetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
ReceiverGuard receiver = mir->receiver(i);
Label next;
- GuardReceiver(masm, receiver, obj, scratch, &next, /* checkNullExpando = */ false);
+ GuardReceiver(masm, receiver, obj, scratch, &next);
if (receiver.shape) {
- // If this is an unboxed expando access, GuardReceiver loaded the
- // expando object into scratch.
- Register target = receiver.group ? scratch : obj;
+ Register target = obj;
Shape* shape = mir->shape(i);
if (shape->slot() < shape->numFixedSlots()) {
@@ -3161,13 +3140,6 @@ CodeGenerator::emitSetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
emitPreBarrier(addr);
masm.storeConstantOrRegister(value, addr);
}
- } else {
- const UnboxedLayout::Property* property =
- receiver.group->unboxedLayout().lookup(mir->name());
- Address propertyAddr(obj, UnboxedPlainObject::offsetOfData() + property->offset);
-
- EmitUnboxedPreBarrier(masm, propertyAddr, property->type);
- masm.storeUnboxedProperty(propertyAddr, property->type, value, nullptr);
}
if (i == mir->numReceivers() - 1) {
@@ -3208,9 +3180,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()));
}
@@ -3319,7 +3289,7 @@ CodeGenerator::visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir)
const ReceiverGuard& receiver = mir->receiver(i);
Label next;
- GuardReceiver(masm, receiver, obj, temp, &next, /* checkNullExpando = */ true);
+ GuardReceiver(masm, receiver, obj, temp, &next);
if (i == mir->numReceivers() - 1) {
bailoutFrom(&next, lir->snapshot());
@@ -3333,27 +3303,6 @@ CodeGenerator::visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir)
}
void
-CodeGenerator::visitGuardUnboxedExpando(LGuardUnboxedExpando* lir)
-{
- Label miss;
-
- Register obj = ToRegister(lir->object());
- masm.branchPtr(lir->mir()->requireExpando() ? Assembler::Equal : Assembler::NotEqual,
- Address(obj, UnboxedPlainObject::offsetOfExpando()), ImmWord(0), &miss);
-
- bailoutFrom(&miss, lir->snapshot());
-}
-
-void
-CodeGenerator::visitLoadUnboxedExpando(LLoadUnboxedExpando* lir)
-{
- Register obj = ToRegister(lir->object());
- Register result = ToRegister(lir->getDef(0));
-
- masm.loadPtr(Address(obj, UnboxedPlainObject::offsetOfExpando()), result);
-}
-
-void
CodeGenerator::visitTypeBarrierV(LTypeBarrierV* lir)
{
ValueOperand operand = ToValue(lir, LTypeBarrierV::Input);
@@ -5217,11 +5166,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;
}
@@ -5367,7 +5316,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");
@@ -5387,21 +5336,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) {
@@ -7823,7 +7762,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");
@@ -7858,49 +7797,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(),
@@ -8196,46 +8092,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());
+ 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);
-
- 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());
}
@@ -8255,47 +8124,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());
}
@@ -8366,11 +8210,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)
@@ -8380,8 +8223,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
const LAllocation* index;
MIRType valueType;
ConstantOrRegister value;
- JSValueType unboxedType;
- LDefinition *temp = nullptr;
if (ins->isStoreElementHoleV()) {
LStoreElementHoleV* store = ins->toStoreElementHoleV();
@@ -8390,8 +8231,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());
@@ -8399,8 +8238,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());
@@ -8411,8 +8248,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());
@@ -8423,8 +8258,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);
@@ -8435,54 +8268,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);
+ // 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()));
-
- // 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
@@ -8511,7 +8322,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
else
pushArg(ToRegister(index));
pushArg(object);
- callVM(SetDenseOrUnboxedArrayElementInfo, ins);
+ callVM(SetDenseElementInfo, ins);
restoreLive(ins);
masm.jump(ool->rejoin());
@@ -8568,29 +8379,6 @@ CodeGenerator::visitStoreUnboxedPointer(LStoreUnboxedPointer* lir)
}
}
-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");
-
-void
-CodeGenerator::visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir)
-{
- Register object = ToRegister(lir->getOperand(0));
-
- OutOfLineCode* ool = oolCallVM(lir->mir()->group()->unboxedLayoutDontCheckGeneration().isArray()
- ? ConvertUnboxedArrayObjectToNativeInfo
- : ConvertUnboxedPlainObjectToNativeInfo,
- lir, ArgList(object), StoreNothing());
-
- masm.branchPtr(Assembler::Equal, Address(object, JSObject::offsetOfGroup()),
- ImmGCPtr(lir->mir()->group()), ool->entry());
- masm.bind(ool->rejoin());
-}
-
typedef bool (*ArrayPopShiftFn)(JSContext*, HandleObject, MutableHandleValue);
static const VMFunction ArrayPopDenseInfo =
FunctionInfo<ArrayPopShiftFn>(jit::ArrayPopDense, "ArrayPopDense");
@@ -8615,20 +8403,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
@@ -8640,13 +8419,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);
@@ -8658,41 +8434,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.
@@ -8731,7 +8491,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");
@@ -8742,50 +8502,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());
+ // Load elements and length.
+ masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
+ masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
- // Guard length < capacity.
- Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
- masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
+ // Guard length == initializedLength.
+ Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
+ masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
- // 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 < capacity.
+ Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
+ masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
- // Guard length == initializedLength.
- Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
- masm.branch32(Assembler::NotEqual, lengthAddr, 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());
}
@@ -8934,11 +8671,11 @@ CodeGenerator::visitIteratorStartO(LIteratorStartO* lir)
masm.loadPtr(Address(niTemp, offsetof(NativeIterator, guard_array)), temp2);
// Compare object with the first receiver guard. The last iterator can only
- // match for native objects and unboxed objects.
+ // match for native objects.
{
Address groupAddr(temp2, offsetof(ReceiverGuard, group));
Address shapeAddr(temp2, offsetof(ReceiverGuard, shape));
- Label guardDone, shapeMismatch, noExpando;
+ Label guardDone, shapeMismatch;
masm.loadObjShape(obj, temp1);
masm.branchPtr(Assembler::NotEqual, shapeAddr, temp1, &shapeMismatch);
@@ -8950,12 +8687,6 @@ CodeGenerator::visitIteratorStartO(LIteratorStartO* lir)
masm.bind(&shapeMismatch);
masm.loadObjGroup(obj, temp1);
masm.branchPtr(Assembler::NotEqual, groupAddr, temp1, ool->entry());
- masm.loadPtr(Address(obj, UnboxedPlainObject::offsetOfExpando()), temp1);
- masm.branchTestPtr(Assembler::Zero, temp1, temp1, &noExpando);
- branchIfNotEmptyObjectElements(temp1, ool->entry());
- masm.loadObjShape(temp1, temp1);
- masm.bind(&noExpando);
- masm.branchPtr(Assembler::NotEqual, shapeAddr, temp1, ool->entry());
masm.bind(&guardDone);
}
@@ -10590,22 +10321,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.
@@ -10983,7 +10703,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);
@@ -10996,7 +10716,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 b226f6cc9..b5f170d84 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -148,8 +148,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir);
void visitGuardObjectIdentity(LGuardObjectIdentity* guard);
void visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir);
- void visitGuardUnboxedExpando(LGuardUnboxedExpando* lir);
- void visitLoadUnboxedExpando(LLoadUnboxedExpando* lir);
void visitTypeBarrierV(LTypeBarrierV* lir);
void visitTypeBarrierO(LTypeBarrierO* lir);
void visitMonitorTypes(LMonitorTypes* lir);
@@ -236,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);
@@ -310,7 +304,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitFallibleStoreElementV(LFallibleStoreElementV* lir);
void visitFallibleStoreElementT(LFallibleStoreElementT* lir);
void visitStoreUnboxedPointer(LStoreUnboxedPointer* lir);
- void visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir);
void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj,
Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
void visitArrayPopShiftV(LArrayPopShiftV* lir);
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index d255c32a8..41c71c9c3 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -3515,8 +3515,6 @@ PassthroughOperand(MDefinition* def)
return def->toConvertElementsToDoubles()->elements();
if (def->isMaybeCopyElementsForWrite())
return def->toMaybeCopyElementsForWrite()->object();
- if (def->isConvertUnboxedObjectToNative())
- return def->toConvertUnboxedObjectToNative()->object();
return nullptr;
}
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 54d05cac4..a54a58add 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -32,7 +32,6 @@
#include "vm/EnvironmentObject-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/ObjectGroup-inl.h"
-#include "vm/UnboxedObject-inl.h"
using namespace js;
using namespace js::jit;
@@ -2219,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;
}
@@ -6392,7 +6393,7 @@ IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
JSObject* templateObject = inspector->getTemplateObject(pc);
if (!templateObject)
return nullptr;
- if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
+ if (!templateObject->is<PlainObject>())
return nullptr;
if (templateObject->staticPrototype() != proto)
return nullptr;
@@ -6429,7 +6430,7 @@ IonBuilder::createThisScriptedBaseline(MDefinition* callee)
JSObject* templateObject = inspector->getTemplateObject(pc);
if (!templateObject)
return nullptr;
- if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
+ if (!templateObject->is<PlainObject>())
return nullptr;
Shape* shape = target->lookupPure(compartment->runtime()->names().prototype);
@@ -7337,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 =
@@ -7598,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() ||
@@ -7609,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;
@@ -7634,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;
@@ -7718,8 +7692,6 @@ IonBuilder::jsop_initprop(PropertyName* name)
if (templateObject->is<PlainObject>()) {
if (!templateObject->as<PlainObject>().containsPure(name))
useSlowPath = true;
- } else {
- MOZ_ASSERT(templateObject->as<UnboxedPlainObject>().layout().lookup(name));
}
} else {
useSlowPath = true;
@@ -8178,9 +8150,7 @@ IonBuilder::maybeMarkEmpty(MDefinition* ins)
static bool
ClassHasEffectlessLookup(const Class* clasp)
{
- return (clasp == &UnboxedPlainObject::class_) ||
- (clasp == &UnboxedArrayObject::class_) ||
- IsTypedObjectClass(clasp) ||
+ return IsTypedObjectClass(clasp) ||
(clasp->isNative() && !clasp->getOpsLookupProperty());
}
@@ -9012,8 +8982,6 @@ IonBuilder::jsop_getelem()
}
obj = maybeUnboxForPropertyAccess(obj);
- if (obj->type() == MIRType::Object)
- obj = convertUnboxedObjects(obj);
bool emitted = false;
@@ -9458,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
@@ -9480,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();
@@ -9832,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);
@@ -9856,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.
@@ -9865,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.
@@ -9887,7 +9852,6 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
}
bool loadDouble =
- unboxedType == JSVAL_TYPE_MAGIC &&
barrier == BarrierKind::NoBarrier &&
loopDepth_ &&
inBounds &&
@@ -9906,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
@@ -9927,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);
}
@@ -10137,7 +10095,7 @@ IonBuilder::jsop_setelem()
MDefinition* value = current->pop();
MDefinition* index = current->pop();
- MDefinition* object = convertUnboxedObjects(current->pop());
+ MDefinition* object = current->pop();
trackTypeInfo(TrackedTypeSite::Receiver, object->type(), object->resultTypeSet());
trackTypeInfo(TrackedTypeSite::Index, index->type(), index->resultTypeSet());
@@ -10375,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,
@@ -10414,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) {
@@ -10504,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
@@ -10540,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.
@@ -10577,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;
@@ -10589,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);
}
@@ -10727,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()) {
@@ -10972,11 +10909,8 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
}
// Definite slots will always be fixed slots when they are in the
- // allowable range for fixed slots, except for objects which were
- // converted from unboxed objects and have a smaller allocation size.
+ // allowable range for fixed slots.
size_t nfixed = NativeObject::MAX_FIXED_SLOTS;
- if (ObjectGroup* group = key->group()->maybeOriginalUnboxedGroup())
- nfixed = gc::GetGCKindSlots(group->unboxedLayout().getAllocKind());
uint32_t propertySlot = property.maybeTypes()->definiteSlot();
if (slot == UINT32_MAX) {
@@ -10991,65 +10925,6 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
return slot;
}
-uint32_t
-IonBuilder::getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name, JSValueType* punboxedType)
-{
- if (!types || types->unknownObject() || !types->objectOrSentinel()) {
- trackOptimizationOutcome(TrackedOutcome::NoTypeInfo);
- return UINT32_MAX;
- }
-
- uint32_t offset = UINT32_MAX;
-
- for (size_t i = 0; i < types->getObjectCount(); i++) {
- TypeSet::ObjectKey* key = types->getObject(i);
- if (!key)
- continue;
-
- if (key->unknownProperties()) {
- trackOptimizationOutcome(TrackedOutcome::UnknownProperties);
- return UINT32_MAX;
- }
-
- if (key->isSingleton()) {
- trackOptimizationOutcome(TrackedOutcome::Singleton);
- return UINT32_MAX;
- }
-
- UnboxedLayout* layout = key->group()->maybeUnboxedLayout();
- if (!layout) {
- trackOptimizationOutcome(TrackedOutcome::NotUnboxed);
- return UINT32_MAX;
- }
-
- const UnboxedLayout::Property* property = layout->lookup(name);
- if (!property) {
- trackOptimizationOutcome(TrackedOutcome::StructNoField);
- return UINT32_MAX;
- }
-
- if (layout->nativeGroup()) {
- trackOptimizationOutcome(TrackedOutcome::UnboxedConvertedToNative);
- return UINT32_MAX;
- }
-
- key->watchStateChangeForUnboxedConvertedToNative(constraints());
-
- if (offset == UINT32_MAX) {
- offset = property->offset;
- *punboxedType = property->type;
- } else if (offset != property->offset) {
- trackOptimizationOutcome(TrackedOutcome::InconsistentFieldOffset);
- return UINT32_MAX;
- } else if (*punboxedType != property->type) {
- trackOptimizationOutcome(TrackedOutcome::InconsistentFieldType);
- return UINT32_MAX;
- }
- }
-
- return offset;
-}
-
bool
IonBuilder::jsop_runonce()
{
@@ -11496,8 +11371,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
}
obj = maybeUnboxForPropertyAccess(obj);
- if (obj->type() == MIRType::Object)
- obj = convertUnboxedObjects(obj);
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
obj, name, types);
@@ -11569,11 +11442,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
if (!getPropTryDefiniteSlot(&emitted, obj, name, barrier, types) || emitted)
return emitted;
- // Try to emit loads from unboxed objects.
- trackOptimizationAttempt(TrackedStrategy::GetProp_Unboxed);
- if (!getPropTryUnboxed(&emitted, obj, name, barrier, types) || emitted)
- return emitted;
-
// Try to inline a common property getter, or make a call.
trackOptimizationAttempt(TrackedStrategy::GetProp_CommonGetter);
if (!getPropTryCommonGetter(&emitted, obj, name, types) || emitted)
@@ -11939,49 +11807,6 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool* emitted,
fieldPrediction, fieldTypeObj);
}
-MDefinition*
-IonBuilder::convertUnboxedObjects(MDefinition* obj)
-{
- // If obj might be in any particular unboxed group which should be
- // converted to a native representation, perform that conversion. This does
- // not guarantee the object will not have such a group afterwards, if the
- // object's possible groups are not precisely known.
- TemporaryTypeSet* types = obj->resultTypeSet();
- if (!types || types->unknownObject() || !types->objectOrSentinel())
- return obj;
-
- BaselineInspector::ObjectGroupVector list(alloc());
- for (size_t i = 0; i < types->getObjectCount(); i++) {
- TypeSet::ObjectKey* key = obj->resultTypeSet()->getObject(i);
- if (!key || !key->isGroup())
- continue;
-
- if (UnboxedLayout* layout = key->group()->maybeUnboxedLayout()) {
- AutoEnterOOMUnsafeRegion oomUnsafe;
- if (layout->nativeGroup() && !list.append(key->group()))
- oomUnsafe.crash("IonBuilder::convertUnboxedObjects");
- }
- }
-
- return convertUnboxedObjects(obj, list);
-}
-
-MDefinition*
-IonBuilder::convertUnboxedObjects(MDefinition* obj,
- const BaselineInspector::ObjectGroupVector& list)
-{
- for (size_t i = 0; i < list.length(); i++) {
- ObjectGroup* group = list[i];
- if (TemporaryTypeSet* types = obj->resultTypeSet()) {
- if (!types->hasType(TypeSet::ObjectType(group)))
- continue;
- }
- obj = MConvertUnboxedObjectToNative::New(alloc(), obj, group);
- current->add(obj->toInstruction());
- }
- return obj;
-}
-
bool
IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types)
@@ -12066,111 +11891,14 @@ IonBuilder::getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyN
return true;
}
-MInstruction*
-IonBuilder::loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
- BarrierKind barrier, TemporaryTypeSet* types)
-{
- // loadUnboxedValue is designed to load any value as if it were contained in
- // an array. Thus a property offset is converted to an index, when the
- // object is reinterpreted as an array of properties of the same size.
- size_t index = offset / UnboxedTypeSize(unboxedType);
- MInstruction* indexConstant = MConstant::New(alloc(), Int32Value(index));
- current->add(indexConstant);
-
- return loadUnboxedValue(obj, UnboxedPlainObject::offsetOfData(),
- indexConstant, unboxedType, barrier, types);
-}
-
-MInstruction*
-IonBuilder::loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
- MDefinition* index, JSValueType unboxedType,
- BarrierKind barrier, TemporaryTypeSet* types)
-{
- MInstruction* load;
- switch (unboxedType) {
- case JSVAL_TYPE_BOOLEAN:
- load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Uint8,
- DoesNotRequireMemoryBarrier, elementsOffset);
- load->setResultType(MIRType::Boolean);
- break;
-
- case JSVAL_TYPE_INT32:
- load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Int32,
- DoesNotRequireMemoryBarrier, elementsOffset);
- load->setResultType(MIRType::Int32);
- break;
-
- case JSVAL_TYPE_DOUBLE:
- load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Float64,
- DoesNotRequireMemoryBarrier, elementsOffset,
- /* canonicalizeDoubles = */ false);
- load->setResultType(MIRType::Double);
- break;
-
- case JSVAL_TYPE_STRING:
- load = MLoadUnboxedString::New(alloc(), elements, index, elementsOffset);
- break;
-
- case JSVAL_TYPE_OBJECT: {
- MLoadUnboxedObjectOrNull::NullBehavior nullBehavior;
- if (types->hasType(TypeSet::NullType()))
- nullBehavior = MLoadUnboxedObjectOrNull::HandleNull;
- else if (barrier != BarrierKind::NoBarrier)
- nullBehavior = MLoadUnboxedObjectOrNull::BailOnNull;
- else
- nullBehavior = MLoadUnboxedObjectOrNull::NullNotPossible;
- load = MLoadUnboxedObjectOrNull::New(alloc(), elements, index, nullBehavior,
- elementsOffset);
- break;
- }
-
- default:
- MOZ_CRASH();
- }
-
- current->add(load);
- return load;
-}
-
-bool
-IonBuilder::getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
- BarrierKind barrier, TemporaryTypeSet* types)
-{
- MOZ_ASSERT(*emitted == false);
-
- JSValueType unboxedType;
- uint32_t offset = getUnboxedOffset(obj->resultTypeSet(), name, &unboxedType);
- if (offset == UINT32_MAX)
- return true;
-
- if (obj->type() != MIRType::Object) {
- MGuardObject* guard = MGuardObject::New(alloc(), obj);
- current->add(guard);
- obj = guard;
- }
-
- MInstruction* load = loadUnboxedProperty(obj, offset, unboxedType, barrier, types);
- current->push(load);
-
- if (!pushTypeBarrier(load, types, barrier))
- return false;
-
- trackOptimizationSuccess();
- *emitted = true;
- return true;
-}
-
MDefinition*
IonBuilder::addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
const BaselineInspector::ReceiverVector& receivers,
- const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
bool isOwnProperty)
{
MOZ_ASSERT(holder);
MOZ_ASSERT(holderShape);
- obj = convertUnboxedObjects(obj, convertUnboxedGroups);
-
if (isOwnProperty) {
MOZ_ASSERT(receivers.empty());
return addShapeGuard(obj, holderShape, Bailout_ShapeGuard);
@@ -12194,10 +11922,8 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
JSObject* foundProto = nullptr;
bool isOwnProperty = false;
BaselineInspector::ReceiverVector receivers(alloc());
- BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
if (!inspector->commonGetPropFunction(pc, &foundProto, &lastProperty, &commonGetter,
- &globalShape, &isOwnProperty,
- receivers, convertUnboxedGroups))
+ &globalShape, &isOwnProperty, receivers))
{
return true;
}
@@ -12213,8 +11939,7 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
// If type information is bad, we can still optimize the getter if we
// shape guard.
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
- receivers, convertUnboxedGroups,
- isOwnProperty);
+ receivers, isOwnProperty);
if (!obj)
return false;
}
@@ -12381,15 +12106,12 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
MOZ_ASSERT(*emitted == false);
BaselineInspector::ReceiverVector receivers(alloc());
- BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
- if (!inspector->maybeInfoForPropertyOp(pc, receivers, convertUnboxedGroups))
+ if (!inspector->maybeInfoForPropertyOp(pc, receivers))
return false;
if (!canInlinePropertyOpShapes(receivers))
return true;
- obj = convertUnboxedObjects(obj, convertUnboxedGroups);
-
MIRType rvalType = types->getKnownMIRType();
if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
rvalType = MIRType::Value;
@@ -12412,45 +12134,6 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
return true;
}
- if (receivers[0].shape) {
- // Monomorphic load from an unboxed object expando.
- spew("Inlining monomorphic unboxed expando GETPROP");
-
- obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
- obj = addUnboxedExpandoGuard(obj, /* hasExpando = */ true, Bailout_ShapeGuard);
-
- MInstruction* expando = MLoadUnboxedExpando::New(alloc(), obj);
- current->add(expando);
-
- expando = addShapeGuard(expando, receivers[0].shape, Bailout_ShapeGuard);
-
- Shape* shape = receivers[0].shape->searchLinear(NameToId(name));
- MOZ_ASSERT(shape);
-
- if (!loadSlot(expando, shape, rvalType, barrier, types))
- return false;
-
- trackOptimizationOutcome(TrackedOutcome::Monomorphic);
- *emitted = true;
- return true;
- }
-
- // Monomorphic load from an unboxed object.
- ObjectGroup* group = receivers[0].group;
- if (obj->resultTypeSet() && !obj->resultTypeSet()->hasType(TypeSet::ObjectType(group)))
- return true;
-
- obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
-
- const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
- MInstruction* load = loadUnboxedProperty(obj, property->offset, property->type, barrier, types);
- current->push(load);
-
- if (!pushTypeBarrier(load, types, barrier))
- return false;
-
- trackOptimizationOutcome(TrackedOutcome::Monomorphic);
- *emitted = true;
return true;
}
@@ -12692,7 +12375,7 @@ bool
IonBuilder::jsop_setprop(PropertyName* name)
{
MDefinition* value = current->pop();
- MDefinition* obj = convertUnboxedObjects(current->pop());
+ MDefinition* obj = current->pop();
bool emitted = false;
startTrackingOptimizations();
@@ -12725,13 +12408,6 @@ IonBuilder::jsop_setprop(PropertyName* name)
bool barrier = PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &obj, name, &value,
/* canModify = */ true);
- if (!forceInlineCaches()) {
- // Try to emit stores to unboxed objects.
- trackOptimizationAttempt(TrackedStrategy::SetProp_Unboxed);
- if (!setPropTryUnboxed(&emitted, obj, name, value, barrier, objTypes) || emitted)
- return emitted;
- }
-
// Add post barrier if needed. The instructions above manage any post
// barriers they need directly.
if (NeedsPostBarrier(value))
@@ -12765,10 +12441,8 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
JSObject* foundProto = nullptr;
bool isOwnProperty;
BaselineInspector::ReceiverVector receivers(alloc());
- BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
if (!inspector->commonSetPropFunction(pc, &foundProto, &lastProperty, &commonSetter,
- &isOwnProperty,
- receivers, convertUnboxedGroups))
+ &isOwnProperty, receivers))
{
trackOptimizationOutcome(TrackedOutcome::NoProtoFound);
return true;
@@ -12783,8 +12457,7 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
// If type information is bad, we can still optimize the setter if we
// shape guard.
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
- receivers, convertUnboxedGroups,
- isOwnProperty);
+ receivers, isOwnProperty);
if (!obj)
return false;
}
@@ -13039,100 +12712,6 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
return true;
}
-MInstruction*
-IonBuilder::storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
- MDefinition* value)
-{
- size_t scaledOffsetConstant = offset / UnboxedTypeSize(unboxedType);
- MInstruction* scaledOffset = MConstant::New(alloc(), Int32Value(scaledOffsetConstant));
- current->add(scaledOffset);
-
- return storeUnboxedValue(obj, obj, UnboxedPlainObject::offsetOfData(),
- scaledOffset, unboxedType, value);
-}
-
-MInstruction*
-IonBuilder::storeUnboxedValue(MDefinition* obj, MDefinition* elements, int32_t elementsOffset,
- MDefinition* scaledOffset, JSValueType unboxedType,
- MDefinition* value, bool preBarrier /* = true */)
-{
- MInstruction* store;
- switch (unboxedType) {
- case JSVAL_TYPE_BOOLEAN:
- store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Uint8,
- MStoreUnboxedScalar::DontTruncateInput,
- DoesNotRequireMemoryBarrier, elementsOffset);
- break;
-
- case JSVAL_TYPE_INT32:
- store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Int32,
- MStoreUnboxedScalar::DontTruncateInput,
- DoesNotRequireMemoryBarrier, elementsOffset);
- break;
-
- case JSVAL_TYPE_DOUBLE:
- store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Float64,
- MStoreUnboxedScalar::DontTruncateInput,
- DoesNotRequireMemoryBarrier, elementsOffset);
- break;
-
- case JSVAL_TYPE_STRING:
- store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value,
- elementsOffset, preBarrier);
- break;
-
- case JSVAL_TYPE_OBJECT:
- MOZ_ASSERT(value->type() == MIRType::Object ||
- value->type() == MIRType::Null ||
- value->type() == MIRType::Value);
- MOZ_ASSERT(!value->mightBeType(MIRType::Undefined),
- "MToObjectOrNull slow path is invalid for unboxed objects");
- store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, obj,
- elementsOffset, preBarrier);
- break;
-
- default:
- MOZ_CRASH();
- }
-
- current->add(store);
- return store;
-}
-
-bool
-IonBuilder::setPropTryUnboxed(bool* emitted, MDefinition* obj,
- PropertyName* name, MDefinition* value,
- bool barrier, TemporaryTypeSet* objTypes)
-{
- MOZ_ASSERT(*emitted == false);
-
- if (barrier) {
- trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
- return true;
- }
-
- JSValueType unboxedType;
- uint32_t offset = getUnboxedOffset(obj->resultTypeSet(), name, &unboxedType);
- if (offset == UINT32_MAX)
- return true;
-
- if (obj->type() != MIRType::Object) {
- MGuardObject* guard = MGuardObject::New(alloc(), obj);
- current->add(guard);
- obj = guard;
- }
-
- MInstruction* store = storeUnboxedProperty(obj, offset, unboxedType, value);
-
- current->push(value);
-
- if (!resumeAfter(store))
- return false;
-
- *emitted = true;
- return true;
-}
-
bool
IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
PropertyName* name, MDefinition* value,
@@ -13146,15 +12725,12 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
}
BaselineInspector::ReceiverVector receivers(alloc());
- BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
- if (!inspector->maybeInfoForPropertyOp(pc, receivers, convertUnboxedGroups))
+ if (!inspector->maybeInfoForPropertyOp(pc, receivers))
return false;
if (!canInlinePropertyOpShapes(receivers))
return true;
- obj = convertUnboxedObjects(obj, convertUnboxedGroups);
-
if (receivers.length() == 1) {
if (!receivers[0].group) {
// Monomorphic store to a native object.
@@ -13174,46 +12750,6 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
return true;
}
- if (receivers[0].shape) {
- // Monomorphic store to an unboxed object expando.
- spew("Inlining monomorphic unboxed expando SETPROP");
-
- obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
- obj = addUnboxedExpandoGuard(obj, /* hasExpando = */ true, Bailout_ShapeGuard);
-
- MInstruction* expando = MLoadUnboxedExpando::New(alloc(), obj);
- current->add(expando);
-
- expando = addShapeGuard(expando, receivers[0].shape, Bailout_ShapeGuard);
-
- Shape* shape = receivers[0].shape->searchLinear(NameToId(name));
- MOZ_ASSERT(shape);
-
- bool needsBarrier = objTypes->propertyNeedsBarrier(constraints(), NameToId(name));
- if (!storeSlot(expando, shape, value, needsBarrier))
- return false;
-
- trackOptimizationOutcome(TrackedOutcome::Monomorphic);
- *emitted = true;
- return true;
- }
-
- // Monomorphic store to an unboxed object.
- spew("Inlining monomorphic unboxed SETPROP");
-
- ObjectGroup* group = receivers[0].group;
- if (!objTypes->hasType(TypeSet::ObjectType(group)))
- return true;
-
- obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
-
- const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
- storeUnboxedProperty(obj, property->offset, property->type, value);
-
- current->push(value);
-
- trackOptimizationOutcome(TrackedOutcome::Monomorphic);
- *emitted = true;
return true;
}
@@ -13884,7 +13420,7 @@ IonBuilder::jsop_setaliasedvar(EnvironmentCoordinate ec)
bool
IonBuilder::jsop_in()
{
- MDefinition* obj = convertUnboxedObjects(current->pop());
+ MDefinition* obj = current->pop();
MDefinition* id = current->pop();
bool emitted = false;
@@ -13911,11 +13447,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;
@@ -13930,10 +13463,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_) {
@@ -13943,8 +13476,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);
@@ -14241,19 +13773,6 @@ IonBuilder::addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bail
}
MInstruction*
-IonBuilder::addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind)
-{
- MGuardUnboxedExpando* guard = MGuardUnboxedExpando::New(alloc(), obj, hasExpando, bailoutKind);
- current->add(guard);
-
- // If a shape guard failed in the past, don't optimize group guards.
- if (failedShapeGuard_)
- guard->setNotMovable();
-
- return guard;
-}
-
-MInstruction*
IonBuilder::addGuardReceiverPolymorphic(MDefinition* obj,
const BaselineInspector::ReceiverVector& receivers)
{
@@ -14262,15 +13781,6 @@ IonBuilder::addGuardReceiverPolymorphic(MDefinition* obj,
// Monomorphic guard on a native object.
return addShapeGuard(obj, receivers[0].shape, Bailout_ShapeGuard);
}
-
- if (!receivers[0].shape) {
- // Guard on an unboxed object that does not have an expando.
- obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
- return addUnboxedExpandoGuard(obj, /* hasExpando = */ false, Bailout_ShapeGuard);
- }
-
- // Monomorphic receiver guards are not yet supported when the receiver
- // is an unboxed object with an expando.
}
MGuardReceiverPolymorphic* guard = MGuardReceiverPolymorphic::New(alloc(), obj);
@@ -14644,32 +14154,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 f24ef30c8..dd40b4bd6 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);
@@ -401,7 +400,6 @@ class IonBuilder
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
- MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
MInstruction*
@@ -441,8 +439,6 @@ class IonBuilder
BarrierKind barrier, TemporaryTypeSet* types);
MOZ_MUST_USE bool getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyName* name,
BarrierKind barrier, TemporaryTypeSet* types);
- MOZ_MUST_USE bool getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
- BarrierKind barrier, TemporaryTypeSet* types);
MOZ_MUST_USE bool getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
TemporaryTypeSet* types);
MOZ_MUST_USE bool getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
@@ -475,9 +471,6 @@ class IonBuilder
MOZ_MUST_USE bool setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
PropertyName* name, MDefinition* value,
bool barrier, TemporaryTypeSet* objTypes);
- MOZ_MUST_USE bool setPropTryUnboxed(bool* emitted, MDefinition* obj,
- PropertyName* name, MDefinition* value,
- bool barrier, TemporaryTypeSet* objTypes);
MOZ_MUST_USE bool setPropTryInlineAccess(bool* emitted, MDefinition* obj,
PropertyName* name, MDefinition* value,
bool barrier, TemporaryTypeSet* objTypes);
@@ -617,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.
@@ -729,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);
@@ -1041,7 +1031,6 @@ class IonBuilder
MDefinition*
addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
const BaselineInspector::ReceiverVector& receivers,
- const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
bool isOwnProperty);
MOZ_MUST_USE bool annotateGetPropertyCache(MDefinition* obj, PropertyName* name,
@@ -1059,22 +1048,6 @@ class IonBuilder
ResultWithOOM<bool> testNotDefinedProperty(MDefinition* obj, jsid id);
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
- MDefinition* convertUnboxedObjects(MDefinition* obj);
- MDefinition* convertUnboxedObjects(MDefinition* obj,
- const BaselineInspector::ObjectGroupVector& list);
- uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
- JSValueType* punboxedType);
- MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
- BarrierKind barrier, TemporaryTypeSet* types);
- MInstruction* loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
- MDefinition* scaledOffset, JSValueType unboxedType,
- BarrierKind barrier, TemporaryTypeSet* types);
- MInstruction* storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
- MDefinition* value);
- MInstruction* storeUnboxedValue(MDefinition* obj,
- MDefinition* elements, int32_t elementsOffset,
- MDefinition* scaledOffset, JSValueType unboxedType,
- MDefinition* value, bool preBarrier = true);
MOZ_MUST_USE bool checkPreliminaryGroups(MDefinition *obj);
MOZ_MUST_USE bool freezePropTypeSets(TemporaryTypeSet* types,
JSObject* foundProto, PropertyName* name);
diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp
index 96e488ea8..9901bdd07 100644
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -619,29 +619,7 @@ TestMatchingReceiver(MacroAssembler& masm, IonCache::StubAttacher& attacher,
Register object, JSObject* obj, Label* failure,
bool alwaysCheckGroup = false)
{
- if (obj->is<UnboxedPlainObject>()) {
- MOZ_ASSERT(failure);
-
- masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
- Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
- if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
- masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failure);
- Label success;
- masm.push(object);
- masm.loadPtr(expandoAddress, object);
- masm.branchTestObjShape(Assembler::Equal, object, expando->lastProperty(),
- &success);
- masm.pop(object);
- masm.jump(failure);
- masm.bind(&success);
- masm.pop(object);
- } 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>()) {
+ if (obj->is<TypedObject>()) {
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
Address(object, JSObject::offsetOfGroup()),
ImmGCPtr(obj->group()), failure);
@@ -758,7 +736,6 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
// jump directly. Otherwise, jump to the end of the stub, so there's a
// common point to patch.
bool multipleFailureJumps = (obj != holder)
- || obj->is<UnboxedPlainObject>()
|| (checkTDZ && output.hasValue())
|| (failures != nullptr && failures->used());
@@ -777,7 +754,6 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
Register scratchReg = Register::FromCode(0); // Quell compiler warning.
if (obj != holder ||
- obj->is<UnboxedPlainObject>() ||
!holder->as<NativeObject>().isFixedSlot(shape->slot()))
{
if (output.hasValue()) {
@@ -838,10 +814,6 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
holderReg = InvalidReg;
}
- } else if (obj->is<UnboxedPlainObject>()) {
- holder = obj->as<UnboxedPlainObject>().maybeExpando();
- holderReg = scratchReg;
- masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), holderReg);
} else {
holderReg = object;
}
@@ -869,30 +841,6 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
attacher.jumpNextStub(masm);
}
-static void
-GenerateReadUnboxed(JSContext* cx, IonScript* ion, MacroAssembler& masm,
- IonCache::StubAttacher& attacher, JSObject* obj,
- const UnboxedLayout::Property* property,
- Register object, TypedOrValueRegister output,
- Label* failures = nullptr)
-{
- // Guard on the group of the object.
- attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
- Address(object, JSObject::offsetOfGroup()),
- ImmGCPtr(obj->group()), failures);
-
- Address address(object, UnboxedPlainObject::offsetOfData() + property->offset);
-
- masm.loadUnboxedProperty(address, property->type, output);
-
- attacher.jumpRejoin(masm);
-
- if (failures) {
- masm.bind(failures);
- attacher.jumpNextStub(masm);
- }
-}
-
static bool
EmitGetterCall(JSContext* cx, MacroAssembler& masm,
IonCache::StubAttacher& attacher, JSObject* obj,
@@ -1187,39 +1135,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.
@@ -1533,101 +1448,6 @@ GetPropertyIC::tryAttachNative(JSContext* cx, HandleScript outerScript, IonScrip
}
bool
-GetPropertyIC::tryAttachUnboxed(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<UnboxedPlainObject>())
- return true;
- const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
- if (!property)
- return true;
-
- *emitted = true;
-
- MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
-
- Label failures;
- emitIdGuard(masm, id, &failures);
- Label* maybeFailures = failures.used() ? &failures : nullptr;
-
- StubAttacher attacher(*this);
- GenerateReadUnboxed(cx, ion, masm, attacher, obj, property, object(), output(), maybeFailures);
- return linkAndAttachStub(cx, masm, attacher, ion, "read unboxed",
- JS::TrackedOutcome::ICGetPropStub_UnboxedRead);
-}
-
-bool
-GetPropertyIC::tryAttachUnboxedExpando(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<UnboxedPlainObject>())
- return true;
- Rooted<UnboxedExpandoObject*> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
- if (!expando)
- return true;
-
- Shape* shape = expando->lookup(cx, id);
- if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
- return true;
-
- *emitted = true;
-
- MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
-
- Label failures;
- emitIdGuard(masm, id, &failures);
- Label* maybeFailures = failures.used() ? &failures : nullptr;
-
- StubAttacher attacher(*this);
- GenerateReadSlot(cx, ion, masm, attacher, DontCheckTDZ, obj, obj,
- shape, object(), output(), maybeFailures);
- return linkAndAttachStub(cx, masm, attacher, ion, "read unboxed expando",
- JS::TrackedOutcome::ICGetPropStub_UnboxedReadExpando);
-}
-
-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)
{
@@ -2196,15 +2016,6 @@ GetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript*
if (!*emitted && !tryAttachNative(cx, outerScript, ion, obj, id, returnAddr, emitted))
return false;
- if (!*emitted && !tryAttachUnboxed(cx, outerScript, ion, obj, id, returnAddr, emitted))
- return false;
-
- 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;
}
@@ -2383,12 +2194,6 @@ GenerateSetSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
NativeObject::slotsSizeMustNotOverflow();
- if (obj->is<UnboxedPlainObject>()) {
- obj = obj->as<UnboxedPlainObject>().maybeExpando();
- masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), tempReg);
- object = tempReg;
- }
-
if (obj->as<NativeObject>().isFixedSlot(shape->slot())) {
Address addr(object, NativeObject::getFixedSlotOffset(shape->slot()));
@@ -3026,23 +2831,13 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
masm.branchTestObjGroup(Assembler::NotEqual, object, oldGroup, failures);
if (obj->maybeShape()) {
masm.branchTestObjShape(Assembler::NotEqual, object, oldShape, failures);
- } else {
- MOZ_ASSERT(obj->is<UnboxedPlainObject>());
-
- Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
- masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failures);
-
- masm.loadPtr(expandoAddress, tempReg);
- masm.branchTestObjShape(Assembler::NotEqual, tempReg, oldShape, failures);
}
Shape* newShape = obj->maybeShape();
- if (!newShape)
- newShape = obj->as<UnboxedPlainObject>().maybeExpando()->lastProperty();
// Guard that the incoming value is in the type set for the property
// if a type barrier is required.
- if (checkTypeset)
+ if (newShape && checkTypeset)
CheckTypeSetForWrite(masm, obj, newShape->propid(), tempReg, value, failures);
// Guard shapes along prototype chain.
@@ -3063,9 +2858,7 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
}
// Call a stub to (re)allocate dynamic slots, if necessary.
- uint32_t newNumDynamicSlots = obj->is<UnboxedPlainObject>()
- ? obj->as<UnboxedPlainObject>().maybeExpando()->numDynamicSlots()
- : obj->as<NativeObject>().numDynamicSlots();
+ uint32_t newNumDynamicSlots = obj->as<NativeObject>().numDynamicSlots();
if (NativeObject::dynamicSlotsCount(oldShape) != newNumDynamicSlots) {
AllocatableRegisterSet regs(RegisterSet::Volatile());
LiveRegisterSet save(regs.asLiveSet());
@@ -3076,12 +2869,6 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
Register temp1 = regs.takeAnyGeneral();
Register temp2 = regs.takeAnyGeneral();
- if (obj->is<UnboxedPlainObject>()) {
- // Pass the expando object to the stub.
- masm.Push(object);
- masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), object);
- }
-
masm.setupUnalignedABICall(temp1);
masm.loadJSContext(temp1);
masm.passABIArg(temp1);
@@ -3098,27 +2885,16 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
masm.jump(&allocDone);
masm.bind(&allocFailed);
- if (obj->is<UnboxedPlainObject>())
- masm.Pop(object);
masm.PopRegsInMask(save);
masm.jump(failures);
masm.bind(&allocDone);
masm.setFramePushed(framePushedAfterCall);
- if (obj->is<UnboxedPlainObject>())
- masm.Pop(object);
masm.PopRegsInMask(save);
}
bool popObject = false;
- if (obj->is<UnboxedPlainObject>()) {
- masm.push(object);
- popObject = true;
- obj = obj->as<UnboxedPlainObject>().maybeExpando();
- masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), object);
- }
-
// Write the object or expando object's new shape.
Address shapeAddr(object, ShapedObject::offsetOfShape());
if (cx->zone()->needsIncrementalBarrier())
@@ -3126,8 +2902,6 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
masm.storePtr(ImmGCPtr(newShape), shapeAddr);
if (oldGroup != obj->group()) {
- MOZ_ASSERT(!obj->is<UnboxedPlainObject>());
-
// Changing object's group from a partially to fully initialized group,
// per the acquired properties analysis. Only change the group if the
// old group still has a newScript.
@@ -3370,141 +3144,6 @@ CanAttachNativeSetProp(JSContext* cx, HandleObject obj, HandleId id, const Const
return SetPropertyIC::CanAttachNone;
}
-static void
-GenerateSetUnboxed(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
- JSObject* obj, jsid id, uint32_t unboxedOffset, JSValueType unboxedType,
- Register object, Register tempReg, const ConstantOrRegister& value,
- bool checkTypeset, Label* failures)
-{
- // Guard on the type of the object.
- masm.branchPtr(Assembler::NotEqual,
- Address(object, JSObject::offsetOfGroup()),
- ImmGCPtr(obj->group()), failures);
-
- if (checkTypeset)
- CheckTypeSetForWrite(masm, obj, id, tempReg, value, failures);
-
- Address address(object, UnboxedPlainObject::offsetOfData() + unboxedOffset);
-
- if (cx->zone()->needsIncrementalBarrier()) {
- if (unboxedType == JSVAL_TYPE_OBJECT)
- masm.callPreBarrier(address, MIRType::Object);
- else if (unboxedType == JSVAL_TYPE_STRING)
- masm.callPreBarrier(address, MIRType::String);
- else
- MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(unboxedType));
- }
-
- masm.storeUnboxedProperty(address, unboxedType, value, failures);
-
- attacher.jumpRejoin(masm);
-
- masm.bind(failures);
- attacher.jumpNextStub(masm);
-}
-
-static bool
-CanAttachSetUnboxed(JSContext* cx, HandleObject obj, HandleId id, const ConstantOrRegister& val,
- bool needsTypeBarrier, bool* checkTypeset,
- uint32_t* unboxedOffset, JSValueType* unboxedType)
-{
- if (!obj->is<UnboxedPlainObject>())
- return false;
-
- const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
- if (property) {
- *checkTypeset = false;
- if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
- return false;
- *unboxedOffset = property->offset;
- *unboxedType = property->type;
- return true;
- }
-
- return false;
-}
-
-static bool
-CanAttachSetUnboxedExpando(JSContext* cx, HandleObject obj, HandleId id,
- const ConstantOrRegister& val,
- bool needsTypeBarrier, bool* checkTypeset, Shape** pshape)
-{
- if (!obj->is<UnboxedPlainObject>())
- return false;
-
- Rooted<UnboxedExpandoObject*> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
- if (!expando)
- return false;
-
- Shape* shape = expando->lookupPure(id);
- if (!shape || !shape->hasDefaultSetter() || !shape->hasSlot() || !shape->writable())
- return false;
-
- *checkTypeset = false;
- if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
- return false;
-
- *pshape = shape;
- return true;
-}
-
-static bool
-CanAttachAddUnboxedExpando(JSContext* cx, HandleObject obj, HandleShape oldShape,
- HandleId id, const ConstantOrRegister& val,
- bool needsTypeBarrier, bool* checkTypeset)
-{
- if (!obj->is<UnboxedPlainObject>())
- return false;
-
- Rooted<UnboxedExpandoObject*> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
- if (!expando || expando->inDictionaryMode())
- return false;
-
- Shape* newShape = expando->lastProperty();
- if (newShape->isEmptyShape() || newShape->propid() != id || newShape->previous() != oldShape)
- return false;
-
- MOZ_ASSERT(newShape->hasDefaultSetter() && newShape->hasSlot() && newShape->writable());
-
- if (PrototypeChainShadowsPropertyAdd(cx, obj, id))
- return false;
-
- *checkTypeset = false;
- if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
- return false;
-
- return true;
-}
-
-bool
-SetPropertyIC::tryAttachUnboxed(JSContext* cx, HandleScript outerScript, IonScript* ion,
- HandleObject obj, HandleId id, bool* emitted)
-{
- MOZ_ASSERT(!*emitted);
-
- bool checkTypeset = false;
- uint32_t unboxedOffset;
- JSValueType unboxedType;
- if (!CanAttachSetUnboxed(cx, obj, id, value(), needsTypeBarrier(), &checkTypeset,
- &unboxedOffset, &unboxedType))
- {
- return true;
- }
-
- *emitted = true;
-
- MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
- StubAttacher attacher(*this);
-
- Label failures;
- emitIdGuard(masm, id, &failures);
-
- GenerateSetUnboxed(cx, masm, attacher, obj, id, unboxedOffset, unboxedType,
- object(), temp(), value(), checkTypeset, &failures);
- return linkAndAttachStub(cx, masm, attacher, ion, "set_unboxed",
- JS::TrackedOutcome::ICSetPropStub_SetUnboxed);
-}
-
bool
SetPropertyIC::tryAttachProxy(JSContext* cx, HandleScript outerScript, IonScript* ion,
HandleObject obj, HandleId id, bool* emitted)
@@ -3586,26 +3225,6 @@ SetPropertyIC::tryAttachNative(JSContext* cx, HandleScript outerScript, IonScrip
}
bool
-SetPropertyIC::tryAttachUnboxedExpando(JSContext* cx, HandleScript outerScript, IonScript* ion,
- HandleObject obj, HandleId id, bool* emitted)
-{
- MOZ_ASSERT(!*emitted);
-
- RootedShape shape(cx);
- bool checkTypeset = false;
- if (!CanAttachSetUnboxedExpando(cx, obj, id, value(), needsTypeBarrier(),
- &checkTypeset, shape.address()))
- {
- return true;
- }
-
- if (!attachSetSlot(cx, outerScript, ion, obj, shape, checkTypeset))
- return false;
- *emitted = true;
- return true;
-}
-
-bool
SetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript* ion,
HandleObject obj, HandleValue idval, HandleValue value,
MutableHandleId id, bool* emitted, bool* tryNativeAddSlot)
@@ -3630,12 +3249,6 @@ SetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript*
if (!*emitted && !tryAttachNative(cx, outerScript, ion, obj, id, emitted, tryNativeAddSlot))
return false;
-
- if (!*emitted && !tryAttachUnboxed(cx, outerScript, ion, obj, id, emitted))
- return false;
-
- if (!*emitted && !tryAttachUnboxedExpando(cx, outerScript, ion, obj, id, emitted))
- return false;
}
if (idval.isInt32()) {
@@ -3687,16 +3300,6 @@ SetPropertyIC::tryAttachAddSlot(JSContext* cx, HandleScript outerScript, IonScri
return true;
}
- checkTypeset = false;
- if (CanAttachAddUnboxedExpando(cx, obj, oldShape, id, value(), needsTypeBarrier(),
- &checkTypeset))
- {
- if (!attachAddSlot(cx, outerScript, ion, obj, id, oldShape, oldGroup, checkTypeset))
- return false;
- *emitted = true;
- return true;
- }
-
return true;
}
@@ -3718,11 +3321,6 @@ SetPropertyIC::update(JSContext* cx, HandleScript outerScript, size_t cacheIndex
return false;
oldShape = obj->maybeShape();
- if (obj->is<UnboxedPlainObject>()) {
- MOZ_ASSERT(!oldShape);
- if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
- oldShape = expando->lastProperty();
- }
}
RootedId id(cx);
@@ -4025,7 +3623,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());
@@ -4056,13 +3654,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();
}
@@ -4139,46 +3730,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/IonCaches.h b/js/src/jit/IonCaches.h
index 173e06c6b..b00646538 100644
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -529,18 +529,6 @@ class GetPropertyIC : public IonCache
HandleObject obj, HandleId id, void* returnAddr,
bool* emitted);
- MOZ_MUST_USE bool tryAttachUnboxed(JSContext* cx, HandleScript outerScript, IonScript* ion,
- HandleObject obj, HandleId id, void* returnAddr,
- bool* emitted);
-
- MOZ_MUST_USE bool tryAttachUnboxedExpando(JSContext* cx, HandleScript outerScript,
- IonScript* ion, HandleObject obj, HandleId id,
- void* returnAddr, bool* emitted);
-
- MOZ_MUST_USE bool tryAttachUnboxedArrayLength(JSContext* cx, HandleScript outerScript,
- IonScript* ion, HandleObject obj, HandleId id,
- void* returnAddr, bool* emitted);
-
MOZ_MUST_USE bool tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript,
IonScript* ion, HandleObject obj, HandleId id,
bool* emitted);
diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
index b9a7c7b27..3f9d9db88 100644
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -221,9 +221,6 @@ DefaultJitOptions::DefaultJitOptions()
Warn(forcedRegisterAllocatorEnv, env);
}
- // Toggles whether unboxed plain objects can be created by the VM.
- SET_DEFAULT(disableUnboxedObjects, true);
-
// Test whether Atomics are allowed in asm.js code.
SET_DEFAULT(asmJSAtomicsEnable, false);
diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
index 076980b4e..719ee14d9 100644
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -91,9 +91,6 @@ struct DefaultJitOptions
mozilla::Maybe<uint32_t> forcedDefaultIonSmallFunctionWarmUpThreshold;
mozilla::Maybe<IonRegisterAllocator> forcedRegisterAllocator;
- // The options below affect the rest of the VM, and not just the JIT.
- bool disableUnboxedObjects;
-
DefaultJitOptions();
bool isSmallFunction(JSScript* script) const;
void setEagerCompilation();
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index 709de9987..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;
}
@@ -3252,14 +3214,6 @@ LIRGenerator::visitStoreUnboxedString(MStoreUnboxedString* ins)
}
void
-LIRGenerator::visitConvertUnboxedObjectToNative(MConvertUnboxedObjectToNative* ins)
-{
- LInstruction* check = new(alloc()) LConvertUnboxedObjectToNative(useRegister(ins->object()));
- add(check, ins);
- assignSafepoint(check, ins);
-}
-
-void
LIRGenerator::visitEffectiveAddress(MEffectiveAddress* ins)
{
define(new(alloc()) LEffectiveAddress(useRegister(ins->base()), useRegister(ins->index())), ins);
@@ -3777,24 +3731,6 @@ LIRGenerator::visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic* ins)
}
void
-LIRGenerator::visitGuardUnboxedExpando(MGuardUnboxedExpando* ins)
-{
- LGuardUnboxedExpando* guard =
- new(alloc()) LGuardUnboxedExpando(useRegister(ins->object()));
- assignSnapshot(guard, ins->bailoutKind());
- add(guard, ins);
- redefine(ins, ins->object());
-}
-
-void
-LIRGenerator::visitLoadUnboxedExpando(MLoadUnboxedExpando* ins)
-{
- LLoadUnboxedExpando* lir =
- new(alloc()) LLoadUnboxedExpando(useRegisterAtStart(ins->object()));
- define(lir, ins);
-}
-
-void
LIRGenerator::visitAssertRange(MAssertRange* ins)
{
MDefinition* input = ins->input();
diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
index 9b4095aec..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);
@@ -232,7 +228,6 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitFallibleStoreElement(MFallibleStoreElement* ins);
void visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins);
void visitStoreUnboxedString(MStoreUnboxedString* ins);
- void visitConvertUnboxedObjectToNative(MConvertUnboxedObjectToNative* ins);
void visitEffectiveAddress(MEffectiveAddress* ins);
void visitArrayPopShift(MArrayPopShift* ins);
void visitArrayPush(MArrayPush* ins);
@@ -256,8 +251,6 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitGuardObject(MGuardObject* ins);
void visitGuardString(MGuardString* ins);
void visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic* ins);
- void visitGuardUnboxedExpando(MGuardUnboxedExpando* ins);
- void visitLoadUnboxedExpando(MLoadUnboxedExpando* ins);
void visitPolyInlineGuard(MPolyInlineGuard* ins);
void visitAssertRange(MAssertRange* ins);
void visitCallGetProperty(MCallGetProperty* ins);
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 01755094a..359f04639 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -30,7 +30,6 @@
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/StringObject-inl.h"
-#include "vm/UnboxedObject-inl.h"
using mozilla::ArrayLength;
using mozilla::AssertedCast;
@@ -475,11 +474,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 +521,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 +536,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 +577,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));
@@ -615,34 +608,27 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
OBJECT_FLAG_LENGTH_OVERFLOW |
OBJECT_FLAG_ITERATED;
- MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
+ MDefinition* obj = callInfo.thisArg();
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
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);
return InliningStatus_NotInlined;
}
- if (ArrayPrototypeHasIndexedProperty(this, script())) {
+ // Watch out for extra indexed properties on the object or its prototype.
+ if (ElementAccessHasExtraIndexedProperty(this, obj)) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
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);
@@ -743,7 +728,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
+ MDefinition* obj = callInfo.thisArg();
MDefinition* value = callInfo.getArg(0);
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
&obj, nullptr, &value, /* canModify = */ false))
@@ -761,16 +746,10 @@ 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))
- {
- trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
- return InliningStatus_NotInlined;
- }
- if (ArrayPrototypeHasIndexedProperty(this, script())) {
+ if (ElementAccessHasExtraIndexedProperty(this, obj)) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
return InliningStatus_NotInlined;
}
@@ -782,13 +761,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 +771,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);
@@ -822,7 +793,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
+ MDefinition* obj = callInfo.thisArg();
// Ensure |this| and result are objects.
if (getInlineReturnType() != MIRType::Object)
@@ -846,24 +817,11 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
- return InliningStatus_NotInlined;
- if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
- OBJECT_FLAG_LENGTH_OVERFLOW))
- {
- trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
+ if (clasp != &ArrayObject::class_)
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())) {
+ // Watch out for indexed properties on the object or its prototype.
+ if (ElementAccessHasExtraIndexedProperty(this, obj)) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
return InliningStatus_NotInlined;
}
@@ -882,15 +840,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 +860,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 +1384,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 +1410,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 +1447,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 +1457,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;
@@ -2152,7 +2097,7 @@ IonBuilder::inlineDefineDataProperty(CallInfo& callInfo)
if (callInfo.argc() != 3)
return InliningStatus_NotInlined;
- MDefinition* obj = convertUnboxedObjects(callInfo.getArg(0));
+ MDefinition* obj = callInfo.getArg(0);
MDefinition* id = callInfo.getArg(1);
MDefinition* value = callInfo.getArg(2);
diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp
index 287b87582..fa9cc3019 100644
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -4810,67 +4810,31 @@ MBeta::printOpcode(GenericPrinter& out) const
bool
MCreateThisWithTemplate::canRecoverOnBailout() const
{
- MOZ_ASSERT(templateObject()->is<PlainObject>() || templateObject()->is<UnboxedPlainObject>());
- MOZ_ASSERT_IF(templateObject()->is<PlainObject>(),
- !templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
- return true;
-}
-
-bool
-OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject)
-{
- const UnboxedLayout& layout =
- templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
-
- const UnboxedLayout::PropertyVector& properties = layout.properties();
- MOZ_ASSERT(properties.length() < 255);
-
- // Allocate an array of indexes, where the top of each field correspond to
- // the index of the operand in the MObjectState instance.
- if (!map.init(alloc, layout.size()))
- return false;
-
- // Reset all indexes to 0, which is an error code.
- for (size_t i = 0; i < map.length(); i++)
- map[i] = 0;
-
- // Map the property offsets to the indexes of MObjectState operands.
- uint8_t index = 1;
- for (size_t i = 0; i < properties.length(); i++, index++)
- map[properties[i].offset] = index;
-
+ MOZ_ASSERT(templateObject()->is<PlainObject>());
+ MOZ_ASSERT(!templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
return true;
}
MObjectState::MObjectState(MObjectState* state)
: numSlots_(state->numSlots_),
- numFixedSlots_(state->numFixedSlots_),
- operandIndex_(state->operandIndex_)
+ numFixedSlots_(state->numFixedSlots_)
{
// This instruction is only used as a summary for bailout paths.
setResultType(MIRType::Object);
setRecoveredOnBailout();
}
-MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandIndex)
+MObjectState::MObjectState(JSObject* templateObject)
{
// This instruction is only used as a summary for bailout paths.
setResultType(MIRType::Object);
setRecoveredOnBailout();
- if (templateObject->is<NativeObject>()) {
- NativeObject* nativeObject = &templateObject->as<NativeObject>();
- numSlots_ = nativeObject->slotSpan();
- numFixedSlots_ = nativeObject->numFixedSlots();
- } else {
- const UnboxedLayout& layout =
- templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
- // Same as UnboxedLayout::makeNativeGroup
- numSlots_ = layout.properties().length();
- numFixedSlots_ = gc::GetGCKindSlots(layout.getAllocKind());
- }
+ MOZ_ASSERT(templateObject->is<NativeObject>());
- operandIndex_ = operandIndex;
+ NativeObject* nativeObject = &templateObject->as<NativeObject>();
+ numSlots_ = nativeObject->slotSpan();
+ numFixedSlots_ = nativeObject->numFixedSlots();
}
JSObject*
@@ -4905,39 +4869,21 @@ MObjectState::initFromTemplateObject(TempAllocator& alloc, MDefinition* undefine
// the template object. This is needed to account values which are baked in
// the template objects and not visible in IonMonkey, such as the
// uninitialized-lexical magic value of call objects.
- if (templateObject->is<UnboxedPlainObject>()) {
- UnboxedPlainObject& unboxedObject = templateObject->as<UnboxedPlainObject>();
- const UnboxedLayout& layout = unboxedObject.layoutDontCheckGeneration();
- const UnboxedLayout::PropertyVector& properties = layout.properties();
-
- for (size_t i = 0; i < properties.length(); i++) {
- Value val = unboxedObject.getValue(properties[i], /* maybeUninitialized = */ true);
- MDefinition *def = undefinedVal;
- if (!val.isUndefined()) {
- MConstant* ins = val.isObject() ?
- MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
- MConstant::New(alloc, val);
- block()->insertBefore(this, ins);
- def = ins;
- }
- initSlot(i, def);
- }
- } else {
- NativeObject& nativeObject = templateObject->as<NativeObject>();
- MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
-
- for (size_t i = 0; i < numSlots(); i++) {
- Value val = nativeObject.getSlot(i);
- MDefinition *def = undefinedVal;
- if (!val.isUndefined()) {
- MConstant* ins = val.isObject() ?
- MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
- MConstant::New(alloc, val);
- block()->insertBefore(this, ins);
- def = ins;
- }
- initSlot(i, def);
+ NativeObject& nativeObject = templateObject->as<NativeObject>();
+ MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
+
+ MOZ_ASSERT(templateObject->is<NativeObject>());
+ for (size_t i = 0; i < numSlots(); i++) {
+ Value val = nativeObject.getSlot(i);
+ MDefinition *def = undefinedVal;
+ if (!val.isUndefined()) {
+ MConstant* ins = val.isObject() ?
+ MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
+ MConstant::New(alloc, val);
+ block()->insertBefore(this, ins);
+ def = ins;
}
+ initSlot(i, def);
}
return true;
}
@@ -4948,14 +4894,7 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj)
JSObject* templateObject = templateObjectOf(obj);
MOZ_ASSERT(templateObject, "Unexpected object creation.");
- OperandIndexMap* operandIndex = nullptr;
- if (templateObject->is<UnboxedPlainObject>()) {
- operandIndex = new(alloc) OperandIndexMap;
- if (!operandIndex || !operandIndex->init(alloc, templateObject))
- return nullptr;
- }
-
- MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex);
+ MObjectState* res = new(alloc) MObjectState(templateObject);
if (!res || !res->init(alloc, obj))
return nullptr;
return res;
@@ -5862,35 +5801,6 @@ MGetFirstDollarIndex::foldsTo(TempAllocator& alloc)
return MConstant::New(alloc, Int32Value(index));
}
-MConvertUnboxedObjectToNative*
-MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
-{
- MConvertUnboxedObjectToNative* res = new(alloc) MConvertUnboxedObjectToNative(obj, group);
-
- ObjectGroup* nativeGroup = group->unboxedLayout().nativeGroup();
-
- // Make a new type set for the result of this instruction which replaces
- // the input group with the native group we will convert it to.
- TemporaryTypeSet* types = obj->resultTypeSet();
- if (types && !types->unknownObject()) {
- TemporaryTypeSet* newTypes = types->cloneWithoutObjects(alloc.lifoAlloc());
- if (newTypes) {
- for (size_t i = 0; i < types->getObjectCount(); i++) {
- TypeSet::ObjectKey* key = types->getObject(i);
- if (!key)
- continue;
- if (key->unknownProperties() || !key->isGroup() || key->group() != group)
- newTypes->addType(TypeSet::ObjectType(key), alloc.lifoAlloc());
- else
- newTypes->addType(TypeSet::ObjectType(nativeGroup), alloc.lifoAlloc());
- }
- res->setResultTypeSet(newTypes);
- }
- }
-
- return res;
-}
-
bool
jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
MDefinition* obj, MDefinition* id)
@@ -5910,48 +5820,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;
-
- key->watchStateChangeForUnboxedConvertedToNative(constraints);
- }
-
- return elementType;
-}
-
bool
jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints,
MDefinition* obj, MDefinition* id,
@@ -6111,11 +5979,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;
}
@@ -6355,15 +6218,6 @@ PrototypeHasIndexedProperty(IonBuilder* builder, JSObject* obj)
return false;
}
-// Whether Array.prototype, or an object on its proto chain, has an indexed property.
-bool
-jit::ArrayPrototypeHasIndexedProperty(IonBuilder* builder, JSScript* script)
-{
- if (JSObject* proto = script->global().maybeGetArrayPrototype())
- return PrototypeHasIndexedProperty(builder, proto);
- return true;
-}
-
// Whether obj or any of its prototypes have an indexed property.
bool
jit::TypeCanHaveExtraIndexedProperties(IonBuilder* builder, TemporaryTypeSet* types)
@@ -6579,23 +6433,6 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
}
}
- // Perform additional filtering to make sure that any unboxed property
- // being written can accommodate the value.
- for (size_t i = 0; i < types->getObjectCount(); i++) {
- TypeSet::ObjectKey* key = types->getObject(i);
- if (key && key->isGroup() && key->group()->maybeUnboxedLayout()) {
- const UnboxedLayout& layout = key->group()->unboxedLayout();
- if (name) {
- const UnboxedLayout::Property* property = layout.lookup(name);
- if (property && !CanStoreUnboxedType(alloc, property->type, *pvalue))
- return true;
- } else {
- if (layout.isArray() && !CanStoreUnboxedType(alloc, layout.elementType(), *pvalue))
- return true;
- }
- }
- }
-
if (success)
return false;
@@ -6626,17 +6463,6 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
MOZ_ASSERT(excluded);
- // If the excluded object is a group with an unboxed layout, make sure it
- // does not have a corresponding native group. Objects with the native
- // group might appear even though they are not in the type set.
- if (excluded->isGroup()) {
- if (UnboxedLayout* layout = excluded->group()->maybeUnboxedLayout()) {
- if (layout->nativeGroup())
- return true;
- excluded->watchStateChangeForUnboxedConvertedToNative(constraints);
- }
- }
-
*pobj = AddGroupGuard(alloc, current, *pobj, excluded, /* bailOnEquality = */ true);
return false;
}
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index fb0f22fc3..0992768bf 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -30,7 +30,6 @@
#include "vm/EnvironmentObject.h"
#include "vm/SharedMem.h"
#include "vm/TypedArrayCommon.h"
-#include "vm/UnboxedObject.h"
// Undo windows.h damage on Win64
#undef MemoryBarrier
@@ -376,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.
DynamicSlot = 1 << 3, // A Value member of obj->slots.
FixedSlot = 1 << 4, // A Value member of obj->fixedSlots().
DOMProperty = 1 << 5, // A DOM property
@@ -434,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;
@@ -3763,14 +3758,9 @@ class MObjectState
{
private:
uint32_t numSlots_;
- uint32_t numFixedSlots_; // valid if isUnboxed() == false.
- OperandIndexMap* operandIndex_; // valid if isUnboxed() == true.
-
- bool isUnboxed() const {
- return operandIndex_ != nullptr;
- }
+ uint32_t numFixedSlots_;
- MObjectState(JSObject *templateObject, OperandIndexMap* operandIndex);
+ MObjectState(JSObject *templateObject);
explicit MObjectState(MObjectState* state);
MOZ_MUST_USE bool init(TempAllocator& alloc, MDefinition* obj);
@@ -3831,18 +3821,6 @@ class MObjectState
setSlot(slot + numFixedSlots(), def);
}
- // Interface reserved for unboxed objects.
- bool hasOffset(uint32_t offset) const {
- MOZ_ASSERT(isUnboxed());
- return offset < operandIndex_->map.length() && operandIndex_->map[offset] != 0;
- }
- MDefinition* getOffset(uint32_t offset) const {
- return getOperand(operandIndex_->map[offset]);
- }
- void setOffset(uint32_t offset, MDefinition* def) {
- replaceOperand(operandIndex_->map[offset], def);
- }
-
MOZ_MUST_USE bool writeRecoverData(CompactBufferWriter& writer) const override;
bool canRecoverOnBailout() const override {
return true;
@@ -8746,102 +8724,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,
@@ -9335,23 +9217,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)
{
@@ -9373,9 +9251,6 @@ class MLoadElementHole
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, elements), (1, index), (2, initLength))
- JSValueType unboxedType() const {
- return unboxedType_;
- }
bool needsNegativeIntCheck() const {
return needsNegativeIntCheck_;
}
@@ -9386,8 +9261,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())
@@ -9395,7 +9268,7 @@ class MLoadElementHole
return congruentIfOperandsEqual(other);
}
AliasSet getAliasSet() const override {
- return AliasSet::Load(AliasSet::BoxedOrUnboxedElements(unboxedType()));
+ return AliasSet::Load(AliasSet::Element);
}
void collectRangeInfoPreTrunc() override;
@@ -9575,20 +9448,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);
@@ -9603,14 +9473,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)
@@ -9623,13 +9489,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);
@@ -9645,12 +9509,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_;
@@ -9742,59 +9602,6 @@ class MStoreUnboxedString
ALLOW_CLONE(MStoreUnboxedString)
};
-// Passes through an object, after ensuring it is converted from an unboxed
-// object to a native representation.
-class MConvertUnboxedObjectToNative
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- CompilerObjectGroup group_;
-
- explicit MConvertUnboxedObjectToNative(MDefinition* obj, ObjectGroup* group)
- : MUnaryInstruction(obj),
- group_(group)
- {
- setGuard();
- setMovable();
- setResultType(MIRType::Object);
- }
-
- public:
- INSTRUCTION_HEADER(ConvertUnboxedObjectToNative)
- NAMED_OPERANDS((0, object))
-
- static MConvertUnboxedObjectToNative* New(TempAllocator& alloc, MDefinition* obj,
- ObjectGroup* group);
-
- ObjectGroup* group() const {
- return group_;
- }
- bool congruentTo(const MDefinition* ins) const override {
- if (!congruentIfOperandsEqual(ins))
- return false;
- return ins->toConvertUnboxedObjectToNative()->group() == group();
- }
- AliasSet getAliasSet() const override {
- // This instruction can read and write to all parts of the object, but
- // is marked as non-effectful so it can be consolidated by LICM and GVN
- // and avoid inhibiting other optimizations.
- //
- // This is valid to do because when unboxed objects might have a native
- // group they can be converted to, we do not optimize accesses to the
- // unboxed objects and do not guard on their group or shape (other than
- // in this opcode).
- //
- // Later accesses can assume the object has a native representation
- // and optimize accordingly. Those accesses cannot be reordered before
- // this instruction, however. This is prevented by chaining this
- // instruction with the object itself, in the same way as MBoundsCheck.
- return AliasSet::None();
- }
- bool appendRoots(MRootList& roots) const override {
- return roots.append(group_);
- }
-};
-
// Array.prototype.pop or Array.prototype.shift on a dense array.
class MArrayPopShift
: public MUnaryInstruction,
@@ -9808,13 +9615,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)
{ }
@@ -9832,12 +9638,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)
@@ -9848,10 +9650,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);
}
@@ -9861,12 +9661,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;
@@ -9880,15 +9676,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);
}
@@ -9906,10 +9700,6 @@ class MArraySlice
return initialHeap_;
}
- JSValueType unboxedType() const {
- return unboxedType_;
- }
-
bool possiblyCalls() const override {
return true;
}
@@ -11174,11 +10964,6 @@ class MGuardShape
setMovable();
setResultType(MIRType::Object);
setResultTypeSet(obj->resultTypeSet());
-
- // Disallow guarding on unboxed object shapes. The group is better to
- // guard on, and guarding on the shape can interact badly with
- // MConvertUnboxedObjectToNative.
- MOZ_ASSERT(shape->getObjectClass() != &UnboxedPlainObject::class_);
}
public:
@@ -11273,11 +11058,6 @@ class MGuardObjectGroup
setGuard();
setMovable();
setResultType(MIRType::Object);
-
- // Unboxed groups which might be converted to natives can't be guarded
- // on, due to MConvertUnboxedObjectToNative.
- MOZ_ASSERT_IF(group->maybeUnboxedLayoutDontCheckGeneration(),
- !group->unboxedLayoutDontCheckGeneration().nativeGroup());
}
public:
@@ -11386,73 +11166,6 @@ class MGuardClass
ALLOW_CLONE(MGuardClass)
};
-// Guard on the presence or absence of an unboxed object's expando.
-class MGuardUnboxedExpando
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- bool requireExpando_;
- BailoutKind bailoutKind_;
-
- MGuardUnboxedExpando(MDefinition* obj, bool requireExpando, BailoutKind bailoutKind)
- : MUnaryInstruction(obj),
- requireExpando_(requireExpando),
- bailoutKind_(bailoutKind)
- {
- setGuard();
- setMovable();
- setResultType(MIRType::Object);
- }
-
- public:
- INSTRUCTION_HEADER(GuardUnboxedExpando)
- TRIVIAL_NEW_WRAPPERS
- NAMED_OPERANDS((0, object))
-
- bool requireExpando() const {
- return requireExpando_;
- }
- BailoutKind bailoutKind() const {
- return bailoutKind_;
- }
- bool congruentTo(const MDefinition* ins) const override {
- if (!congruentIfOperandsEqual(ins))
- return false;
- if (requireExpando() != ins->toGuardUnboxedExpando()->requireExpando())
- return false;
- return true;
- }
- AliasSet getAliasSet() const override {
- return AliasSet::Load(AliasSet::ObjectFields);
- }
-};
-
-// Load an unboxed plain object's expando.
-class MLoadUnboxedExpando
- : public MUnaryInstruction,
- public SingleObjectPolicy::Data
-{
- private:
- explicit MLoadUnboxedExpando(MDefinition* object)
- : MUnaryInstruction(object)
- {
- setResultType(MIRType::Object);
- setMovable();
- }
-
- public:
- INSTRUCTION_HEADER(LoadUnboxedExpando)
- 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);
- }
-};
-
// Load from vp[slot] (slots that are not inline in an object).
class MLoadSlot
: public MUnaryInstruction,
@@ -12355,15 +12068,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();
@@ -12383,9 +12094,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);
@@ -12398,8 +12106,6 @@ class MInArray
return false;
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
return false;
- if (unboxedType() != other->unboxedType())
- return false;
return congruentIfOperandsEqual(other);
}
};
@@ -14300,8 +14006,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);
@@ -14333,7 +14037,6 @@ bool PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
MBasicBlock* current, MDefinition** pobj,
PropertyName* name, MDefinition** pvalue,
bool canModify, MIRType implicitType = MIRType::None);
-bool ArrayPrototypeHasIndexedProperty(IonBuilder* builder, JSScript* script);
bool TypeCanHaveExtraIndexedProperties(IonBuilder* builder, TemporaryTypeSet* types);
inline MIRType
diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h
index fddc1e637..ab37604b4 100644
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -187,8 +187,6 @@ namespace jit {
_(GuardObjectGroup) \
_(GuardObjectIdentity) \
_(GuardClass) \
- _(GuardUnboxedExpando) \
- _(LoadUnboxedExpando) \
_(ArrayLength) \
_(SetArrayLength) \
_(GetNextEntryForIterator) \
@@ -200,10 +198,6 @@ namespace jit {
_(SetTypedObjectOffset) \
_(InitializedLength) \
_(SetInitializedLength) \
- _(UnboxedArrayLength) \
- _(UnboxedArrayInitializedLength) \
- _(IncrementUnboxedArrayInitializedLength) \
- _(SetUnboxedArrayInitializedLength) \
_(Not) \
_(BoundsCheck) \
_(BoundsCheckLower) \
@@ -219,7 +213,6 @@ namespace jit {
_(StoreUnboxedScalar) \
_(StoreUnboxedObjectOrNull) \
_(StoreUnboxedString) \
- _(ConvertUnboxedObjectToNative) \
_(ArrayPopShift) \
_(ArrayPush) \
_(ArraySlice) \
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
index f633b9b7b..a739b9325 100644
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -126,20 +126,14 @@ MacroAssembler::guardTypeSetMightBeIncomplete(TypeSet* types, Register obj, Regi
{
// Type set guards might miss when an object's group changes. In this case
// either its old group's properties will become unknown, or it will change
- // to a native object with an original unboxed group. Jump to label if this
- // might have happened for the input object.
+ // to a native object. Jump to label if this might have happened for the
+ // input object.
if (types->unknownObject()) {
jump(label);
return;
}
- loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
- load32(Address(scratch, ObjectGroup::offsetOfFlags()), scratch);
- and32(Imm32(OBJECT_FLAG_ADDENDUM_MASK), scratch);
- branch32(Assembler::Equal,
- scratch, Imm32(ObjectGroup::addendumOriginalUnboxedGroupValue()), label);
-
for (size_t i = 0; i < types->getObjectCount(); i++) {
if (JSObject* singleton = types->getSingletonNoBarrier(i)) {
movePtr(ImmGCPtr(singleton), scratch);
@@ -468,268 +462,6 @@ template void MacroAssembler::loadFromTypedArray(Scalar::Type arrayType, const A
template void MacroAssembler::loadFromTypedArray(Scalar::Type arrayType, const BaseIndex& src, const ValueOperand& dest,
bool allowDouble, Register temp, Label* fail);
-template <typename T>
-void
-MacroAssembler::loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output)
-{
- switch (type) {
- case JSVAL_TYPE_INT32: {
- // Handle loading an int32 into a double reg.
- if (output.type() == MIRType::Double) {
- convertInt32ToDouble(address, output.typedReg().fpu());
- break;
- }
- MOZ_FALLTHROUGH;
- }
-
- case JSVAL_TYPE_BOOLEAN:
- case JSVAL_TYPE_STRING: {
- Register outReg;
- if (output.hasValue()) {
- outReg = output.valueReg().scratchReg();
- } else {
- MOZ_ASSERT(output.type() == MIRTypeFromValueType(type));
- outReg = output.typedReg().gpr();
- }
-
- switch (type) {
- case JSVAL_TYPE_BOOLEAN:
- load8ZeroExtend(address, outReg);
- break;
- case JSVAL_TYPE_INT32:
- load32(address, outReg);
- break;
- case JSVAL_TYPE_STRING:
- loadPtr(address, outReg);
- break;
- default:
- MOZ_CRASH();
- }
-
- if (output.hasValue())
- tagValue(type, outReg, output.valueReg());
- break;
- }
-
- case JSVAL_TYPE_OBJECT:
- if (output.hasValue()) {
- Register scratch = output.valueReg().scratchReg();
- loadPtr(address, scratch);
-
- Label notNull, done;
- branchPtr(Assembler::NotEqual, scratch, ImmWord(0), &notNull);
-
- moveValue(NullValue(), output.valueReg());
- jump(&done);
-
- bind(&notNull);
- tagValue(JSVAL_TYPE_OBJECT, scratch, output.valueReg());
-
- bind(&done);
- } else {
- // Reading null can't be possible here, as otherwise the result
- // would be a value (either because null has been read before or
- // because there is a barrier).
- Register reg = output.typedReg().gpr();
- loadPtr(address, reg);
-#ifdef DEBUG
- Label ok;
- branchTestPtr(Assembler::NonZero, reg, reg, &ok);
- assumeUnreachable("Null not possible");
- bind(&ok);
-#endif
- }
- break;
-
- case JSVAL_TYPE_DOUBLE:
- // Note: doubles in unboxed objects are not accessed through other
- // views and do not need canonicalization.
- if (output.hasValue())
- loadValue(address, output.valueReg());
- else
- loadDouble(address, output.typedReg().fpu());
- break;
-
- default:
- MOZ_CRASH();
- }
-}
-
-template void
-MacroAssembler::loadUnboxedProperty(Address address, JSValueType type,
- TypedOrValueRegister output);
-
-template void
-MacroAssembler::loadUnboxedProperty(BaseIndex address, JSValueType type,
- TypedOrValueRegister output);
-
-static void
-StoreUnboxedFailure(MacroAssembler& masm, Label* failure)
-{
- // Storing a value to an unboxed property is a fallible operation and
- // the caller must provide a failure label if a particular unboxed store
- // might fail. Sometimes, however, a store that cannot succeed (such as
- // storing a string to an int32 property) will be marked as infallible.
- // This can only happen if the code involved is unreachable.
- if (failure)
- masm.jump(failure);
- else
- masm.assumeUnreachable("Incompatible write to unboxed property");
-}
-
-template <typename T>
-void
-MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
- const ConstantOrRegister& value, Label* failure)
-{
- switch (type) {
- case JSVAL_TYPE_BOOLEAN:
- if (value.constant()) {
- if (value.value().isBoolean())
- store8(Imm32(value.value().toBoolean()), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else if (value.reg().hasTyped()) {
- if (value.reg().type() == MIRType::Boolean)
- store8(value.reg().typedReg().gpr(), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else {
- if (failure)
- branchTestBoolean(Assembler::NotEqual, value.reg().valueReg(), failure);
- storeUnboxedPayload(value.reg().valueReg(), address, /* width = */ 1);
- }
- break;
-
- case JSVAL_TYPE_INT32:
- if (value.constant()) {
- if (value.value().isInt32())
- store32(Imm32(value.value().toInt32()), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else if (value.reg().hasTyped()) {
- if (value.reg().type() == MIRType::Int32)
- store32(value.reg().typedReg().gpr(), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else {
- if (failure)
- branchTestInt32(Assembler::NotEqual, value.reg().valueReg(), failure);
- storeUnboxedPayload(value.reg().valueReg(), address, /* width = */ 4);
- }
- break;
-
- case JSVAL_TYPE_DOUBLE:
- if (value.constant()) {
- if (value.value().isNumber()) {
- loadConstantDouble(value.value().toNumber(), ScratchDoubleReg);
- storeDouble(ScratchDoubleReg, address);
- } else {
- StoreUnboxedFailure(*this, failure);
- }
- } else if (value.reg().hasTyped()) {
- if (value.reg().type() == MIRType::Int32) {
- convertInt32ToDouble(value.reg().typedReg().gpr(), ScratchDoubleReg);
- storeDouble(ScratchDoubleReg, address);
- } else if (value.reg().type() == MIRType::Double) {
- storeDouble(value.reg().typedReg().fpu(), address);
- } else {
- StoreUnboxedFailure(*this, failure);
- }
- } else {
- ValueOperand reg = value.reg().valueReg();
- Label notInt32, end;
- branchTestInt32(Assembler::NotEqual, reg, &notInt32);
- int32ValueToDouble(reg, ScratchDoubleReg);
- storeDouble(ScratchDoubleReg, address);
- jump(&end);
- bind(&notInt32);
- if (failure)
- branchTestDouble(Assembler::NotEqual, reg, failure);
- storeValue(reg, address);
- bind(&end);
- }
- break;
-
- case JSVAL_TYPE_OBJECT:
- if (value.constant()) {
- if (value.value().isObjectOrNull())
- storePtr(ImmGCPtr(value.value().toObjectOrNull()), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else if (value.reg().hasTyped()) {
- MOZ_ASSERT(value.reg().type() != MIRType::Null);
- if (value.reg().type() == MIRType::Object)
- storePtr(value.reg().typedReg().gpr(), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else {
- if (failure) {
- Label ok;
- branchTestNull(Assembler::Equal, value.reg().valueReg(), &ok);
- branchTestObject(Assembler::NotEqual, value.reg().valueReg(), failure);
- bind(&ok);
- }
- storeUnboxedPayload(value.reg().valueReg(), address, /* width = */ sizeof(uintptr_t));
- }
- break;
-
- case JSVAL_TYPE_STRING:
- if (value.constant()) {
- if (value.value().isString())
- storePtr(ImmGCPtr(value.value().toString()), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else if (value.reg().hasTyped()) {
- if (value.reg().type() == MIRType::String)
- storePtr(value.reg().typedReg().gpr(), address);
- else
- StoreUnboxedFailure(*this, failure);
- } else {
- if (failure)
- branchTestString(Assembler::NotEqual, value.reg().valueReg(), failure);
- storeUnboxedPayload(value.reg().valueReg(), address, /* width = */ sizeof(uintptr_t));
- }
- break;
-
- default:
- MOZ_CRASH();
- }
-}
-
-template void
-MacroAssembler::storeUnboxedProperty(Address address, JSValueType type,
- const ConstantOrRegister& value, Label* failure);
-
-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
@@ -1277,20 +1009,6 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject* templateObj,
nbytes = (nbytes < sizeof(uintptr_t)) ? 0 : nbytes - sizeof(uintptr_t);
offset += sizeof(uintptr_t);
}
- } else if (templateObj->is<UnboxedPlainObject>()) {
- 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");
}
@@ -1312,29 +1030,6 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject* templateObj,
}
void
-MacroAssembler::initUnboxedObjectContents(Register object, UnboxedPlainObject* templateObject)
-{
- const UnboxedLayout& layout = templateObject->layoutDontCheckGeneration();
-
- // Initialize reference fields of the object, per UnboxedPlainObject::create.
- if (const int32_t* list = layout.traceList()) {
- while (*list != -1) {
- storePtr(ImmGCPtr(GetJitContext()->runtime->names().empty),
- Address(object, UnboxedPlainObject::offsetOfData() + *list));
- list++;
- }
- list++;
- while (*list != -1) {
- storePtr(ImmWord(0),
- Address(object, UnboxedPlainObject::offsetOfData() + *list));
- list++;
- }
- // Unboxed objects don't have Values to initialize.
- MOZ_ASSERT(*(list + 1) == -1);
- }
-}
-
-void
MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register result,
Label* fail)
{
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
index b6616321c..d5cc95839 100644
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -36,7 +36,6 @@
#include "vm/ProxyObject.h"
#include "vm/Shape.h"
#include "vm/TypedArrayObject.h"
-#include "vm/UnboxedObject.h"
using mozilla::FloatingPoint;
@@ -1626,20 +1625,6 @@ 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.
- template <typename T>
- void loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output);
-
- // Store a property to an UnboxedPlainObject, without triggering barriers.
- // If failure is null, the value definitely has a type suitable for storing
- // in the property.
- template <typename T>
- 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);
}
@@ -1716,8 +1701,6 @@ class MacroAssembler : public MacroAssemblerSpecific
LiveRegisterSet liveRegs, Label* fail,
TypedArrayObject* templateObj, TypedArrayLength lengthKind);
- void initUnboxedObjectContents(Register object, UnboxedPlainObject* templateObject);
-
void newGCString(Register result, Register temp, Label* fail);
void newGCFatInlineString(Register result, Register temp, Label* fail);
diff --git a/js/src/jit/OptimizationTracking.cpp b/js/src/jit/OptimizationTracking.cpp
index 308def041..7d72795a0 100644
--- a/js/src/jit/OptimizationTracking.cpp
+++ b/js/src/jit/OptimizationTracking.cpp
@@ -844,8 +844,6 @@ MaybeConstructorFromType(TypeSet::Type ty)
return nullptr;
ObjectGroup* obj = ty.group();
TypeNewScript* newScript = obj->newScript();
- if (!newScript && obj->maybeUnboxedLayout())
- newScript = obj->unboxedLayout().newScript();
return newScript ? newScript->function() : nullptr;
}
diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
index 13bf9224b..793b631df 100644
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1354,7 +1354,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;
@@ -1539,37 +1539,12 @@ RObjectState::recover(JSContext* cx, SnapshotIterator& iter) const
RootedObject object(cx, &iter.read().toObject());
RootedValue val(cx);
- if (object->is<UnboxedPlainObject>()) {
- const UnboxedLayout& layout = object->as<UnboxedPlainObject>().layout();
+ RootedNativeObject nativeObject(cx, &object->as<NativeObject>());
+ MOZ_ASSERT(nativeObject->slotSpan() == numSlots());
- RootedId id(cx);
- RootedValue receiver(cx, ObjectValue(*object));
- const UnboxedLayout::PropertyVector& properties = layout.properties();
- for (size_t i = 0; i < properties.length(); i++) {
- val = iter.read();
-
- // This is the default placeholder value of MObjectState, when no
- // properties are defined yet.
- if (val.isUndefined())
- continue;
-
- id = NameToId(properties[i].name);
- ObjectOpResult result;
-
- // SetProperty can only fail due to OOM.
- if (!SetProperty(cx, object, id, val, receiver, result))
- return false;
- if (!result)
- return result.reportError(cx, object, id);
- }
- } else {
- RootedNativeObject nativeObject(cx, &object->as<NativeObject>());
- MOZ_ASSERT(nativeObject->slotSpan() == numSlots());
-
- for (size_t i = 0; i < numSlots(); i++) {
- val = iter.read();
- nativeObject->setSlot(i, val);
- }
+ for (size_t i = 0; i < numSlots(); i++) {
+ val = iter.read();
+ nativeObject->setSlot(i, val);
}
val.setObject(*object);
diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp
index 4614b2162..97ba52349 100644
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -13,7 +13,6 @@
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
-#include "vm/UnboxedObject.h"
#include "jsobjinlines.h"
@@ -183,25 +182,6 @@ IsObjectEscaped(MInstruction* ins, JSObject* objDefault)
JitSpewDef(JitSpew_Escape, "is escaped by\n", def);
return true;
- case MDefinition::Op_LoadUnboxedScalar:
- case MDefinition::Op_StoreUnboxedScalar:
- case MDefinition::Op_LoadUnboxedObjectOrNull:
- case MDefinition::Op_StoreUnboxedObjectOrNull:
- case MDefinition::Op_LoadUnboxedString:
- case MDefinition::Op_StoreUnboxedString:
- // Not escaped if it is the first argument.
- if (def->indexOf(*i) != 0) {
- JitSpewDef(JitSpew_Escape, "is escaped by\n", def);
- return true;
- }
-
- if (!def->getOperand(1)->isConstant()) {
- JitSpewDef(JitSpew_Escape, "is addressed with unknown index\n", def);
- return true;
- }
-
- break;
-
case MDefinition::Op_PostWriteBarrier:
break;
@@ -305,16 +285,6 @@ class ObjectMemoryView : public MDefinitionVisitorDefaultNoop
void visitGuardShape(MGuardShape* ins);
void visitFunctionEnvironment(MFunctionEnvironment* ins);
void visitLambda(MLambda* ins);
- void visitStoreUnboxedScalar(MStoreUnboxedScalar* ins);
- void visitLoadUnboxedScalar(MLoadUnboxedScalar* ins);
- void visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins);
- void visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins);
- void visitStoreUnboxedString(MStoreUnboxedString* ins);
- void visitLoadUnboxedString(MLoadUnboxedString* ins);
-
- private:
- void storeOffset(MInstruction* ins, size_t offset, MDefinition* value);
- void loadOffset(MInstruction* ins, size_t offset);
};
const char* ObjectMemoryView::phaseName = "Scalar Replacement of Object";
@@ -656,121 +626,6 @@ ObjectMemoryView::visitLambda(MLambda* ins)
ins->setIncompleteObject();
}
-static size_t
-GetOffsetOf(MDefinition* index, size_t width, int32_t baseOffset)
-{
- int32_t idx = index->toConstant()->toInt32();
- MOZ_ASSERT(idx >= 0);
- MOZ_ASSERT(baseOffset >= 0 && size_t(baseOffset) >= UnboxedPlainObject::offsetOfData());
- return idx * width + baseOffset - UnboxedPlainObject::offsetOfData();
-}
-
-static size_t
-GetOffsetOf(MDefinition* index, Scalar::Type type, int32_t baseOffset)
-{
- return GetOffsetOf(index, Scalar::byteSize(type), baseOffset);
-}
-
-void
-ObjectMemoryView::storeOffset(MInstruction* ins, size_t offset, MDefinition* value)
-{
- // Clone the state and update the slot value.
- MOZ_ASSERT(state_->hasOffset(offset));
- state_ = BlockState::Copy(alloc_, state_);
- if (!state_) {
- oom_ = true;
- return;
- }
-
- state_->setOffset(offset, value);
- ins->block()->insertBefore(ins, state_);
-
- // Remove original instruction.
- ins->block()->discard(ins);
-}
-
-void
-ObjectMemoryView::loadOffset(MInstruction* ins, size_t offset)
-{
- // Replace load by the slot value.
- MOZ_ASSERT(state_->hasOffset(offset));
- ins->replaceAllUsesWith(state_->getOffset(offset));
-
- // Remove original instruction.
- ins->block()->discard(ins);
-}
-
-void
-ObjectMemoryView::visitStoreUnboxedScalar(MStoreUnboxedScalar* ins)
-{
- // Skip stores made on other objects.
- if (ins->elements() != obj_)
- return;
-
- size_t offset = GetOffsetOf(ins->index(), ins->storageType(), ins->offsetAdjustment());
- storeOffset(ins, offset, ins->value());
-}
-
-void
-ObjectMemoryView::visitLoadUnboxedScalar(MLoadUnboxedScalar* ins)
-{
- // Skip loads made on other objects.
- if (ins->elements() != obj_)
- return;
-
- // Replace load by the slot value.
- size_t offset = GetOffsetOf(ins->index(), ins->storageType(), ins->offsetAdjustment());
- loadOffset(ins, offset);
-}
-
-void
-ObjectMemoryView::visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins)
-{
- // Skip stores made on other objects.
- if (ins->elements() != obj_)
- return;
-
- // Clone the state and update the slot value.
- size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
- storeOffset(ins, offset, ins->value());
-}
-
-void
-ObjectMemoryView::visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins)
-{
- // Skip loads made on other objects.
- if (ins->elements() != obj_)
- return;
-
- // Replace load by the slot value.
- size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
- loadOffset(ins, offset);
-}
-
-void
-ObjectMemoryView::visitStoreUnboxedString(MStoreUnboxedString* ins)
-{
- // Skip stores made on other objects.
- if (ins->elements() != obj_)
- return;
-
- // Clone the state and update the slot value.
- size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
- storeOffset(ins, offset, ins->value());
-}
-
-void
-ObjectMemoryView::visitLoadUnboxedString(MLoadUnboxedString* ins)
-{
- // Skip loads made on other objects.
- if (ins->elements() != obj_)
- return;
-
- // Replace load by the slot value.
- size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
- loadOffset(ins, offset);
-}
-
static bool
IndexOf(MDefinition* ins, int32_t* res)
{
@@ -907,11 +762,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 767cff661..05a95824f 100644
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -27,6 +27,7 @@
#endif
#include "jit/VMFunctions.h"
#include "vm/Interpreter.h"
+#include "vm/NativeObject-inl.h"
#include "jit/MacroAssembler-inl.h"
#include "vm/Interpreter-inl.h"
@@ -285,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");
@@ -2248,9 +2244,7 @@ IsCacheableProtoChain(JSObject* obj, JSObject* holder, bool isDOMProxy)
if (!isDOMProxy && !obj->isNative()) {
if (obj == holder)
return false;
- if (!obj->is<UnboxedPlainObject>() &&
- !obj->is<UnboxedArrayObject>() &&
- !obj->is<TypedObject>())
+ if (!obj->is<TypedObject>())
{
return false;
}
@@ -2578,12 +2572,6 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
} else if (curObj != obj) {
// Non-native objects are only handled as the original receiver.
return false;
- } 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;
@@ -2848,34 +2836,15 @@ GuardReceiverObject(MacroAssembler& masm, ReceiverGuard guard,
{
Address groupAddress(ICStubReg, receiverGuardOffset + HeapReceiverGuard::offsetOfGroup());
Address shapeAddress(ICStubReg, receiverGuardOffset + HeapReceiverGuard::offsetOfShape());
- Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
if (guard.group) {
masm.loadPtr(groupAddress, scratch);
masm.branchTestObjGroup(Assembler::NotEqual, object, scratch, failure);
-
- if (guard.group->clasp() == &UnboxedPlainObject::class_ && !guard.shape) {
- // Guard the unboxed object has no expando object.
- masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), failure);
- }
}
if (guard.shape) {
masm.loadPtr(shapeAddress, scratch);
- if (guard.group && guard.group->clasp() == &UnboxedPlainObject::class_) {
- // Guard the unboxed object has a matching expando object.
- masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failure);
- Label done;
- masm.push(object);
- masm.loadPtr(expandoAddress, object);
- masm.branchTestObjShape(Assembler::Equal, object, scratch, &done);
- masm.pop(object);
- masm.jump(failure);
- masm.bind(&done);
- masm.pop(object);
- } else {
- masm.branchTestObjShape(Assembler::NotEqual, object, scratch, failure);
- }
+ masm.branchTestObjShape(Assembler::NotEqual, object, scratch, failure);
}
}
@@ -4259,8 +4228,7 @@ DoNewObject(JSContext* cx, void* payload, ICNewObject_Fallback* stub, MutableHan
return false;
if (!stub->invalid() &&
- (templateObject->is<UnboxedPlainObject>() ||
- !templateObject->as<PlainObject>().hasDynamicSlots()))
+ !templateObject->as<PlainObject>().hasDynamicSlots())
{
JitCode* code = GenerateNewObjectWithTemplateCode(cx, templateObject);
if (!code)
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 77b9e3647..402d910b9 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -28,7 +28,7 @@
#include "vm/NativeObject-inl.h"
#include "vm/StringObject-inl.h"
#include "vm/TypeInference-inl.h"
-#include "vm/UnboxedObject-inl.h"
+#include "gc/StoreBuffer-inl.h"
using namespace js;
using namespace js::jit;
@@ -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/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp
index 2830f0695..1e20da1c8 100644
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -2401,7 +2401,12 @@ Assembler::as_b(Label* l, Condition c)
if (oom())
return BufferOffset();
- as_b(BufferOffset(l).diffB<BOffImm>(ret), c, ret);
+ BOffImm off = BufferOffset(l).diffB<BOffImm>(ret);
+ if (off.isInvalid()) {
+ m_buffer.fail_bail();
+ return BufferOffset();
+ }
+ as_b(off, c, ret);
#ifdef JS_DISASM_ARM
spewBranch(m_buffer.getInstOrNull(ret), l);
#endif
diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp
index d40578514..a4161ab00 100644
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -5012,7 +5012,10 @@ void
MacroAssembler::patchCall(uint32_t callerOffset, uint32_t calleeOffset)
{
BufferOffset inst(callerOffset - 4);
- as_bl(BufferOffset(calleeOffset).diffB<BOffImm>(inst), Always, inst);
+ BOffImm off = BufferOffset(calleeOffset).diffB<BOffImm>(inst);
+ MOZ_RELEASE_ASSERT(!off.isInvalid(),
+ "Failed to insert necessary far jump islands");
+ as_bl(off, Always, inst);
}
CodeOffset
diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h
index f4adcc63c..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 {
@@ -5891,22 +5817,6 @@ class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0>
}
};
-// If necessary, convert an unboxed object in a particular group to its native
-// representation.
-class LConvertUnboxedObjectToNative : public LInstructionHelper<0, 1, 0>
-{
- public:
- LIR_HEADER(ConvertUnboxedObjectToNative)
-
- explicit LConvertUnboxedObjectToNative(const LAllocation& object) {
- setOperand(0, object);
- }
-
- MConvertUnboxedObjectToNative* mir() {
- return mir_->toConvertUnboxedObjectToNative();
- }
-};
-
class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2>
{
public:
@@ -7429,38 +7339,6 @@ class LGuardReceiverPolymorphic : public LInstructionHelper<0, 1, 1>
}
};
-class LGuardUnboxedExpando : public LInstructionHelper<0, 1, 0>
-{
- public:
- LIR_HEADER(GuardUnboxedExpando)
-
- explicit LGuardUnboxedExpando(const LAllocation& in) {
- setOperand(0, in);
- }
- const LAllocation* object() {
- return getOperand(0);
- }
- const MGuardUnboxedExpando* mir() const {
- return mir_->toGuardUnboxedExpando();
- }
-};
-
-class LLoadUnboxedExpando : public LInstructionHelper<1, 1, 0>
-{
- public:
- LIR_HEADER(LoadUnboxedExpando)
-
- explicit LLoadUnboxedExpando(const LAllocation& in) {
- setOperand(0, in);
- }
- const LAllocation* object() {
- return getOperand(0);
- }
- const MLoadUnboxedExpando* mir() const {
- return mir_->toLoadUnboxedExpando();
- }
-};
-
// Guard that a value is in a TypeSet.
class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
{
diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h
index fe2ab5ea3..deae92839 100644
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -258,8 +258,6 @@
_(GuardObjectGroup) \
_(GuardObjectIdentity) \
_(GuardClass) \
- _(GuardUnboxedExpando) \
- _(LoadUnboxedExpando) \
_(TypeBarrierV) \
_(TypeBarrierO) \
_(MonitorTypes) \
@@ -269,10 +267,6 @@
_(PostWriteElementBarrierV) \
_(InitializedLength) \
_(SetInitializedLength) \
- _(UnboxedArrayLength) \
- _(UnboxedArrayInitializedLength) \
- _(IncrementUnboxedArrayInitializedLength) \
- _(SetUnboxedArrayInitializedLength) \
_(BoundsCheck) \
_(BoundsCheckRange) \
_(BoundsCheckLower) \
@@ -287,7 +281,6 @@
_(StoreElementT) \
_(StoreUnboxedScalar) \
_(StoreUnboxedPointer) \
- _(ConvertUnboxedObjectToNative) \
_(ArrayPopShiftV) \
_(ArrayPopShiftT) \
_(ArrayPushV) \