From 5ee844f71001af821244696414bd92973f78fc09 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.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'js/src/jit/MIR.h') diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 0c1e77f80..cafdbab71 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -375,7 +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 - // typed object. + // typed object or unboxed object. DynamicSlot = 1 << 3, // A Value member of obj->slots. FixedSlot = 1 << 4, // A Value member of obj->fixedSlots(). DOMProperty = 1 << 5, // A DOM property @@ -3758,9 +3758,14 @@ class MObjectState { private: uint32_t numSlots_; - uint32_t numFixedSlots_; + uint32_t numFixedSlots_; // valid if isUnboxed() == false. + OperandIndexMap* operandIndex_; // valid if isUnboxed() == true. - MObjectState(JSObject *templateObject); + bool isUnboxed() const { + return operandIndex_ != nullptr; + } + + MObjectState(JSObject *templateObject, OperandIndexMap* operandIndex); explicit MObjectState(MObjectState* state); MOZ_MUST_USE bool init(TempAllocator& alloc, MDefinition* obj); @@ -3820,6 +3825,18 @@ 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; -- cgit v1.2.3 From dd57b9273c7c95a7cdabc94854c8dc63b0653f02 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.h | 188 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 168 insertions(+), 20 deletions(-) (limited to 'js/src/jit/MIR.h') diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index cafdbab71..ebc98a4f8 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -375,7 +375,8 @@ 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 - // typed object or unboxed object. + // a typed array, typed object, or unboxed + // object. DynamicSlot = 1 << 3, // A Value member of obj->slots. FixedSlot = 1 << 4, // A Value member of obj->fixedSlots(). DOMProperty = 1 << 5, // A DOM property @@ -432,6 +433,9 @@ 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 MDefinitionVector; @@ -8758,6 +8762,102 @@ 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, @@ -9251,19 +9351,23 @@ class MLoadElement ALLOW_CLONE(MLoadElement) }; -// Load a value from the elements vector of a native object. +// Load a value from the elements vector for a dense native or unboxed array. // 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, - bool needsHoleCheck) + JSValueType unboxedType, bool needsHoleCheck) : MTernaryInstruction(elements, index, initLength), + unboxedType_(unboxedType), needsNegativeIntCheck_(true), needsHoleCheck_(needsHoleCheck) { @@ -9285,6 +9389,9 @@ class MLoadElementHole TRIVIAL_NEW_WRAPPERS NAMED_OPERANDS((0, elements), (1, index), (2, initLength)) + JSValueType unboxedType() const { + return unboxedType_; + } bool needsNegativeIntCheck() const { return needsNegativeIntCheck_; } @@ -9295,6 +9402,8 @@ 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()) @@ -9302,7 +9411,7 @@ class MLoadElementHole return congruentIfOperandsEqual(other); } AliasSet getAliasSet() const override { - return AliasSet::Load(AliasSet::Element); + return AliasSet::Load(AliasSet::BoxedOrUnboxedElements(unboxedType())); } void collectRangeInfoPreTrunc() override; @@ -9482,17 +9591,20 @@ class MStoreElement ALLOW_CLONE(MStoreElement) }; -// 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. +// 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. class MStoreElementHole : public MAryInstruction<4>, public MStoreElementCommon, public MixPolicy >::Data { + JSValueType unboxedType_; + MStoreElementHole(MDefinition* object, MDefinition* elements, - MDefinition* index, MDefinition* value) + MDefinition* index, MDefinition* value, JSValueType unboxedType) + : unboxedType_(unboxedType) { initOperand(0, object); initOperand(1, elements); @@ -9507,6 +9619,10 @@ class MStoreElementHole TRIVIAL_NEW_WRAPPERS NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value)) + JSValueType unboxedType() const { + return unboxedType_; + } + ALLOW_CLONE(MStoreElementHole) }; @@ -9517,11 +9633,13 @@ class MFallibleStoreElement public MStoreElementCommon, public MixPolicy >::Data { + JSValueType unboxedType_; bool strict_; MFallibleStoreElement(MDefinition* object, MDefinition* elements, MDefinition* index, MDefinition* value, - bool strict) + JSValueType unboxedType, bool strict) + : unboxedType_(unboxedType) { initOperand(0, object); initOperand(1, elements); @@ -9537,6 +9655,10 @@ class MFallibleStoreElement TRIVIAL_NEW_WRAPPERS NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value)) + JSValueType unboxedType() const { + return unboxedType_; + } + bool strict() const { return strict_; } @@ -9640,12 +9762,13 @@ class MArrayPopShift private: Mode mode_; + JSValueType unboxedType_; bool needsHoleCheck_; bool maybeUndefined_; - MArrayPopShift(MDefinition* object, Mode mode, + MArrayPopShift(MDefinition* object, Mode mode, JSValueType unboxedType, bool needsHoleCheck, bool maybeUndefined) - : MUnaryInstruction(object), mode_(mode), + : MUnaryInstruction(object), mode_(mode), unboxedType_(unboxedType), needsHoleCheck_(needsHoleCheck), maybeUndefined_(maybeUndefined) { } @@ -9663,8 +9786,12 @@ class MArrayPopShift bool mode() const { return mode_; } + JSValueType unboxedType() const { + return unboxedType_; + } AliasSet getAliasSet() const override { - return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element); + return AliasSet::Store(AliasSet::ObjectFields | + AliasSet::BoxedOrUnboxedElements(unboxedType())); } ALLOW_CLONE(MArrayPopShift) @@ -9675,8 +9802,10 @@ class MArrayPush : public MBinaryInstruction, public MixPolicy >::Data { - MArrayPush(MDefinition* object, MDefinition* value) - : MBinaryInstruction(object, value) + JSValueType unboxedType_; + + MArrayPush(MDefinition* object, MDefinition* value, JSValueType unboxedType) + : MBinaryInstruction(object, value), unboxedType_(unboxedType) { setResultType(MIRType::Int32); } @@ -9686,8 +9815,12 @@ 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::Element); + return AliasSet::Store(AliasSet::ObjectFields | + AliasSet::BoxedOrUnboxedElements(unboxedType())); } void computeRange(TempAllocator& alloc) override; @@ -9701,13 +9834,15 @@ class MArraySlice { CompilerObject templateObj_; gc::InitialHeap initialHeap_; + JSValueType unboxedType_; MArraySlice(CompilerConstraintList* constraints, MDefinition* obj, MDefinition* begin, MDefinition* end, - JSObject* templateObj, gc::InitialHeap initialHeap) + JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType) : MTernaryInstruction(obj, begin, end), templateObj_(templateObj), - initialHeap_(initialHeap) + initialHeap_(initialHeap), + unboxedType_(unboxedType) { setResultType(MIRType::Object); } @@ -9725,6 +9860,10 @@ class MArraySlice return initialHeap_; } + JSValueType unboxedType() const { + return unboxedType_; + } + bool possiblyCalls() const override { return true; } @@ -12093,13 +12232,15 @@ class MInArray { bool needsHoleCheck_; bool needsNegativeIntCheck_; + JSValueType unboxedType_; MInArray(MDefinition* elements, MDefinition* index, MDefinition* initLength, MDefinition* object, - bool needsHoleCheck) + bool needsHoleCheck, JSValueType unboxedType) : MQuaternaryInstruction(elements, index, initLength, object), needsHoleCheck_(needsHoleCheck), - needsNegativeIntCheck_(true) + needsNegativeIntCheck_(true), + unboxedType_(unboxedType) { setResultType(MIRType::Boolean); setMovable(); @@ -12119,6 +12260,9 @@ class MInArray bool needsNegativeIntCheck() const { return needsNegativeIntCheck_; } + JSValueType unboxedType() const { + return unboxedType_; + } void collectRangeInfoPreTrunc() override; AliasSet getAliasSet() const override { return AliasSet::Load(AliasSet::Element); @@ -12131,6 +12275,8 @@ class MInArray return false; if (needsNegativeIntCheck() != other->needsNegativeIntCheck()) return false; + if (unboxedType() != other->unboxedType()) + return false; return congruentIfOperandsEqual(other); } }; @@ -14031,6 +14177,8 @@ 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); -- cgit v1.2.3 From ecdeefc4dd5624e824e696ac1c492c0b103f4acd 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.h | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'js/src/jit/MIR.h') diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index ebc98a4f8..af0abc695 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -30,6 +30,7 @@ #include "vm/EnvironmentObject.h" #include "vm/SharedMem.h" #include "vm/TypedArrayCommon.h" +#include "vm/UnboxedObject.h" // Undo windows.h damage on Win64 #undef MemoryBarrier @@ -9749,6 +9750,59 @@ 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, @@ -11128,6 +11182,11 @@ 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: @@ -11222,6 +11281,11 @@ 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: @@ -11330,6 +11394,73 @@ 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, -- cgit v1.2.3