From c22a493144e39d76bfa42c46f9d6d17a5143ac35 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sat, 22 Feb 2020 21:09:32 +0100 Subject: Revert #1142 - Remove unboxed objects - accounting for removal of watch()/unwatch() --- js/src/jit/MIR.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'js/src/jit/MIR.cpp') diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 0cf31adb3..1e4ee170f 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -4783,14 +4783,15 @@ MCreateThisWithTemplate::canRecoverOnBailout() const MObjectState::MObjectState(MObjectState* state) : numSlots_(state->numSlots_), - numFixedSlots_(state->numFixedSlots_) + numFixedSlots_(state->numFixedSlots_), + operandIndex_(state->operandIndex_) { // This instruction is only used as a summary for bailout paths. setResultType(MIRType::Object); setRecoveredOnBailout(); } -MObjectState::MObjectState(JSObject* templateObject) +MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandIndex) { // This instruction is only used as a summary for bailout paths. setResultType(MIRType::Object); @@ -4801,6 +4802,8 @@ MObjectState::MObjectState(JSObject* templateObject) NativeObject* nativeObject = &templateObject->as(); numSlots_ = nativeObject->slotSpan(); numFixedSlots_ = nativeObject->numFixedSlots(); + + operandIndex_ = operandIndex; } JSObject* @@ -4860,7 +4863,7 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj) JSObject* templateObject = templateObjectOf(obj); MOZ_ASSERT(templateObject, "Unexpected object creation."); - MObjectState* res = new(alloc) MObjectState(templateObject); + MObjectState* res = new(alloc) MObjectState(templateObject, nullptr); if (!res || !res->init(alloc, obj)) return nullptr; return res; -- cgit v1.2.3 From af69cb07db0d810a1a1a507b890e6beb23dc421c Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 23 Feb 2020 14:41:40 +0100 Subject: Revert #1137 - Remove unboxed arrays - accounting for removal of watch()/unwatch() - updated for intermediate code changes. --- js/src/jit/MIR.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'js/src/jit/MIR.cpp') diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 1e4ee170f..403e70c02 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -5789,6 +5789,46 @@ jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints, return clasp && clasp->isNative() && !IsTypedArrayClass(clasp); } +JSValueType +jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj, + MDefinition* id) +{ + if (obj->mightBeType(MIRType::String)) + return JSVAL_TYPE_MAGIC; + + if (id && id->type() != MIRType::Int32 && id->type() != MIRType::Double) + return JSVAL_TYPE_MAGIC; + + TemporaryTypeSet* types = obj->resultTypeSet(); + if (!types || types->unknownObject()) + return JSVAL_TYPE_MAGIC; + + JSValueType elementType = JSVAL_TYPE_MAGIC; + for (unsigned i = 0; i < types->getObjectCount(); i++) { + TypeSet::ObjectKey* key = types->getObject(i); + if (!key) + continue; + + if (key->unknownProperties() || !key->isGroup()) + return JSVAL_TYPE_MAGIC; + + if (key->clasp() != &UnboxedArrayObject::class_) + return JSVAL_TYPE_MAGIC; + + const UnboxedLayout &layout = key->group()->unboxedLayout(); + + if (layout.nativeGroup()) + return JSVAL_TYPE_MAGIC; + + if (elementType == layout.elementType() || elementType == JSVAL_TYPE_MAGIC) + elementType = layout.elementType(); + else + return JSVAL_TYPE_MAGIC; + } + + return elementType; +} + bool jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints, MDefinition* obj, MDefinition* id, @@ -5948,6 +5988,11 @@ 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; } -- cgit v1.2.3 From 0d1eea2ebfcf1a3746ff0125a6fa340e8b90d722 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 23 Feb 2020 19:43:47 +0100 Subject: Revert #1091 Remove unboxed object code phase 1 + extras. This should be the last code backout for this. merging this branch should get us back to the way we were (+ additional code changes for later changes) as fasr as the unused unboxed code is concerned. --- js/src/jit/MIR.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 173 insertions(+), 22 deletions(-) (limited to 'js/src/jit/MIR.cpp') diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 403e70c02..b9e5e8d61 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -2630,6 +2630,40 @@ jit::EqualTypes(MIRType type1, TemporaryTypeSet* typeset1, return typeset1->equals(typeset2); } +// Tests whether input/inputTypes can always be stored to an unboxed +// object/array property with the given unboxed type. +bool +jit::CanStoreUnboxedType(TempAllocator& alloc, + JSValueType unboxedType, MIRType input, TypeSet* inputTypes) +{ + TemporaryTypeSet types; + + switch (unboxedType) { + case JSVAL_TYPE_BOOLEAN: + case JSVAL_TYPE_INT32: + case JSVAL_TYPE_DOUBLE: + case JSVAL_TYPE_STRING: + types.addType(TypeSet::PrimitiveType(unboxedType), alloc.lifoAlloc()); + break; + + case JSVAL_TYPE_OBJECT: + types.addType(TypeSet::AnyObjectType(), alloc.lifoAlloc()); + types.addType(TypeSet::NullType(), alloc.lifoAlloc()); + break; + + default: + MOZ_CRASH("Bad unboxed type"); + } + + return TypeSetIncludes(&types, input, inputTypes); +} + +static bool +CanStoreUnboxedType(TempAllocator& alloc, JSValueType unboxedType, MDefinition* value) +{ + return CanStoreUnboxedType(alloc, unboxedType, value->type(), value->resultTypeSet()); +} + bool MPhi::specializeType(TempAllocator& alloc) { @@ -4776,8 +4810,35 @@ MBeta::printOpcode(GenericPrinter& out) const bool MCreateThisWithTemplate::canRecoverOnBailout() const { - MOZ_ASSERT(templateObject()->is()); - MOZ_ASSERT(!templateObject()->as().denseElementsAreCopyOnWrite()); + MOZ_ASSERT(templateObject()->is() || templateObject()->is()); + MOZ_ASSERT_IF(templateObject()->is(), + !templateObject()->as().denseElementsAreCopyOnWrite()); + return true; +} + +bool +OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject) +{ + const UnboxedLayout& layout = + templateObject->as().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; + return true; } @@ -4797,11 +4858,17 @@ MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandInd setResultType(MIRType::Object); setRecoveredOnBailout(); - MOZ_ASSERT(templateObject->is()); - - NativeObject* nativeObject = &templateObject->as(); - numSlots_ = nativeObject->slotSpan(); - numFixedSlots_ = nativeObject->numFixedSlots(); + if (templateObject->is()) { + NativeObject* nativeObject = &templateObject->as(); + numSlots_ = nativeObject->slotSpan(); + numFixedSlots_ = nativeObject->numFixedSlots(); + } else { + const UnboxedLayout& layout = + templateObject->as().layoutDontCheckGeneration(); + // Same as UnboxedLayout::makeNativeGroup + numSlots_ = layout.properties().length(); + numFixedSlots_ = gc::GetGCKindSlots(layout.getAllocKind()); + } operandIndex_ = operandIndex; } @@ -4838,21 +4905,39 @@ 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. - NativeObject& nativeObject = templateObject->as(); - MOZ_ASSERT(nativeObject.slotSpan() == numSlots()); - - MOZ_ASSERT(templateObject->is()); - 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; + if (templateObject->is()) { + UnboxedPlainObject& unboxedObject = templateObject->as(); + 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(); + 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); } - initSlot(i, def); } return true; } @@ -4863,7 +4948,14 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj) JSObject* templateObject = templateObjectOf(obj); MOZ_ASSERT(templateObject, "Unexpected object creation."); - MObjectState* res = new(alloc) MObjectState(templateObject, nullptr); + OperandIndexMap* operandIndex = nullptr; + if (templateObject->is()) { + operandIndex = new(alloc) OperandIndexMap; + if (!operandIndex || !operandIndex->init(alloc, templateObject)) + return nullptr; + } + + MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex); if (!res || !res->init(alloc, obj)) return nullptr; return res; @@ -5770,6 +5862,35 @@ 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) @@ -5824,6 +5945,8 @@ jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* o elementType = layout.elementType(); else return JSVAL_TYPE_MAGIC; + + key->watchStateChangeForUnboxedConvertedToNative(constraints); } return elementType; @@ -6447,6 +6570,23 @@ 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; @@ -6477,6 +6617,17 @@ 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; } -- cgit v1.2.3