| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- class BackwardPass;
- enum class ValueStructureKind
- {
- Generic,
- IntConstant,
- IntRange,
- IntBounded,
- FloatConstant,
- VarConstant,
- JsType,
- Array
- };
- class IntConstantValueInfo;
- class IntRangeValueInfo;
- class IntBoundedValueInfo;
- class FloatConstantValueInfo;
- class VarConstantValueInfo;
- class JsTypeValueInfo;
- class EquivalentTypeSetValueInfo;
- class ArrayValueInfo;
- class LoopCount;
- class GlobOpt;
- class ValueInfo : protected ValueType
- {
- private:
- const ValueStructureKind structureKind;
- Sym * symStore;
- protected:
- ValueInfo(const ValueType type, const ValueStructureKind structureKind)
- : ValueType(type), structureKind(structureKind)
- {
- // We can only prove that the representation is a tagged int on a ToVar. Currently, we cannot have more than one value
- // info per value number in a block, so a value info specifying tagged int representation cannot be created for a
- // specific sym. Instead, a value info can be shared by multiple syms, and hence cannot specify tagged int
- // representation. Currently, the tagged int representation info can only be carried on the dst opnd of ToVar, and can't
- // even be propagated forward.
- Assert(!type.IsTaggedInt());
- SetSymStore(nullptr);
- }
- private:
- ValueInfo(const ValueInfo &other, const bool)
- : ValueType(other), structureKind(ValueStructureKind::Generic) // uses generic structure kind, as opposed to copying the structure kind
- {
- SetSymStore(other.GetSymStore());
- }
- public:
- static ValueInfo * New(JitArenaAllocator *const alloc, const ValueType type)
- {
- return JitAnew(alloc, ValueInfo, type, ValueStructureKind::Generic);
- }
- const ValueType & Type() const { return *this; }
- ValueType & Type() { return *this; }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // ValueType imports. Only importing functions that are appropriate to be called on Value.
- public:
- using ValueType::IsUninitialized;
- using ValueType::IsDefinite;
- using ValueType::IsTaggedInt;
- using ValueType::IsIntAndLikelyTagged;
- using ValueType::IsLikelyTaggedInt;
- using ValueType::HasBeenUntaggedInt;
- using ValueType::IsIntAndLikelyUntagged;
- using ValueType::IsLikelyUntaggedInt;
- using ValueType::HasBeenInt;
- using ValueType::IsInt;
- using ValueType::IsLikelyInt;
- using ValueType::IsNotInt;
- using ValueType::IsNotNumber;
- using ValueType::HasBeenFloat;
- using ValueType::IsFloat;
- using ValueType::IsLikelyFloat;
- using ValueType::HasBeenNumber;
- using ValueType::IsNumber;
- using ValueType::IsLikelyNumber;
- using ValueType::HasBeenUnknownNumber;
- using ValueType::IsUnknownNumber;
- using ValueType::IsLikelyUnknownNumber;
- using ValueType::HasBeenUndefined;
- using ValueType::IsUndefined;
- using ValueType::IsLikelyUndefined;
- using ValueType::HasBeenNull;
- using ValueType::IsNull;
- using ValueType::IsLikelyNull;
- using ValueType::HasBeenBoolean;
- using ValueType::IsBoolean;
- using ValueType::IsLikelyBoolean;
- using ValueType::HasBeenString;
- using ValueType::IsString;
- using ValueType::IsLikelyString;
- using ValueType::IsNotString;
- using ValueType::HasBeenPrimitive;
- using ValueType::IsPrimitive;
- using ValueType::IsLikelyPrimitive;
- using ValueType::HasBeenObject;
- using ValueType::IsObject;
- using ValueType::IsLikelyObject;
- using ValueType::IsNotObject;
- using ValueType::CanMergeToObject;
- using ValueType::CanMergeToSpecificObjectType;
- using ValueType::IsRegExp;
- using ValueType::IsLikelyRegExp;
- using ValueType::IsArray;
- using ValueType::IsLikelyArray;
- using ValueType::IsNotArray;
- using ValueType::IsArrayOrObjectWithArray;
- using ValueType::IsLikelyArrayOrObjectWithArray;
- using ValueType::IsNotArrayOrObjectWithArray;
- using ValueType::IsNativeArray;
- using ValueType::IsLikelyNativeArray;
- using ValueType::IsNotNativeArray;
- using ValueType::IsNativeIntArray;
- using ValueType::IsLikelyNativeIntArray;
- using ValueType::IsNativeFloatArray;
- using ValueType::IsLikelyNativeFloatArray;
- using ValueType::IsTypedArray;
- using ValueType::IsLikelyTypedArray;
- using ValueType::IsOptimizedTypedArray;
- using ValueType::IsLikelyOptimizedTypedArray;
- using ValueType::IsLikelyOptimizedVirtualTypedArray;
- using ValueType::IsAnyArrayWithNativeFloatValues;
- using ValueType::IsLikelyAnyArrayWithNativeFloatValues;
- using ValueType::IsAnyArray;
- using ValueType::IsLikelyAnyArray;
- using ValueType::IsAnyOptimizedArray;
- using ValueType::IsLikelyAnyOptimizedArray;
- // The following apply to object types only
- using ValueType::GetObjectType;
- // The following apply to javascript array types only
- using ValueType::HasNoMissingValues;
- using ValueType::HasIntElements;
- using ValueType::HasFloatElements;
- using ValueType::HasVarElements;
- using ValueType::IsSimd128;
- using ValueType::IsSimd128Float32x4;
- using ValueType::IsSimd128Int32x4;
- using ValueType::IsSimd128Float64x2;
- using ValueType::IsLikelySimd128;
- using ValueType::IsLikelySimd128Float32x4;
- using ValueType::IsLikelySimd128Int32x4;
- using ValueType::IsLikelySimd128Float64x2;
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- public:
- bool IsGeneric() const;
- private:
- bool IsIntConstant() const;
- const IntConstantValueInfo * AsIntConstant() const;
- bool IsIntRange() const;
- const IntRangeValueInfo * AsIntRange() const;
- public:
- bool IsIntBounded() const;
- const IntBoundedValueInfo * AsIntBounded() const;
- bool IsFloatConstant() const;
- FloatConstantValueInfo * AsFloatConstant();
- const FloatConstantValueInfo * AsFloatConstant() const;
- bool IsVarConstant() const;
- VarConstantValueInfo * AsVarConstant();
- bool IsJsType() const;
- JsTypeValueInfo * AsJsType();
- const JsTypeValueInfo * AsJsType() const;
- #if FALSE
- bool IsObjectType() const;
- JsTypeValueInfo * AsObjectType();
- bool IsEquivalentTypeSet() const;
- EquivalentTypeSetValueInfo * AsEquivalentTypeSet();
- #endif
- bool IsArrayValueInfo() const;
- const ArrayValueInfo * AsArrayValueInfo() const;
- ArrayValueInfo * AsArrayValueInfo();
- public:
- bool HasIntConstantValue(const bool includeLikelyInt = false) const;
- bool TryGetIntConstantValue(int32 *const intValueRef, const bool includeLikelyInt = false) const;
- bool TryGetIntConstantLowerBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
- bool TryGetIntConstantUpperBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
- bool TryGetIntConstantBounds(IntConstantBounds *const intConstantBoundsRef, const bool includeLikelyInt = false) const;
- bool WasNegativeZeroPreventedByBailout() const;
- public:
- static bool IsEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- static bool IsNotEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- private:
- static bool IsEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- static bool IsNotEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- public:
- static bool IsGreaterThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- static bool IsGreaterThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- static bool IsLessThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- static bool IsLessThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
- public:
- static bool IsGreaterThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
- static bool IsLessThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
- private:
- static bool IsGreaterThanOrEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
- static bool IsLessThanOrEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
- public:
- ValueInfo *SpecializeToInt32(JitArenaAllocator *const allocator, const bool isForLoopBackEdgeCompensation = false);
- ValueInfo *SpecializeToFloat64(JitArenaAllocator *const allocator);
- // SIMD_JS
- ValueInfo *SpecializeToSimd128(IRType type, JitArenaAllocator *const allocator);
- ValueInfo *SpecializeToSimd128F4(JitArenaAllocator *const allocator);
- ValueInfo *SpecializeToSimd128I4(JitArenaAllocator *const allocator);
- public:
- Sym * GetSymStore() const { return this->symStore; }
- void SetSymStore(Sym * sym)
- {
- // Sym store should always be a var sym
- Assert(sym == nullptr || sym->IsPropertySym() || !sym->AsStackSym()->IsTypeSpec()); // property syms always have a var stack sym
- this->symStore = sym;
- }
- bool GetIsShared() const;
- void SetIsShared();
- ValueInfo * Copy(JitArenaAllocator * allocator);
- ValueInfo * CopyWithGenericStructureKind(JitArenaAllocator * allocator) const
- {
- return JitAnew(allocator, ValueInfo, *this, false);
- }
- bool GetIntValMinMax(int *pMin, int *pMax, bool doAggressiveIntTypeSpec);
- #if DBG_DUMP
- void Dump();
- #endif
- #if DBG
- // Add a vtable in debug builds so that the actual can been inspected easily in the debugger without having to manually cast
- virtual void AddVtable() { Assert(false); }
- #endif
- };
- class Value
- {
- private:
- const ValueNumber valueNumber;
- ValueInfo *valueInfo;
- protected:
- Value(const ValueNumber valueNumber, ValueInfo *valueInfo)
- : valueNumber(valueNumber), valueInfo(valueInfo)
- {
- };
- public:
- static Value *New(JitArenaAllocator *const allocator, const ValueNumber valueNumber, ValueInfo *valueInfo)
- {
- return JitAnew(allocator, Value, valueNumber, valueInfo);
- }
- ValueNumber GetValueNumber() const { return this->valueNumber; }
- ValueInfo * GetValueInfo() const { return this->valueInfo; }
- ValueInfo * ShareValueInfo() const { this->valueInfo->SetIsShared(); return this->valueInfo; }
- void SetValueInfo(ValueInfo * newValueInfo) { Assert(newValueInfo); this->valueInfo = newValueInfo; }
- Value * Copy(JitArenaAllocator * allocator, ValueNumber newValueNumber) { return Value::New(allocator, newValueNumber, this->ShareValueInfo()); }
- #if DBG_DUMP
- __declspec(noinline) void Dump() const { Output::Print(L"0x%X ValueNumber: %3d, -> ", this, this->valueNumber); this->valueInfo->Dump(); }
- #endif
- };
- template<>
- ValueNumber JsUtil::ValueToKey<ValueNumber, Value *>::ToKey(Value *const &value)
- {
- Assert(value);
- return value->GetValueNumber();
- }
- class IntConstantValueInfo : public ValueInfo
- {
- private:
- const int32 intValue;
- protected:
- IntConstantValueInfo(const int32 intValue)
- : ValueInfo(GetInt(IsTaggable(intValue)), ValueStructureKind::IntConstant),
- intValue(intValue)
- {
- }
- public:
- static IntConstantValueInfo *New(JitArenaAllocator *const allocator, const int32 intValue)
- {
- return JitAnew(allocator, IntConstantValueInfo, intValue);
- }
- IntConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
- {
- return JitAnew(allocator, IntConstantValueInfo, *this);
- }
- public:
- int32 IntValue() const
- {
- return intValue;
- }
- private:
- static bool IsTaggable(const int32 i)
- {
- #if INT32VAR
- // All 32-bit ints are taggable on 64-bit architectures
- return true;
- #else
- return i >= Js::Constants::Int31MinValue && i <= Js::Constants::Int31MaxValue;
- #endif
- }
- };
- class IntRangeValueInfo : public ValueInfo, public IntConstantBounds
- {
- private:
- // Definitely-int values are inherently not negative zero. This member variable, if true, indicates that this value was
- // produced by an int-specialized instruction that prevented a negative zero result using a negative zero bailout
- // (BailOutOnNegativeZero). Negative zero tracking in the dead-store phase tracks this information to see if some of these
- // negative zero bailout checks can be removed.
- bool wasNegativeZeroPreventedByBailout;
- protected:
- IntRangeValueInfo(
- const IntConstantBounds &constantBounds,
- const bool wasNegativeZeroPreventedByBailout,
- const ValueStructureKind structureKind = ValueStructureKind::IntRange)
- : ValueInfo(constantBounds.GetValueType(), structureKind),
- IntConstantBounds(constantBounds),
- wasNegativeZeroPreventedByBailout(wasNegativeZeroPreventedByBailout)
- {
- Assert(!wasNegativeZeroPreventedByBailout || constantBounds.LowerBound() <= 0 && constantBounds.UpperBound() >= 0);
- }
- public:
- static IntRangeValueInfo *New(
- JitArenaAllocator *const allocator,
- const int32 lowerBound,
- const int32 upperBound,
- const bool wasNegativeZeroPreventedByBailout)
- {
- return
- JitAnew(
- allocator,
- IntRangeValueInfo,
- IntConstantBounds(lowerBound, upperBound),
- wasNegativeZeroPreventedByBailout);
- }
- IntRangeValueInfo *Copy(JitArenaAllocator *const allocator) const
- {
- return JitAnew(allocator, IntRangeValueInfo, *this);
- }
- public:
- bool WasNegativeZeroPreventedByBailout() const
- {
- return wasNegativeZeroPreventedByBailout;
- }
- };
- class FloatConstantValueInfo : public ValueInfo
- {
- private:
- const FloatConstType floatValue;
- public:
- FloatConstantValueInfo(const FloatConstType floatValue)
- : ValueInfo(Float, ValueStructureKind::FloatConstant), floatValue(floatValue)
- {
- }
- static FloatConstantValueInfo *New(
- JitArenaAllocator *const allocator,
- const FloatConstType floatValue)
- {
- return JitAnew(allocator, FloatConstantValueInfo, floatValue);
- }
- FloatConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
- {
- return JitAnew(allocator, FloatConstantValueInfo, *this);
- }
- public:
- FloatConstType FloatValue() const
- {
- return floatValue;
- }
- };
- class VarConstantValueInfo : public ValueInfo
- {
- private:
- Js::Var const varValue;
- bool isFunction;
- public:
- VarConstantValueInfo(Js::Var varValue, ValueType valueType, bool isFunction = false)
- : ValueInfo(valueType, ValueStructureKind::VarConstant),
- varValue(varValue), isFunction(isFunction)
- {
- }
- static VarConstantValueInfo *New(JitArenaAllocator *const allocator, Js::Var varValue, ValueType valueType, bool isFunction = false)
- {
- return JitAnew(allocator, VarConstantValueInfo, varValue, valueType, isFunction);
- }
- VarConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
- {
- return JitAnew(allocator, VarConstantValueInfo, *this);
- }
- public:
- Js::Var VarValue() const
- {
- return this->varValue;
- }
- bool IsFunction() const
- {
- return this->isFunction;
- }
- };
- struct ObjectTypePropertyEntry
- {
- Js::ObjTypeSpecFldInfo* fldInfo;
- uint blockNumber;
- };
- typedef JsUtil::BaseDictionary<Js::PropertyId, ObjectTypePropertyEntry, JitArenaAllocator> ObjectTypePropertyMap;
- class JsTypeValueInfo : public ValueInfo
- {
- private:
- const Js::Type * jsType;
- Js::EquivalentTypeSet * jsTypeSet;
- bool isShared;
- public:
- JsTypeValueInfo(Js::Type * type)
- : ValueInfo(Uninitialized, ValueStructureKind::JsType),
- jsType(type), jsTypeSet(nullptr), isShared(false)
- {
- }
- JsTypeValueInfo(Js::EquivalentTypeSet * typeSet)
- : ValueInfo(Uninitialized, ValueStructureKind::JsType),
- jsType(nullptr), jsTypeSet(typeSet), isShared(false)
- {
- }
- JsTypeValueInfo(const JsTypeValueInfo& other)
- : ValueInfo(Uninitialized, ValueStructureKind::JsType),
- jsType(other.jsType), jsTypeSet(other.jsTypeSet)
- {
- }
- static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::Type * typeSet)
- {
- return JitAnew(allocator, JsTypeValueInfo, typeSet);
- }
- static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::EquivalentTypeSet * typeSet)
- {
- return JitAnew(allocator, JsTypeValueInfo, typeSet);
- }
- JsTypeValueInfo(const Js::Type* type, Js::EquivalentTypeSet * typeSet)
- : ValueInfo(Uninitialized, ValueStructureKind::JsType),
- jsType(type), jsTypeSet(typeSet), isShared(false)
- {
- }
- static JsTypeValueInfo * New(JitArenaAllocator *const allocator, const Js::Type* type, Js::EquivalentTypeSet * typeSet)
- {
- return JitAnew(allocator, JsTypeValueInfo, type, typeSet);
- }
- public:
- JsTypeValueInfo * Copy(JitArenaAllocator *const allocator) const
- {
- JsTypeValueInfo * newInfo = JitAnew(allocator, JsTypeValueInfo, *this);
- newInfo->isShared = false;
- return newInfo;
- }
- const Js::Type * GetJsType() const
- {
- return this->jsType;
- }
- void SetJsType(const Js::Type * value)
- {
- Assert(!this->isShared);
- this->jsType = value;
- }
- Js::EquivalentTypeSet * GetJsTypeSet() const
- {
- return this->jsTypeSet;
- }
- void SetJsTypeSet(Js::EquivalentTypeSet * value)
- {
- Assert(!this->isShared);
- this->jsTypeSet = value;
- }
- bool GetIsShared() const { return this->isShared; }
- void SetIsShared() { this->isShared = true; }
- };
- class ArrayValueInfo : public ValueInfo
- {
- private:
- StackSym *const headSegmentSym;
- StackSym *const headSegmentLengthSym;
- StackSym *const lengthSym;
- private:
- ArrayValueInfo(
- const ValueType valueType,
- StackSym *const headSegmentSym,
- StackSym *const headSegmentLengthSym,
- StackSym *const lengthSym,
- Sym *const symStore = nullptr)
- : ValueInfo(valueType, ValueStructureKind::Array),
- headSegmentSym(headSegmentSym),
- headSegmentLengthSym(headSegmentLengthSym),
- lengthSym(lengthSym)
- {
- Assert(valueType.IsAnyOptimizedArray());
- Assert(!(valueType.IsLikelyTypedArray() && !valueType.IsOptimizedTypedArray()));
- // For typed arrays, the head segment length is the same as the array length. For objects with internal arrays, the
- // length behaves like a regular object's property rather than like an array length.
- Assert(!lengthSym || valueType.IsLikelyArray());
- Assert(!lengthSym || lengthSym != headSegmentLengthSym);
- if(symStore)
- {
- SetSymStore(symStore);
- }
- }
- public:
- static ArrayValueInfo *New(
- JitArenaAllocator *const allocator,
- const ValueType valueType,
- StackSym *const headSegmentSym,
- StackSym *const headSegmentLengthSym,
- StackSym *const lengthSym,
- Sym *const symStore = nullptr)
- {
- Assert(allocator);
- return JitAnew(allocator, ArrayValueInfo, valueType, headSegmentSym, headSegmentLengthSym, lengthSym, symStore);
- }
- ValueInfo *Copy(
- JitArenaAllocator *const allocator,
- const bool copyHeadSegment = true,
- const bool copyHeadSegmentLength = true,
- const bool copyLength = true) const
- {
- Assert(allocator);
- return
- copyHeadSegment && headSegmentSym || copyHeadSegmentLength && headSegmentLengthSym || copyLength && lengthSym
- ? New(
- allocator,
- Type(),
- copyHeadSegment ? headSegmentSym : nullptr,
- copyHeadSegmentLength ? headSegmentLengthSym : nullptr,
- copyLength ? lengthSym : nullptr,
- GetSymStore())
- : CopyWithGenericStructureKind(allocator);
- }
- public:
- StackSym *HeadSegmentSym() const
- {
- return headSegmentSym;
- }
- StackSym *HeadSegmentLengthSym() const
- {
- return headSegmentLengthSym;
- }
- StackSym *LengthSym() const
- {
- return lengthSym;
- }
- IR::ArrayRegOpnd *CreateOpnd(
- IR::RegOpnd *const previousArrayOpnd,
- const bool needsHeadSegment,
- const bool needsHeadSegmentLength,
- const bool needsLength,
- const bool eliminatedLowerBoundCheck,
- const bool eliminatedUpperBoundCheck,
- Func *const func) const
- {
- Assert(previousArrayOpnd);
- Assert(func);
- return
- IR::ArrayRegOpnd::New(
- previousArrayOpnd,
- Type(),
- needsHeadSegment ? headSegmentSym : nullptr,
- needsHeadSegmentLength ? headSegmentLengthSym : nullptr,
- needsLength ? lengthSym : nullptr,
- eliminatedLowerBoundCheck,
- eliminatedUpperBoundCheck,
- func);
- }
- };
- class ExprAttributes
- {
- protected:
- uint32 attributes;
- public:
- ExprAttributes(const uint32 attributes = 0) : attributes(attributes)
- {
- }
- uint32 Attributes() const
- {
- return attributes;
- }
- private:
- static const uint32 BitMask(const uint index)
- {
- return 1u << index;
- }
- protected:
- void SetBitAttribute(const uint index, const bool bit)
- {
- if(bit)
- {
- attributes |= BitMask(index);
- }
- else
- {
- attributes &= ~BitMask(index);
- }
- }
- };
- class IntMathExprAttributes : public ExprAttributes
- {
- private:
- static const uint IgnoredIntOverflowIndex = 0;
- static const uint IgnoredNegativeZeroIndex = 1;
- public:
- IntMathExprAttributes(const ExprAttributes &exprAttributes) : ExprAttributes(exprAttributes)
- {
- }
- IntMathExprAttributes(const bool ignoredIntOverflow, const bool ignoredNegativeZero)
- {
- SetBitAttribute(IgnoredIntOverflowIndex, ignoredIntOverflow);
- SetBitAttribute(IgnoredNegativeZeroIndex, ignoredNegativeZero);
- }
- };
- class DstIsIntOrNumberAttributes : public ExprAttributes
- {
- private:
- static const uint DstIsIntOnlyIndex = 0;
- static const uint DstIsNumberOnlyIndex = 1;
- public:
- DstIsIntOrNumberAttributes(const ExprAttributes &exprAttributes) : ExprAttributes(exprAttributes)
- {
- }
- DstIsIntOrNumberAttributes(const bool dstIsIntOnly, const bool dstIsNumberOnly)
- {
- SetBitAttribute(DstIsIntOnlyIndex, dstIsIntOnly);
- SetBitAttribute(DstIsNumberOnlyIndex, dstIsNumberOnly);
- }
- };
- class ExprHash
- {
- public:
- ExprHash() { this->opcode = 0; }
- ExprHash(int init) { Assert(init == 0); this->opcode = 0; }
- void Init(Js::OpCode opcode, ValueNumber src1Val, ValueNumber src2Val, ExprAttributes exprAttributes)
- {
- extern uint8 OpCodeToHash[(int)Js::OpCode::Count];
- uint32 opCodeHash = OpCodeToHash[(int)opcode];
- this->opcode = opCodeHash;
- this->src1Val = src1Val;
- this->src2Val = src2Val;
- this->attributes = exprAttributes.Attributes();
- // Assert too many opcodes...
- AssertMsg(this->opcode == (uint32)opCodeHash, "Opcode value too large for CSEs");
- AssertMsg(this->attributes == exprAttributes.Attributes(), "Not enough bits for expr attributes");
- // If value numbers are too large, just give up
- if (this->src1Val != src1Val || this->src2Val != src2Val)
- {
- this->opcode = 0;
- this->src1Val = 0;
- this->src2Val = 0;
- this->attributes = 0;
- }
- }
- Js::OpCode GetOpcode() { return (Js::OpCode)this->opcode; }
- ValueNumber GetSrc1ValueNumber() { return this->src1Val; }
- ValueNumber GetSrc2ValueNumber() { return this->src2Val; }
- ExprAttributes GetExprAttributes() { return this->attributes; }
- bool IsValid() { return this->opcode != 0; }
- operator uint() { return *(uint*)this; }
- private:
- uint32 opcode: 8;
- uint32 src1Val: 11;
- uint32 src2Val: 11;
- uint32 attributes: 2;
- };
- enum class PathDependentRelationship : uint8
- {
- Equal,
- NotEqual,
- GreaterThanOrEqual,
- GreaterThan,
- LessThanOrEqual,
- LessThan
- };
- class PathDependentInfo
- {
- private:
- Value *leftValue, *rightValue;
- int32 rightConstantValue;
- PathDependentRelationship relationship;
- public:
- PathDependentInfo(const PathDependentRelationship relationship, Value *const leftValue, Value *const rightValue)
- : relationship(relationship), leftValue(leftValue), rightValue(rightValue)
- {
- Assert(leftValue);
- Assert(rightValue);
- }
- PathDependentInfo(
- const PathDependentRelationship relationship,
- Value *const leftValue,
- Value *const rightValue,
- const int32 rightConstantValue)
- : relationship(relationship), leftValue(leftValue), rightValue(rightValue), rightConstantValue(rightConstantValue)
- {
- Assert(leftValue);
- }
- public:
- bool HasInfo() const
- {
- return !!leftValue;
- }
- PathDependentRelationship Relationship() const
- {
- Assert(HasInfo());
- return relationship;
- }
- Value *LeftValue() const
- {
- Assert(HasInfo());
- return leftValue;
- }
- Value *RightValue() const
- {
- Assert(HasInfo());
- return rightValue;
- }
- int32 RightConstantValue() const
- {
- Assert(!RightValue());
- return rightConstantValue;
- }
- };
- class PathDependentInfoToRestore
- {
- private:
- ValueInfo *leftValueInfo, *rightValueInfo;
- public:
- PathDependentInfoToRestore() : leftValueInfo(nullptr), rightValueInfo(nullptr)
- {
- }
- PathDependentInfoToRestore(ValueInfo *const leftValueInfo, ValueInfo *const rightValueInfo)
- : leftValueInfo(leftValueInfo), rightValueInfo(rightValueInfo)
- {
- }
- public:
- ValueInfo *LeftValueInfo() const
- {
- return leftValueInfo;
- }
- ValueInfo *RightValueInfo() const
- {
- return rightValueInfo;
- }
- public:
- void Clear()
- {
- leftValueInfo = nullptr;
- rightValueInfo = nullptr;
- }
- };
- typedef JsUtil::List<IR::Opnd *, JitArenaAllocator> OpndList;
- typedef JsUtil::BaseDictionary<Sym *, ValueInfo *, JitArenaAllocator> SymToValueInfoMap;
- typedef JsUtil::BaseDictionary<SymID, IR::Instr *, JitArenaAllocator> SymIdToInstrMap;
- typedef JsUtil::BaseHashSet<Value *, JitArenaAllocator> ValueSet;
- typedef JsUtil::BaseHashSet<Value *, JitArenaAllocator, PowerOf2SizePolicy, ValueNumber> ValueSetByValueNumber;
- typedef JsUtil::BaseDictionary<SymID, StackSym *, JitArenaAllocator> SymIdToStackSymMap;
- typedef JsUtil::Pair<ValueNumber, ValueNumber> ValueNumberPair;
- typedef JsUtil::BaseDictionary<ValueNumberPair, Value *, JitArenaAllocator> ValueNumberPairToValueMap;
- #include "GlobHashTable.h"
- typedef ValueHashTable<Sym *, Value *> GlobHashTable;
- typedef HashBucket<Sym *, Value *> GlobHashBucket;
- typedef ValueHashTable<ExprHash, Value *> ExprHashTable;
- typedef HashBucket<ExprHash, Value *> ExprHashBucket;
- struct StackLiteralInitFldData
- {
- const Js::PropertyIdArray * propIds;
- uint currentInitFldCount;
- };
- namespace JsUtil
- {
- template <>
- class ValueEntry<StackLiteralInitFldData> : public BaseValueEntry<StackLiteralInitFldData>
- {
- public:
- void Clear()
- {
- #if DBG
- this->value.propIds = nullptr;
- this->value.currentInitFldCount = (uint)-1;
- #endif
- }
- };
- };
- typedef JsUtil::BaseDictionary<StackSym *, StackLiteralInitFldData, JitArenaAllocator> StackLiteralInitFldDataMap;
- typedef SList<GlobHashBucket*, JitArenaAllocator> PRECandidatesList;
- class GlobOptBlockData
- {
- public:
- GlobOptBlockData(Func *func) :
- symToValueMap(nullptr),
- exprToValueMap(nullptr),
- liveFields(nullptr),
- liveArrayValues(nullptr),
- maybeWrittenTypeSyms(nullptr),
- liveVarSyms(nullptr),
- liveInt32Syms(nullptr),
- liveLossyInt32Syms(nullptr),
- liveFloat64Syms(nullptr),
- liveSimd128F4Syms(nullptr),
- liveSimd128I4Syms(nullptr),
- hoistableFields(nullptr),
- argObjSyms(nullptr),
- maybeTempObjectSyms(nullptr),
- canStoreTempObjectSyms(nullptr),
- valuesToKillOnCalls(nullptr),
- inductionVariables(nullptr),
- availableIntBoundChecks(nullptr),
- startCallCount(0),
- argOutCount(0),
- totalOutParamCount(0),
- callSequence(nullptr),
- hasCSECandidates(false),
- curFunc(func),
- hasDataRef(nullptr),
- stackLiteralInitFldDataMap(nullptr)
- {
- }
- // Data
- GlobHashTable * symToValueMap;
- ExprHashTable * exprToValueMap;
- BVSparse<JitArenaAllocator> * liveFields;
- BVSparse<JitArenaAllocator> * liveArrayValues;
- BVSparse<JitArenaAllocator> * maybeWrittenTypeSyms;
- BVSparse<JitArenaAllocator> * isTempSrc;
- BVSparse<JitArenaAllocator> * liveVarSyms;
- BVSparse<JitArenaAllocator> * liveInt32Syms;
- // 'liveLossyInt32Syms' includes only syms that contain an int value that may not fully represent the value of the
- // equivalent var sym. The set (liveInt32Syms - liveLossyInt32Syms) includes only syms that contain an int value that fully
- // represents the value of the equivalent var sym, such as when (a + 1) is type-specialized. Among other things, this
- // bit-vector is used, based on the type of conversion that is needed, to determine whether conversion is necessary, and if
- // so, whether a bailout is needed. For instance, after type-specializing (a | 0), the int32 sym of 'a' cannot be reused in
- // (a + 1) during type-specialization. It needs to be converted again using a lossless conversion with a bailout.
- // Conversely, a lossless int32 sym can be reused to avoid a lossy conversion.
- BVSparse<JitArenaAllocator> * liveLossyInt32Syms;
- BVSparse<JitArenaAllocator> * liveFloat64Syms;
- // SIMD_JS
- BVSparse<JitArenaAllocator> * liveSimd128F4Syms;
- BVSparse<JitArenaAllocator> * liveSimd128I4Syms;
- BVSparse<JitArenaAllocator> * hoistableFields;
- BVSparse<JitArenaAllocator> * argObjSyms;
- BVSparse<JitArenaAllocator> * maybeTempObjectSyms;
- BVSparse<JitArenaAllocator> * canStoreTempObjectSyms;
- Func * curFunc;
- // 'valuesToKillOnCalls' includes values whose value types need to be killed upon a call. Upon a call, the value types of
- // values in the set are updated and removed from the set as appropriate.
- ValueSet * valuesToKillOnCalls;
- InductionVariableSet * inductionVariables;
- IntBoundCheckSet * availableIntBoundChecks;
- // Bailout data
- uint startCallCount;
- uint argOutCount;
- uint totalOutParamCount;
- SListBase<IR::Opnd *> * callSequence;
- StackLiteralInitFldDataMap * stackLiteralInitFldDataMap;
- uint inlinedArgOutCount;
- bool hasCSECandidates;
- private:
- bool * hasDataRef;
- public:
- void OnDataInitialized(JitArenaAllocator *const allocator)
- {
- Assert(allocator);
- hasDataRef = JitAnew(allocator, bool, true);
- }
- void OnDataReused(GlobOptBlockData *const fromData)
- {
- // If a block's data is deleted, *hasDataRef will be set to false. Since these two blocks are pointing to the same data,
- // they also need to point to the same has-data info.
- hasDataRef = fromData->hasDataRef;
- }
- void OnDataUnreferenced()
- {
- // Other blocks may still be using the data, we should only un-reference the previous data
- hasDataRef = nullptr;
- }
- void OnDataDeleted()
- {
- if(hasDataRef)
- *hasDataRef = false;
- OnDataUnreferenced();
- }
- bool HasData()
- {
- if(!hasDataRef)
- return false;
- if(*hasDataRef)
- return true;
- OnDataUnreferenced();
- return false;
- }
- // SIMD_JS
- BVSparse<JitArenaAllocator> * GetSimd128LivenessBV(IRType type)
- {
- switch (type)
- {
- case TySimd128F4:
- return liveSimd128F4Syms;
- case TySimd128I4:
- return liveSimd128I4Syms;
- default:
- Assert(UNREACHED);
- return nullptr;
- }
- }
- };
- typedef JsUtil::BaseDictionary<IntConstType, StackSym *, JitArenaAllocator> IntConstantToStackSymMap;
- typedef JsUtil::BaseDictionary<IntConstType, Value *, JitArenaAllocator> IntConstantToValueMap;
- typedef JsUtil::BaseDictionary<Js::Var, Value *, JitArenaAllocator> AddrConstantToValueMap;
- typedef JsUtil::BaseDictionary<Js::InternalString, Value *, JitArenaAllocator> StringConstantToValueMap;
- class JsArrayKills
- {
- private:
- union
- {
- struct
- {
- bool killsAllArrays : 1;
- bool killsArraysWithNoMissingValues : 1;
- bool killsNativeArrays : 1;
- bool killsArrayHeadSegments : 1;
- bool killsArrayHeadSegmentLengths : 1;
- bool killsArrayLengths : 1;
- };
- byte bits;
- };
- public:
- JsArrayKills() : bits(0)
- {
- }
- private:
- JsArrayKills(const byte bits) : bits(bits)
- {
- }
- public:
- bool KillsAllArrays() const { return killsAllArrays; }
- void SetKillsAllArrays() { killsAllArrays = true; }
- bool KillsArraysWithNoMissingValues() const { return killsArraysWithNoMissingValues; }
- void SetKillsArraysWithNoMissingValues() { killsArraysWithNoMissingValues = true; }
- bool KillsNativeArrays() const { return killsNativeArrays; }
- void SetKillsNativeArrays() { killsNativeArrays = true; }
- bool KillsArrayHeadSegments() const { return killsArrayHeadSegments; }
- void SetKillsArrayHeadSegments() { killsArrayHeadSegments = true; }
- bool KillsArrayHeadSegmentLengths() const { return killsArrayHeadSegmentLengths; }
- void SetKillsArrayHeadSegmentLengths() { killsArrayHeadSegmentLengths = true; }
- bool KillsTypedArrayHeadSegmentLengths() const { return KillsAllArrays(); }
- bool KillsArrayLengths() const { return killsArrayLengths; }
- void SetKillsArrayLengths() { killsArrayLengths = true; }
- public:
- bool KillsValueType(const ValueType valueType) const
- {
- Assert(valueType.IsArrayOrObjectWithArray());
- return
- killsAllArrays ||
- killsArraysWithNoMissingValues && valueType.HasNoMissingValues() ||
- killsNativeArrays && !valueType.HasVarElements();
- }
- bool AreSubsetOf(const JsArrayKills &other) const
- {
- return (bits & other.bits) == bits;
- }
- JsArrayKills Merge(const JsArrayKills &other)
- {
- return bits | other.bits;
- }
- };
- class InvariantBlockBackwardIterator
- {
- private:
- GlobOpt *const globOpt;
- BasicBlock *const exclusiveEndBlock;
- StackSym *const invariantSym;
- const ValueNumber invariantSymValueNumber;
- BasicBlock *block;
- Value *invariantSymValue;
- #if DBG
- BasicBlock *const inclusiveEndBlock;
- #endif
- public:
- InvariantBlockBackwardIterator(GlobOpt *const globOpt, BasicBlock *const exclusiveBeginBlock, BasicBlock *const inclusiveEndBlock, StackSym *const invariantSym, const ValueNumber invariantSymValueNumber = InvalidValueNumber);
- public:
- bool IsValid() const;
- void MoveNext();
- BasicBlock *Block() const;
- Value *InvariantSymValue() const;
- PREVENT_ASSIGN(InvariantBlockBackwardIterator);
- };
- class GlobOpt
- {
- private:
- class AddSubConstantInfo;
- class ArrayLowerBoundCheckHoistInfo;
- class ArrayUpperBoundCheckHoistInfo;
- friend BackwardPass;
- #if DBG
- friend class ObjectTempVerify;
- #endif
- private:
- SparseArray<Value> * byteCodeConstantValueArray;
- // Global bitvectors
- BVSparse<JitArenaAllocator> * byteCodeConstantValueNumbersBv;
- // Global bitvectors
- IntConstantToStackSymMap * intConstantToStackSymMap;
- IntConstantToValueMap* intConstantToValueMap;
- AddrConstantToValueMap * addrConstantToValueMap;
- StringConstantToValueMap * stringConstantToValueMap;
- #if DBG
- // We can still track the finished stack literal InitFld lexically.
- BVSparse<JitArenaAllocator> * finishedStackLiteralInitFld;
- #endif
- BVSparse<JitArenaAllocator> * byteCodeUses;
- BVSparse<JitArenaAllocator> * tempBv; // Bit vector for temporary uses
- BVSparse<JitArenaAllocator> * objectTypeSyms;
- BVSparse<JitArenaAllocator> * prePassCopyPropSym; // Symbols that were copy prop'd during loop prepass
- PropertySym * propertySymUse;
- BVSparse<JitArenaAllocator> * lengthEquivBv;
- BVSparse<JitArenaAllocator> * argumentsEquivBv;
- GlobOptBlockData blockData;
- JitArenaAllocator * alloc;
- JitArenaAllocator * tempAlloc;
- Func * func;
- ValueNumber currentValue;
- BasicBlock * currentBlock;
- Region * currentRegion;
- IntOverflowDoesNotMatterRange *intOverflowDoesNotMatterRange;
- Loop * prePassLoop;
- Loop * rootLoopPrePass;
- uint instrCountSinceLastCleanUp;
- SymIdToInstrMap * prePassInstrMap;
- SymID maxInitialSymID;
- bool isCallHelper: 1;
- bool intOverflowCurrentlyMattersInRange : 1;
- bool ignoredIntOverflowForCurrentInstr : 1;
- bool ignoredNegativeZeroForCurrentInstr : 1;
- bool inInlinedBuiltIn : 1;
- bool isRecursiveCallOnLandingPad : 1;
- bool updateInductionVariableValueNumber : 1;
- bool isPerformingLoopBackEdgeCompensation : 1;
- bool doTypeSpec : 1;
- bool doAggressiveIntTypeSpec : 1;
- bool doAggressiveMulIntTypeSpec : 1;
- bool doDivIntTypeSpec : 1;
- bool doLossyIntTypeSpec : 1;
- bool doFloatTypeSpec : 1;
- bool doArrayCheckHoist : 1;
- bool doArrayMissingValueCheckHoist : 1;
- bool doArraySegmentHoist : 1;
- bool doJsArraySegmentHoist : 1;
- bool doArrayLengthHoist : 1;
- bool doEliminateArrayAccessHelperCall : 1;
- bool doTrackRelativeIntBounds : 1;
- bool doBoundCheckElimination : 1;
- bool doBoundCheckHoist : 1;
- bool doLoopCountBasedBoundCheckHoist : 1;
- bool isAsmJSFunc : 1;
- OpndList * noImplicitCallUsesToInsert;
- ValueSetByValueNumber * valuesCreatedForClone;
- ValueNumberPairToValueMap *valuesCreatedForMerge;
- #if DBG
- BVSparse<JitArenaAllocator> * byteCodeUsesBeforeOpt;
- #endif
- public:
- GlobOpt(Func * func);
- void Optimize();
- // Return whether the instruction transfer value from the src to the dst for copy prop
- static bool TransferSrcValue(IR::Instr * instr);
- // Function used by the backward pass as well.
- // GlobOptBailout.cpp
- static void TrackByteCodeSymUsed(IR::Instr * instr, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed, PropertySym **pPropertySym);
- // GlobOptFields.cpp
- void ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt);
- static bool DoFieldHoisting(Loop * loop);
- IR::ByteCodeUsesInstr * ConvertToByteCodeUses(IR::Instr * isntr);
- bool GetIsAsmJSFunc()const{ return isAsmJSFunc; };
- private:
- bool IsLoopPrePass() const { return this->prePassLoop != nullptr; }
- void OptBlock(BasicBlock *block);
- void BackwardPass(Js::Phase tag);
- void ForwardPass();
- void OptLoops(Loop *loop);
- void TailDupPass();
- bool TryTailDup(IR::BranchInstr *tailBranch);
- void CleanUpValueMaps();
- PRECandidatesList * FindBackEdgePRECandidates(BasicBlock *block, JitArenaAllocator *alloc);
- PRECandidatesList * RemoveUnavailableCandidates(BasicBlock *block, PRECandidatesList *candidates, JitArenaAllocator *alloc);
- PRECandidatesList * FindPossiblePRECandidates(Loop *loop, JitArenaAllocator *alloc);
- void PreloadPRECandidates(Loop *loop, PRECandidatesList *candidates);
- BOOL PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate);
- void SetLoopFieldInitialValue(Loop *loop, IR::Instr *instr, PropertySym *propertySym, PropertySym *originalPropertySym);
- void FieldPRE(Loop *loop);
- void MergePredBlocksValueMaps(BasicBlock *block);
- void NulloutBlockData(GlobOptBlockData *data);
- void InitBlockData();
- void ReuseBlockData(GlobOptBlockData *toData, GlobOptBlockData *fromData);
- void CopyBlockData(GlobOptBlockData *toData, GlobOptBlockData *fromData);
- void CloneBlockData(BasicBlock *const toBlock, BasicBlock *const fromBlock);
- void CloneBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock);
- void CloneValues(BasicBlock *const toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
- void MergeBlockData(GlobOptBlockData *toData, BasicBlock *toBlock, BasicBlock *fromBlock, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
- void DeleteBlockData(GlobOptBlockData *data);
- IR::Instr * OptInstr(IR::Instr *&instr, bool* isInstrCleared);
- Value* OptDst(IR::Instr **pInstr, Value *dstVal, Value *src1Val, Value *src2Val, Value *dstIndirIndexVal, Value *src1IndirIndexVal);
- void CopyPropDstUses(IR::Opnd *opnd, IR::Instr *instr, Value *src1Val);
- Value * OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef = nullptr, IR::IndirOpnd *parentIndirOpnd = nullptr);
- void MarkArgumentsUsedForBranch(IR::Instr *inst);
- bool OptTagChecks(IR::Instr *instr);
- void TryOptimizeInstrWithFixedDataProperty(IR::Instr * * const pInstr);
- bool CheckIfPropOpEmitsTypeCheck(IR::Instr *instr, IR::PropertySymOpnd *opnd);
- bool FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block = nullptr, bool updateExistingValue = false, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr);
- void FinishOptHoistedPropOps(Loop * loop);
- IR::Instr * SetTypeCheckBailOut(IR::Opnd *opnd, IR::Instr *instr, BailOutInfo *bailOutInfo);
- void OptArguments(IR::Instr *Instr);
- BOOLEAN IsArgumentsOpnd(IR::Opnd* opnd);
- bool AreFromSameBytecodeFunc(IR::RegOpnd* src1, IR::RegOpnd* dst);
- void TrackArgumentsSym(IR::RegOpnd* opnd);
- void ClearArgumentsSym(IR::RegOpnd* opnd);
- BOOLEAN TestAnyArgumentsSym();
- BOOLEAN IsArgumentsSymID(SymID id, const GlobOptBlockData& blockData);
- Value * ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
- Value * ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
- ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool *const isValueInfoPreciseRef = nullptr) const;
- bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue) const;
- Value * CreateDstUntransferredIntValue(const int32 min, const int32 max, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
- Value * CreateDstUntransferredValue(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
- Value * ValueNumberTransferDst(IR::Instr *const instr, Value *src1Val);
- bool IsSafeToTransferInPrePass(IR::Opnd *src, Value *srcValue);
- Value * ValueNumberTransferDstInPrepass(IR::Instr *const instr, Value *const src1Val);
- Value * FindValue(Sym *sym);
- Value * FindValue(GlobHashTable *valueNumberMap, Sym *sym);
- ValueNumber FindValueNumber(GlobHashTable *valueNumberMap, Sym *sym);
- Value * FindValueFromHashTable(GlobHashTable *valueNumberMap, SymID symId);
- ValueNumber FindPropertyValueNumber(GlobHashTable *valueNumberMap, SymID symId);
- Value * FindPropertyValue(GlobHashTable *valueNumberMap, SymID symId);
- Value * FindObjectTypeValue(StackSym* typeSym);
- Value * FindObjectTypeValue(StackSym* typeSym, GlobHashTable *valueNumberMap);
- Value * FindObjectTypeValue(SymID typeSymId, GlobHashTable *valueNumberMap);
- Value * FindObjectTypeValue(StackSym* typeSym, BasicBlock* block);
- Value* FindObjectTypeValue(SymID typeSymId, BasicBlock* block);
- Value * FindObjectTypeValue(StackSym* typeSym, GlobHashTable *valueNumberMap, BVSparse<JitArenaAllocator>* liveFields);
- Value * FindObjectTypeValue(SymID typeSymId, GlobHashTable *valueNumberMap, BVSparse<JitArenaAllocator>* liveFields);
- Value * FindFuturePropertyValue(PropertySym *const propertySym);
- IR::Opnd * CopyProp(IR::Opnd *opnd, IR::Instr *instr, Value *val, IR::IndirOpnd *parentIndirOpnd = nullptr);
- IR::Opnd * CopyPropReplaceOpnd(IR::Instr * instr, IR::Opnd * opnd, StackSym * copySym, IR::IndirOpnd *parentIndirOpnd = nullptr);
- StackSym * GetCopyPropSym(Sym * sym, Value * val);
- StackSym * GetCopyPropSym(BasicBlock * block, Sym * sym, Value * val);
- void MarkTempLastUse(IR::Instr *instr, IR::RegOpnd *regOpnd);
- ValueNumber NewValueNumber();
- Value * NewValue(ValueInfo *const valueInfo);
- Value * NewValue(const ValueNumber valueNumber, ValueInfo *const valueInfo);
- Value * CopyValue(Value *const value);
- Value * CopyValue(Value *const value, const ValueNumber valueNumber);
- Value * NewGenericValue(const ValueType valueType);
- Value * NewGenericValue(const ValueType valueType, IR::Opnd *const opnd);
- Value * NewGenericValue(const ValueType valueType, Sym *const sym);
- Value * GetIntConstantValue(const int32 intConst, IR::Instr * instr, IR::Opnd *const opnd = nullptr);
- Value * NewIntConstantValue(const int32 intConst, IR::Instr * instr, bool isTaggable);
- ValueInfo * NewIntRangeValueInfo(const int32 min, const int32 max, const bool wasNegativeZeroPreventedByBailout);
- ValueInfo * NewIntRangeValueInfo(const ValueInfo *const originalValueInfo, const int32 min, const int32 max) const;
- Value * NewIntRangeValue(const int32 min, const int32 max, const bool wasNegativeZeroPreventedByBailout, IR::Opnd *const opnd = nullptr);
- IntBoundedValueInfo * NewIntBoundedValueInfo(const ValueInfo *const originalValueInfo, const IntBounds *const bounds) const;
- Value * NewIntBoundedValue(const ValueType valueType, const IntBounds *const bounds, const bool wasNegativeZeroPreventedByBailout, IR::Opnd *const opnd = nullptr);
- Value * NewFloatConstantValue(const FloatConstType floatValue, IR::Opnd *const opnd = nullptr);
- Value * GetVarConstantValue(IR::AddrOpnd *addrOpnd);
- Value * NewVarConstantValue(IR::AddrOpnd *addrOpnd, bool isString);
- Value * HoistConstantLoadAndPropagateValueBackward(Js::Var varConst, IR::Instr * origInstr, Value * value);
- Value * NewFixedFunctionValue(Js::JavascriptFunction *functionValue, IR::AddrOpnd *addrOpnd);
- StackSym * GetTaggedIntConstantStackSym(const int32 intConstantValue) const;
- StackSym * GetOrCreateTaggedIntConstantStackSym(const int32 intConstantValue) const;
- Sym * SetSymStore(ValueInfo *valueInfo, Sym *sym);
- Value * InsertNewValue(Value *val, IR::Opnd *opnd);
- Value * InsertNewValue(GlobOptBlockData * blockData, Value *val, IR::Opnd *opnd);
- Value * SetValue(GlobOptBlockData * blockData, Value *val, IR::Opnd *opnd);
- void SetValue(GlobOptBlockData * blockData, Value *val, Sym * sym);
- void SetValueToHashTable(GlobHashTable * valueNumberMap, Value *val, Sym *sym);
- IR::Instr * TypeSpecialization(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal, bool *redoTypeSpecRef, bool *const forceInvariantHoistingRef);
- // SIMD_JS
- bool TypeSpecializeSimd128(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal);
- bool Simd128DoTypeSpec(IR::Instr *instr, const Value *src1Val, const Value *src2Val, const Value *dstVal);
- bool Simd128CanTypeSpecOpnd(const ValueType opndType, const ValueType expectedType);
- IRType GetIRTypeFromValueType(const ValueType &valueType);
- ValueType GetValueTypeFromIRType(const IRType &type);
- IR::BailOutKind GetBailOutKindFromValueType(const ValueType &valueType);
- IR::Instr * GetExtendedArg(IR::Instr *instr);
- IR::Instr * OptNewScObject(IR::Instr** instrPtr, Value* srcVal);
- bool OptConstFoldBinary(IR::Instr * *pInstr, const IntConstantBounds &src1IntConstantBounds, const IntConstantBounds &src2IntConstantBounds, Value **pDstVal);
- bool OptConstFoldUnary(IR::Instr * *pInstr, const int32 intConstantValue, const bool isUsingOriginalSrc1Value, Value **pDstVal);
- bool OptConstPeep(IR::Instr *instr, IR::Opnd *constSrc, Value **pDstVal, ValueInfo *vInfo);
- bool OptConstFoldBranch(IR::Instr *instr, Value *src1Val, Value*src2Val, Value **pDstVal);
- Js::Var GetConstantVar(IR::Opnd *opnd, Value *val);
- bool IsWorthSpecializingToInt32DueToSrc(IR::Opnd *const src, Value *const val);
- bool IsWorthSpecializingToInt32DueToDst(IR::Opnd *const dst);
- bool IsWorthSpecializingToInt32(IR::Instr *const instr, Value *const src1Val, Value *const src2Val = nullptr);
- bool TypeSpecializeNumberUnary(IR::Instr *instr, Value *src1Val, Value **pDstVal);
- bool TypeSpecializeIntUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, int32 min, int32 max, Value *const src1OriginalVal, bool *redoTypeSpecRef, bool skipDst = false);
- bool TypeSpecializeIntBinary(IR::Instr **pInstr, Value *src1Val, Value *src2Val, Value **pDstVal, int32 min, int32 max, bool skipDst = false);
- void TypeSpecializeInlineBuiltInUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, Value *const src1OriginalVal, bool *redoTypeSpecRef);
- void TypeSpecializeInlineBuiltInBinary(IR::Instr **pInstr, Value *src1Val, Value* src2Val, Value **pDstVal, Value *const src1OriginalVal, Value *const src2OriginalVal);
- void TypeSpecializeInlineBuiltInDst(IR::Instr **pInstr, Value **pDstVal);
- bool TypeSpecializeUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, Value *const src1OriginalVal, bool *redoTypeSpecRef, bool *const forceInvariantHoistingRef);
- bool TypeSpecializeBinary(IR::Instr **pInstr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal, Value *const src1OriginalVal, Value *const src2OriginalVal, bool *redoTypeSpecRef);
- bool TypeSpecializeFloatUnary(IR::Instr **pInstr, Value *src1Val, Value **pDstVal, bool skipDst = false);
- bool TypeSpecializeFloatBinary(IR::Instr *instr, Value *src1Val, Value *src2Val, Value **pDstVal);
- void TypeSpecializeFloatDst(IR::Instr *instr, Value *valToTransfer, Value *const src1Value, Value *const src2Value, Value **pDstVal);
- bool TypeSpecializeLdLen(IR::Instr * *const instrRef, Value * *const src1ValueRef, Value * *const dstValueRef, bool *const forceInvariantHoistingRef);
- void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, int32 newMin, int32 newMax, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
- void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, ValueType valueType, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
- void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, ValueType valueType, int32 newMin, int32 newMax, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
- bool TryTypeSpecializeUnaryToFloatHelper(IR::Instr** pInstr, Value** pSrc1Val, Value* const src1OriginalVal, Value **pDstVal);
- bool TypeSpecializeBailoutExpectedInteger(IR::Instr* instr, Value* src1Val, Value** dstVal);
- bool TypeSpecializeStElem(IR::Instr **pInstr, Value *src1Val, Value **pDstVal);
- bool TryGetIntConstIndexValue(IR::Instr *instr, IR::IndirOpnd *indirOpnd, bool checkSym, int32 *pValue, bool *isNotInt);
- bool ShouldExpectConventionalArrayIndexValue(IR::IndirOpnd *const indirOpnd);
- ValueType GetDivValueType(IR::Instr* instr, Value* src1Val, Value* src2Val, bool specialize);
- bool CollectMemOpInfo(IR::Instr *, Value *, Value *);
- bool CollectMemOpStElementI(IR::Instr *, Loop *);
- bool CollectMemsetStElementI(IR::Instr *, Loop *);
- bool CollectMemcopyStElementI(IR::Instr *, Loop *);
- bool CollectMemOpLdElementI(IR::Instr *, Loop *);
- bool CollectMemcopyLdElementI(IR::Instr *, Loop *);
- SymID GetVarSymID(StackSym *);
- const InductionVariable* GetInductionVariable(SymID, Loop *);
- bool IsSymIDInductionVariable(SymID, Loop *);
- bool IsAllowedForMemOpt(IR::Instr* instr, bool isMemset, IR::RegOpnd *baseOpnd, IR::Opnd *indexOpnd);
- void ProcessMemOp();
- bool InspectInstrForMemSetCandidate(Loop* loop, IR::Instr* instr, struct MemSetEmitData* emitData, bool& errorInInstr);
- bool InspectInstrForMemCopyCandidate(Loop* loop, IR::Instr* instr, struct MemCopyEmitData* emitData, bool& errorInInstr);
- bool ValidateMemOpCandidates(Loop * loop, struct MemOpEmitData** emitData, int& iEmitData);
- void HoistHeadSegmentForMemOp(IR::Instr *instr, IR::ArrayRegOpnd *arrayRegOpnd, IR::Instr *insertBeforeInstr);
- void EmitMemop(Loop * loop, LoopCount *loopCount, const struct MemOpEmitData* emitData);
- IR::Opnd* GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::Instr *insertBeforeInstr = nullptr);
- IR::RegOpnd* GenerateStartIndexOpndForMemop(Loop *loop, IR::Opnd *indexOpnd, IR::Opnd *sizeOpnd, bool isInductionVariableChangeIncremental, bool bIndexAlreadyChanged, IR::Instr *insertBeforeInstr = nullptr);
- LoopCount* GetOrGenerateLoopCountForMemOp(Loop *loop);
- IR::Instr* FindUpperBoundsCheckInstr(IR::Instr* instr);
- IR::Instr* FindArraySegmentLoadInstr(IR::Instr* instr);
- void RemoveMemOpSrcInstr(IR::Instr* memopInstr, IR::Instr* srcInstr, BasicBlock* block);
- void GetMemOpSrcInfo(Loop* loop, IR::Instr* instr, IR::RegOpnd*& base, IR::RegOpnd*& index, IRType& arrayType);
- bool DoMemOp(Loop * loop);
- private:
- void ChangeValueType(BasicBlock *const block, Value *const value, const ValueType newValueType, const bool preserveSubclassInfo, const bool allowIncompatibleType = false) const;
- void ChangeValueInfo(BasicBlock *const block, Value *const value, ValueInfo *const newValueInfo, const bool allowIncompatibleType = false) const;
- bool AreValueInfosCompatible(const ValueInfo *const v0, const ValueInfo *const v1) const;
- private:
- void VerifyArrayValueInfoForTracking(const ValueInfo *const valueInfo, const bool isJsArray, const BasicBlock *const block, const bool ignoreKnownImplicitCalls = false) const;
- void TrackNewValueForKills(Value *const value);
- void DoTrackNewValueForKills(Value *const value);
- void TrackCopiedValueForKills(Value *const value);
- void DoTrackCopiedValueForKills(Value *const value);
- void TrackMergedValueForKills(Value *const value, GlobOptBlockData *const blockData, BVSparse<JitArenaAllocator> *const mergedValueTypesTrackedForKills) const;
- void DoTrackMergedValueForKills(Value *const value, GlobOptBlockData *const blockData, BVSparse<JitArenaAllocator> *const mergedValueTypesTrackedForKills) const;
- void TrackValueInfoChangeForKills(BasicBlock *const block, Value *const value, ValueInfo *const newValueInfo) const;
- void ProcessValueKills(IR::Instr *const instr);
- void ProcessValueKills(BasicBlock *const block, GlobOptBlockData *const blockData);
- void ProcessValueKillsForLoopHeaderAfterBackEdgeMerge(BasicBlock *const block, GlobOptBlockData *const blockData);
- bool NeedBailOnImplicitCallForLiveValues(BasicBlock *const block, const bool isForwardPass) const;
- IR::Instr* CreateBoundsCheckInstr(IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset, Func* func);
- IR::Instr* CreateBoundsCheckInstr(IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset, IR::BailOutKind bailoutkind, BailOutInfo* bailoutInfo, Func* func);
- IR::Instr* AttachBoundsCheckData(IR::Instr* instr, IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset);
- void OptArraySrc(IR::Instr * *const instrRef);
- private:
- void TrackIntSpecializedAddSubConstant(IR::Instr *const instr, const AddSubConstantInfo *const addSubConstantInfo, Value *const dstValue, const bool updateSourceBounds);
- void CloneBoundCheckHoistBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock, GlobOptBlockData *const fromData);
- void MergeBoundCheckHoistBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock, GlobOptBlockData *const fromData);
- void DetectUnknownChangesToInductionVariables(GlobOptBlockData *const blockData);
- void SetInductionVariableValueNumbers(GlobOptBlockData *const blockData);
- void FinalizeInductionVariables(Loop *const loop, GlobOptBlockData *const headerData);
- bool DetermineSymBoundOffsetOrValueRelativeToLandingPad(StackSym *const sym, const bool landingPadValueIsLowerBound, ValueInfo *const valueInfo, const IntBounds *const bounds, GlobHashTable *const landingPadSymToValueMap, int *const boundOffsetOrValueRef);
- private:
- void DetermineDominatingLoopCountableBlock(Loop *const loop, BasicBlock *const headerBlock);
- void DetermineLoopCount(Loop *const loop);
- void GenerateLoopCount(Loop *const loop, LoopCount *const loopCount);
- void GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCount);
- void GenerateSecondaryInductionVariableBound(Loop *const loop, StackSym *const inductionVariableSym, const LoopCount *const loopCount, const int maxMagnitudeChange, StackSym *const boundSym);
- private:
- void DetermineArrayBoundCheckHoistability(bool needLowerBoundCheck, bool needUpperBoundCheck, ArrayLowerBoundCheckHoistInfo &lowerHoistInfo, ArrayUpperBoundCheckHoistInfo &upperHoistInfo, const bool isJsArray, StackSym *const indexSym, Value *const indexValue, const IntConstantBounds &indexConstantBounds, StackSym *const headSegmentLengthSym, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, Loop *const headSegmentLengthInvariantLoop, bool &failedToUpdateCompatibleLowerBoundCheck, bool &failedToUpdateCompatibleUpperBoundCheck);
- private:
- void CaptureNoImplicitCallUses(IR::Opnd *opnd, const bool usesNoMissingValuesInfo, IR::Instr *const includeCurrentInstr = nullptr);
- void InsertNoImplicitCallUses(IR::Instr *const instr);
- void PrepareLoopArrayCheckHoist();
- public:
- JsArrayKills CheckJsArrayKills(IR::Instr *const instr);
- private:
- bool IsOperationThatLikelyKillsJsArraysWithNoMissingValues(IR::Instr *const instr);
- bool NeedBailOnImplicitCallForArrayCheckHoist(BasicBlock *const block, const bool isForwardPass) const;
- private:
- bool PrepareForIgnoringIntOverflow(IR::Instr *const instr);
- void VerifyIntSpecForIgnoringIntOverflow(IR::Instr *const instr);
- void PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val);
- void ProcessKills(IR::Instr *instr);
- void MergeValueMaps(GlobOptBlockData *toData, BasicBlock *toBlock, BasicBlock *fromBlock, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
- Value * MergeValues(Value *toDataValueMap, Value *fromDataValueMap, Sym *fromDataSym, GlobOptBlockData *toData, GlobOptBlockData *fromData, bool isLoopBackEdge, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
- ValueInfo * MergeValueInfo(Value *toDataVal, Value *fromDataVal, Sym *fromDataSym, GlobOptBlockData *fromData, bool isLoopBackEdge, bool sameValueNumber, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
- ValueInfo * MergeLikelyIntValueInfo(Value *toDataVal, Value *fromDataVal, const ValueType newValueType);
- JsTypeValueInfo * MergeJsTypeValueInfo(JsTypeValueInfo * toValueInfo, JsTypeValueInfo * fromValueInfo, bool isLoopBackEdge, bool sameValueNumber);
- ValueInfo * MergeArrayValueInfo(const ValueType mergedValueType, const ArrayValueInfo *const toDataValueInfo, const ArrayValueInfo *const fromDataValueInfo, Sym *const arraySym, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
- void InsertCloneStrs(BasicBlock *toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
- void InsertValueCompensation(BasicBlock *const predecessor, const SymToValueInfoMap &symsRequiringCompensationToMergedValueInfoMap);
- IR::Instr * ToVarUses(IR::Instr *instr, IR::Opnd *opnd, bool isDst, Value *val);
- void ToVar(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
- IR::Instr * ToVar(IR::Instr *instr, IR::RegOpnd *regOpnd, BasicBlock *block, Value *val, bool needsUpdate);
- void ToInt32(BVSparse<JitArenaAllocator> *bv, BasicBlock *block, bool lossy, IR::Instr *insertBeforeInstr = nullptr);
- void ToFloat64(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
- void ToTypeSpec(BVSparse<JitArenaAllocator> *bv, BasicBlock *block, IRType toType, IR::BailOutKind bailOutKind = IR::BailOutInvalid, bool lossy = false, IR::Instr *insertBeforeInstr = nullptr);
- IR::Instr * ToInt32(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir, bool lossy);
- IR::Instr * ToFloat64(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir, IR::BailOutKind bailOutKind);
- IR::Instr * ToTypeSpecUse(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir,
- IRType toType, IR::BailOutKind bailOutKind, bool lossy = false, IR::Instr *insertBeforeInstr = nullptr);
- void ToVarRegOpnd(IR::RegOpnd *dst, BasicBlock *block);
- void ToVarStackSym(StackSym *varSym, BasicBlock *block);
- void ToInt32Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
- void ToUInt32Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
- void ToFloat64Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
- // SIMD_JS
- void TypeSpecializeSimd128Dst(IRType type, IR::Instr *instr, Value *valToTransfer, Value *const src1Value, Value **pDstVal);
- void ToSimd128Dst(IRType toType, IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
- static BOOL IsInt32TypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsInt32TypeSpecialized(Sym *sym, GlobOptBlockData *data);
- static BOOL IsSwitchInt32TypeSpecialized(IR::Instr * instr, BasicBlock * block);
- static BOOL IsFloat64TypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsFloat64TypeSpecialized(Sym *sym, GlobOptBlockData *data);
- // SIMD_JS
- static BOOL IsSimd128TypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsSimd128TypeSpecialized(Sym *sym, GlobOptBlockData *data);
- static BOOL IsSimd128TypeSpecialized(IRType type, Sym *sym, BasicBlock *block);
- static BOOL IsSimd128TypeSpecialized(IRType type, Sym *sym, GlobOptBlockData *data);
- static BOOL IsSimd128F4TypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsSimd128F4TypeSpecialized(Sym *sym, GlobOptBlockData *data);
- static BOOL IsSimd128I4TypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsSimd128I4TypeSpecialized(Sym *sym, GlobOptBlockData *data);
- static BOOL IsLiveAsSimd128(Sym *sym, GlobOptBlockData *data);
- static BOOL IsLiveAsSimd128F4(Sym *sym, GlobOptBlockData *data);
- static BOOL IsLiveAsSimd128I4(Sym *sym, GlobOptBlockData *data);
- static BOOL IsTypeSpecialized(Sym *sym, BasicBlock *block);
- static BOOL IsTypeSpecialized(Sym *sym, GlobOptBlockData *data);
- static BOOL IsLive(Sym *sym, BasicBlock *block);
- static BOOL IsLive(Sym *sym, GlobOptBlockData *data);
- void MakeLive(StackSym *const sym, GlobOptBlockData *const blockData, const bool lossy) const;
- void OptConstFoldBr(bool test, IR::Instr *instr, Value * intTypeSpecSrc1Val = nullptr, Value * intTypeSpecSrc2Val = nullptr);
- void PropagateIntRangeForNot(int32 minimum, int32 maximum, int32 *pNewMin, int32 * pNewMax);
- void PropagateIntRangeBinary(IR::Instr *instr, int32 min1, int32 max1,
- int32 min2, int32 max2, int32 *pNewMin, int32 *pNewMax);
- bool OptIsInvariant(IR::Opnd *src, BasicBlock *block, Loop *loop, Value *srcVal, bool isNotTypeSpecConv, bool allowNonPrimitives);
- bool OptIsInvariant(Sym *sym, BasicBlock *block, Loop *loop, Value *srcVal, bool isNotTypeSpecConv, bool allowNonPrimitives, Value **loopHeadValRef = nullptr);
- bool OptDstIsInvariant(IR::RegOpnd *dst);
- bool OptIsInvariant(IR::Instr *instr, BasicBlock *block, Loop *loop, Value *src1Val, Value *src2Val, bool isNotTypeSpecConv, const bool forceInvariantHoisting = false);
- void OptHoistInvariant(IR::Instr *instr, BasicBlock *block, Loop *loop, Value *dstVal, Value *const src1Val, bool isNotTypeSpecConv, bool lossy = false);
- bool TryHoistInvariant(IR::Instr *instr, BasicBlock *block, Value *dstVal, Value *src1Val, Value *src2Val, bool isNotTypeSpecConv, const bool lossy = false, const bool forceInvariantHoisting = false);
- void HoistInvariantValueInfo(ValueInfo *const invariantValueInfoToHoist, Value *const valueToUpdate, BasicBlock *const targetBlock);
- public:
- static bool IsTypeSpecPhaseOff(Func* func);
- static bool DoAggressiveIntTypeSpec(Func* func);
- static bool DoLossyIntTypeSpec(Func* func);
- static bool DoFloatTypeSpec(Func* func);
- static bool DoStringTypeSpec(Func* func);
- static bool DoArrayCheckHoist(Func *const func);
- static bool DoArrayMissingValueCheckHoist(Func *const func);
- static bool DoArraySegmentHoist(const ValueType baseValueType, Func *const func);
- static bool DoArrayLengthHoist(Func *const func);
- static bool DoTypedArrayTypeSpec(Func* func);
- static bool DoNativeArrayTypeSpec(Func* func);
- static bool IsSwitchOptEnabled(Func* func);
- static bool DoEquivObjTypeSpec(Func* func);
- static bool DoInlineArgsOpt(Func* func);
- static bool IsPREInstrCandidateLoad(Js::OpCode opcode);
- static bool IsPREInstrCandidateStore(Js::OpCode opcode);
- static bool ImplicitCallFlagsAllowOpts(Loop * loop);
- static bool ImplicitCallFlagsAllowOpts(Func *func);
- private:
- bool DoConstFold() const;
- bool DoTypeSpec() const;
- bool DoAggressiveIntTypeSpec() const;
- bool DoAggressiveMulIntTypeSpec() const;
- bool DoDivIntTypeSpec() const;
- bool DoLossyIntTypeSpec() const;
- bool DoFloatTypeSpec() const;
- bool DoStringTypeSpec() const { return GlobOpt::DoStringTypeSpec(this->func); }
- bool DoArrayCheckHoist() const;
- bool DoArrayCheckHoist(const ValueType baseValueType, Loop* loop, IR::Instr *const instr = nullptr) const;
- bool DoArrayMissingValueCheckHoist() const;
- bool DoArraySegmentHoist(const ValueType baseValueType) const;
- bool DoTypedArraySegmentLengthHoist(Loop *const loop) const;
- bool DoArrayLengthHoist() const;
- bool DoEliminateArrayAccessHelperCall() const;
- bool DoTypedArrayTypeSpec() const { return GlobOpt::DoTypedArrayTypeSpec(this->func); }
- bool DoNativeArrayTypeSpec() const { return GlobOpt::DoNativeArrayTypeSpec(this->func); }
- bool DoLdLenIntSpec(IR::Instr *const instr, const ValueType baseValueType) const;
- bool IsSwitchOptEnabled() const { return GlobOpt::IsSwitchOptEnabled(this->func); }
- bool DoPathDependentValues() const;
- bool DoTrackRelativeIntBounds() const;
- bool DoBoundCheckElimination() const;
- bool DoBoundCheckHoist() const;
- bool DoLoopCountBasedBoundCheckHoist() const;
- private:
- // GlobOptBailout.cpp
- bool MayNeedBailOut(Loop * loop) const;
- static void TrackByteCodeSymUsed(IR::Opnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed, PropertySym **pPropertySymUse);
- static void TrackByteCodeSymUsed(IR::RegOpnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
- static void TrackByteCodeSymUsed(StackSym * sym, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
- void CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo);
- void CaptureValue(BasicBlock *block, StackSym * stackSym, Value * value, BailOutInfo * bailOutInfo);
- void CaptureArguments(BasicBlock *block, BailOutInfo * bailOutInfo, JitArenaAllocator *allocator);
- void CaptureByteCodeSymUses(IR::Instr * instr);
- IR::ByteCodeUsesInstr * InsertByteCodeUses(IR::Instr * instr, bool includeDef = false);
- void TrackCalls(IR::Instr * instr);
- void RecordInlineeFrameInfo(IR::Instr* instr);
- void EndTrackCall(IR::Instr * instr);
- void EndTrackingOfArgObjSymsForInlinee();
- void FillBailOutInfo(BasicBlock *block, BailOutInfo *bailOutInfo);
- static void MarkNonByteCodeUsed(IR::Instr * instr);
- static void MarkNonByteCodeUsed(IR::Opnd * opnd);
- bool IsImplicitCallBailOutCurrentlyNeeded(IR::Instr * instr, Value *src1Val, Value *src2Val);
- bool IsImplicitCallBailOutCurrentlyNeeded(IR::Instr * instr, Value *src1Val, Value *src2Val, BasicBlock * block, bool hasLiveFields, bool mayNeedImplicitCallBailOut, bool isForwardPass);
- static bool IsTypeCheckProtected(const IR::Instr * instr);
- static bool MayNeedBailOnImplicitCall(const IR::Instr * instr, Value *src1Val, Value *src2Val);
- static bool MayNeedBailOnImplicitCall(IR::Opnd * opnd, Value *val, bool callsToPrimitive);
- void GenerateBailAfterOperation(IR::Instr * *const pInstr, IR::BailOutKind kind);
- public:
- void GenerateBailAtOperation(IR::Instr * *const pInstr, const IR::BailOutKind bailOutKind);
- private:
- IR::Instr * EnsureBailTarget(Loop * loop);
- // GlobOptFields.cpp
- void ProcessFieldKills(IR::Instr * instr);
- void KillLiveFields(StackSym * stackSym, BVSparse<JitArenaAllocator> * bv);
- void KillLiveFields(PropertySym * propertySym, BVSparse<JitArenaAllocator> * bv);
- void KillLiveFields(BVSparse<JitArenaAllocator> *const propertyEquivSet, BVSparse<JitArenaAllocator> *const bv) const;
- void KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func);
- void KillAllFields(BVSparse<JitArenaAllocator> * bv);
- void SetAnyPropertyMayBeWrittenTo();
- void AddToPropertiesWrittenTo(Js::PropertyId propertyId);
- bool DoFieldCopyProp() const;
- bool DoFieldCopyProp(Loop * loop) const;
- bool DoFunctionFieldCopyProp() const;
- bool DoFieldHoisting() const;
- bool DoObjTypeSpec() const;
- bool DoObjTypeSpec(Loop * loop) const;
- bool DoEquivObjTypeSpec() const { return DoEquivObjTypeSpec(this->func); }
- bool DoFieldRefOpts() const { return DoObjTypeSpec(); }
- bool DoFieldRefOpts(Loop * loop) const { return DoObjTypeSpec(loop); }
- bool DoFieldOpts(Loop * loop) const;
- bool DoFieldPRE() const;
- bool DoFieldPRE(Loop *loop) const;
- bool FieldHoistOptSrc(IR::Opnd *opnd, IR::Instr *instr, PropertySym * propertySym);
- void FieldHoistOptDst(IR::Instr * instr, PropertySym * propertySym, Value * src1Val);
- bool TrackHoistableFields() const;
- void PreparePrepassFieldHoisting(Loop * loop);
- void PrepareFieldHoisting(Loop * loop);
- void CheckFieldHoistCandidate(IR::Instr * instr, PropertySym * sym);
- Loop * FindFieldHoistStackSym(Loop * startLoop, SymID propertySymId, StackSym ** copySym, IR::Instr * instrToHoist = nullptr) const;
- bool CopyPropHoistedFields(PropertySym * sym, IR::Opnd ** ppOpnd, IR::Instr * instr);
- void HoistFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, Value * oldValue, Value * newValue);
- void HoistNewFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, Value * oldValue, Value * newValue);
- void GenerateHoistFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, StackSym * newStackSym, Value * oldValue, Value * newValue);
- void HoistFieldLoadValue(Loop * loop, Value * newValue, SymID symId, Js::OpCode opcode, IR::Opnd * srcOpnd);
- void ReloadFieldHoistStackSym(IR::Instr * instr, PropertySym * propertySym);
- void CopyStoreFieldHoistStackSym(IR::Instr * storeFldInstr, PropertySym * sym, Value * src1Val);
- Value * CreateFieldSrcValue(PropertySym * sym, PropertySym * originalSym, IR::Opnd **ppOpnd, IR::Instr * instr);
- static bool HasHoistableFields(BasicBlock * block);
- static bool HasHoistableFields(GlobOptBlockData const * globOptData);
- bool IsHoistablePropertySym(SymID symId) const;
- bool NeedBailOnImplicitCallWithFieldOpts(Loop *loop, bool hasLiveFields) const;
- IR::Instr * EnsureDisableImplicitCallRegion(Loop * loop);
- void UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr);
- bool TrackArgumentsObject();
- void CannotAllocateArgumentsObjectOnStack();
- #if DBG
- bool IsPropertySymId(SymID symId) const;
- bool IsHoistedPropertySym(PropertySym * sym) const;
- bool IsHoistedPropertySym(SymID symId, Loop * loop) const;
- static void AssertCanCopyPropOrCSEFieldLoad(IR::Instr * instr);
- #endif
- StackSym * EnsureObjectTypeSym(StackSym * objectSym);
- PropertySym * EnsurePropertyWriteGuardSym(PropertySym * propertySym);
- void PreparePropertySymForTypeCheckSeq(PropertySym *propertySym);
- bool IsPropertySymPreparedForTypeCheckSeq(PropertySym *propertySym);
- bool PreparePropertySymOpndForTypeCheckSeq(IR::PropertySymOpnd *propertySymOpnd, IR::Instr * instr, Loop *loop);
- static bool AreTypeSetsIdentical(Js::EquivalentTypeSet * leftTypeSet, Js::EquivalentTypeSet * rightTypeSet);
- static bool IsSubsetOf(Js::EquivalentTypeSet * leftTypeSet, Js::EquivalentTypeSet * rightTypeSet);
- bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd);
- bool CheckIfInstrInTypeCheckSeqEmitsTypeCheck(IR::Instr* instr, IR::PropertySymOpnd *opnd);
- template<bool makeChanges>
- bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr, bool *isObjTypeChecked = nullptr);
- void KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecialized, SymID symId = (SymID)-1);
- void ValueNumberObjectType(IR::Opnd *dstOpnd, IR::Instr *instr);
- void SetSingleTypeOnObjectTypeValue(Value* value, const Js::Type* type);
- void SetTypeSetOnObjectTypeValue(Value* value, Js::EquivalentTypeSet* typeSet);
- void UpdateObjectTypeValue(Value* value, const Js::Type* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet);
- void SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* block = nullptr);
- void SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr, bool updateExistingValue = false);
- void SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue = false);
- void KillObjectType(StackSym *objectSym, BVSparse<JitArenaAllocator>* liveFields = nullptr);
- void KillAllObjectTypes(BVSparse<JitArenaAllocator>* liveFields = nullptr);
- void EndFieldLifetime(IR::SymOpnd *symOpnd);
- PropertySym * CopyPropPropertySymObj(IR::SymOpnd *opnd, IR::Instr *instr);
- static bool NeedsTypeCheckBailOut(const IR::Instr *instr, IR::PropertySymOpnd *propertySymOpnd, bool isStore, bool* pIsTypeCheckProtected, IR::BailOutKind *pBailOutKind);
- IR::Instr * PreOptPeep(IR::Instr *instr);
- IR::Instr * OptPeep(IR::Instr *instr, Value *src1Val, Value *src2Val);
- void OptimizeIndirUses(IR::IndirOpnd *indir, IR::Instr * *pInstr, Value **indirIndexValRef);
- void RemoveCodeAfterNoFallthroughInstr(IR::Instr *instr);
- void ProcessTryCatch(IR::Instr* instr);
- void InsertToVarAtDefInTryRegion(IR::Instr * instr, IR::Opnd * dstOpnd);
- void RemoveFlowEdgeToCatchBlock(IR::Instr * instr);
- void CSEAddInstr(BasicBlock *block, IR::Instr *instr, Value *dstVal, Value *src1Val, Value *src2Val, Value *dstIndirIndexVal, Value *src1IndirIndexVal);
- bool CSEOptimize(BasicBlock *block, IR::Instr * *const instrRef, Value **pSrc1Val, Value **pSrc2Val, Value **pSrc1IndirIndexVal, bool intMathExprOnly = false);
- bool GetHash(IR::Instr *instr, Value *src1Val, Value *src2Val, ExprAttributes exprAttributes, ExprHash *pHash);
- void ProcessArrayValueKills(IR::Instr *instr);
- static bool NeedBailOnImplicitCallForCSE(BasicBlock *block, bool isForwardPass);
- bool DoCSE();
- bool CanCSEArrayStore(IR::Instr *instr);
- #if DBG_DUMP
- void Dump();
- void DumpSymToValueMap();
- void DumpSymToValueMap(GlobHashTable* symToValueMap);
- void DumpSymToValueMap(BasicBlock *block);
- static void DumpSym(Sym *sym);
- void DumpSymVal(int index);
- void Trace(BasicBlock * basicBlock, bool before);
- void TraceSettings();
- #endif
- bool IsWorthSpecializingToInt32Branch(IR::Instr * instr, Value * src1Val, Value * src2Val);
- bool TryOptConstFoldBrFalse(IR::Instr *const instr, Value *const srcValue, const int32 min, const int32 max);
- bool TryOptConstFoldBrEqual(IR::Instr *const instr, const bool branchOnEqual, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
- bool TryOptConstFoldBrGreaterThan(IR::Instr *const instr, const bool branchOnGreaterThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
- bool TryOptConstFoldBrGreaterThanOrEqual(IR::Instr *const instr, const bool branchOnGreaterThanOrEqual, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
- bool TryOptConstFoldBrUnsignedLessThan(IR::Instr *const instr, const bool branchOnLessThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
- bool TryOptConstFoldBrUnsignedGreaterThan(IR::Instr *const instr, const bool branchOnGreaterThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
- void UpdateIntBoundsForEqualBranch(Value *const src1Value, Value *const src2Value, const int32 src2ConstantValue = 0);
- void UpdateIntBoundsForNotEqualBranch(Value *const src1Value, Value *const src2Value, const int32 src2ConstantValue = 0);
- void UpdateIntBoundsForGreaterThanOrEqualBranch(Value *const src1Value, Value *const src2Value);
- void UpdateIntBoundsForGreaterThanBranch(Value *const src1Value, Value *const src2Value);
- void UpdateIntBoundsForLessThanOrEqualBranch(Value *const src1Value, Value *const src2Value);
- void UpdateIntBoundsForLessThanBranch(Value *const src1Value, Value *const src2Value);
- IntBounds * GetIntBoundsToUpdate(const ValueInfo *const valueInfo, const IntConstantBounds &constantBounds, const bool isSettingNewBound, const bool isBoundConstant, const bool isSettingUpperBound, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForNotEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForGreaterThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForGreaterThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const int boundOffset, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForGreaterThan(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForLessThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForLessThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const int boundOffset, const bool isExplicit);
- ValueInfo * UpdateIntBoundsForLessThan(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
- void SetPathDependentInfo(const bool conditionToBranch, const PathDependentInfo &info);
- PathDependentInfoToRestore UpdatePathDependentInfo(PathDependentInfo *const info);
- void RestorePathDependentInfo(PathDependentInfo *const info, const PathDependentInfoToRestore infoToRestore);
- IR::Instr * TrackMarkTempObject(IR::Instr * instrStart, IR::Instr * instrEnd);
- void TrackTempObjectSyms(IR::Instr * instr, IR::RegOpnd * opnd);
- IR::Instr * GenerateBailOutMarkTempObjectIfNeeded(IR::Instr * instr, IR::Opnd * opnd, bool isDst);
- bool IsDefinedInCurrentLoopIteration(Loop *loop, Value *val) const;
- void KillStateForGeneratorYield();
- static void InstantiateForceInlinedMembers_GlobOptIntBounds();
- friend class InvariantBlockBackwardIterator;
- };
|