ValueInfo.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. enum class ValueStructureKind
  7. {
  8. Generic,
  9. IntConstant,
  10. Int64Constant,
  11. IntRange,
  12. IntBounded,
  13. FloatConstant,
  14. VarConstant,
  15. JsType,
  16. Array
  17. };
  18. class IntConstantValueInfo;
  19. class Int64ConstantValueInfo;
  20. class IntRangeValueInfo;
  21. class IntBoundedValueInfo;
  22. class FloatConstantValueInfo;
  23. class VarConstantValueInfo;
  24. class JsTypeValueInfo;
  25. class EquivalentTypeSetValueInfo;
  26. class ArrayValueInfo;
  27. class ValueInfo : protected ValueType
  28. {
  29. private:
  30. const ValueStructureKind structureKind;
  31. Sym * symStore;
  32. protected:
  33. ValueInfo(const ValueType type, const ValueStructureKind structureKind)
  34. : ValueType(type), structureKind(structureKind)
  35. {
  36. // We can only prove that the representation is a tagged int on a ToVar. Currently, we cannot have more than one value
  37. // info per value number in a block, so a value info specifying tagged int representation cannot be created for a
  38. // specific sym. Instead, a value info can be shared by multiple syms, and hence cannot specify tagged int
  39. // representation. Currently, the tagged int representation info can only be carried on the dst opnd of ToVar, and can't
  40. // even be propagated forward.
  41. Assert(!type.IsTaggedInt());
  42. SetSymStore(nullptr);
  43. }
  44. private:
  45. ValueInfo(const ValueInfo &other, const bool)
  46. : ValueType(other), structureKind(ValueStructureKind::Generic) // uses generic structure kind, as opposed to copying the structure kind
  47. {
  48. SetSymStore(other.GetSymStore());
  49. }
  50. public:
  51. static ValueInfo * New(JitArenaAllocator *const alloc, const ValueType type)
  52. {
  53. return JitAnew(alloc, ValueInfo, type, ValueStructureKind::Generic);
  54. }
  55. static ValueInfo * MergeLikelyIntValueInfo(JitArenaAllocator* alloc, Value *toDataVal, Value *fromDataVal, const ValueType newValueType);
  56. static ValueInfo * NewIntRangeValueInfo(JitArenaAllocator* alloc, int32 min, int32 max, bool wasNegativeZeroPreventedByBailout);
  57. const ValueType & Type() const { return *this; }
  58. ValueType & Type() { return *this; }
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. // ValueType imports. Only importing functions that are appropriate to be called on Value.
  61. public:
  62. using ValueType::IsUninitialized;
  63. using ValueType::IsDefinite;
  64. using ValueType::IsTaggedInt;
  65. using ValueType::IsIntAndLikelyTagged;
  66. using ValueType::IsLikelyTaggedInt;
  67. using ValueType::HasBeenUntaggedInt;
  68. using ValueType::IsIntAndLikelyUntagged;
  69. using ValueType::IsLikelyUntaggedInt;
  70. using ValueType::HasBeenInt;
  71. using ValueType::IsInt;
  72. using ValueType::IsLikelyInt;
  73. using ValueType::IsNotInt;
  74. using ValueType::IsNotNumber;
  75. using ValueType::HasBeenFloat;
  76. using ValueType::IsFloat;
  77. using ValueType::IsLikelyFloat;
  78. using ValueType::HasBeenNumber;
  79. using ValueType::IsNumber;
  80. using ValueType::IsLikelyNumber;
  81. using ValueType::HasBeenUnknownNumber;
  82. using ValueType::IsUnknownNumber;
  83. using ValueType::IsLikelyUnknownNumber;
  84. using ValueType::HasBeenUndefined;
  85. using ValueType::IsUndefined;
  86. using ValueType::IsLikelyUndefined;
  87. using ValueType::HasBeenNull;
  88. using ValueType::IsNull;
  89. using ValueType::IsLikelyNull;
  90. using ValueType::HasBeenBoolean;
  91. using ValueType::IsBoolean;
  92. using ValueType::IsLikelyBoolean;
  93. using ValueType::HasBeenString;
  94. using ValueType::IsString;
  95. using ValueType::HasHadStringTag;
  96. using ValueType::IsLikelyString;
  97. using ValueType::IsNotString;
  98. using ValueType::HasBeenPrimitive;
  99. using ValueType::IsPrimitive;
  100. using ValueType::IsLikelyPrimitive;
  101. using ValueType::HasBeenObject;
  102. using ValueType::IsObject;
  103. using ValueType::IsLikelyObject;
  104. using ValueType::IsNotObject;
  105. using ValueType::CanMergeToObject;
  106. using ValueType::CanMergeToSpecificObjectType;
  107. using ValueType::IsRegExp;
  108. using ValueType::IsLikelyRegExp;
  109. using ValueType::IsArray;
  110. using ValueType::IsLikelyArray;
  111. using ValueType::IsNotArray;
  112. using ValueType::IsArrayOrObjectWithArray;
  113. using ValueType::IsLikelyArrayOrObjectWithArray;
  114. using ValueType::IsNotArrayOrObjectWithArray;
  115. using ValueType::IsNativeArray;
  116. using ValueType::IsLikelyNativeArray;
  117. using ValueType::IsNotNativeArray;
  118. using ValueType::IsNativeIntArray;
  119. using ValueType::IsLikelyNativeIntArray;
  120. using ValueType::IsNativeFloatArray;
  121. using ValueType::IsLikelyNativeFloatArray;
  122. using ValueType::IsTypedArray;
  123. using ValueType::IsLikelyTypedArray;
  124. using ValueType::IsOptimizedTypedArray;
  125. using ValueType::IsLikelyOptimizedTypedArray;
  126. using ValueType::IsLikelyOptimizedVirtualTypedArray;
  127. using ValueType::IsAnyArrayWithNativeFloatValues;
  128. using ValueType::IsLikelyAnyArrayWithNativeFloatValues;
  129. using ValueType::IsAnyArray;
  130. using ValueType::IsLikelyAnyArray;
  131. using ValueType::IsAnyOptimizedArray;
  132. using ValueType::IsLikelyAnyOptimizedArray;
  133. // The following apply to object types only
  134. using ValueType::GetObjectType;
  135. // The following apply to javascript array types only
  136. using ValueType::HasNoMissingValues;
  137. using ValueType::HasIntElements;
  138. using ValueType::HasFloatElements;
  139. using ValueType::HasVarElements;
  140. using ValueType::IsSimd128;
  141. using ValueType::IsSimd128Float32x4;
  142. using ValueType::IsSimd128Int32x4;
  143. using ValueType::IsSimd128Float64x2;
  144. using ValueType::IsLikelySimd128;
  145. using ValueType::IsLikelySimd128Float32x4;
  146. using ValueType::IsLikelySimd128Int32x4;
  147. using ValueType::IsLikelySimd128Float64x2;
  148. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. public:
  150. bool IsGeneric() const;
  151. private:
  152. bool IsIntConstant() const;
  153. bool IsInt64Constant() const;
  154. const IntConstantValueInfo * AsIntConstant() const;
  155. const Int64ConstantValueInfo * AsInt64Constant() const;
  156. bool IsIntRange() const;
  157. const IntRangeValueInfo * AsIntRange() const;
  158. public:
  159. bool IsIntBounded() const;
  160. const IntBoundedValueInfo * AsIntBounded() const;
  161. bool IsFloatConstant() const;
  162. FloatConstantValueInfo * AsFloatConstant();
  163. const FloatConstantValueInfo * AsFloatConstant() const;
  164. bool IsVarConstant() const;
  165. VarConstantValueInfo * AsVarConstant();
  166. bool IsJsType() const;
  167. JsTypeValueInfo * AsJsType();
  168. const JsTypeValueInfo * AsJsType() const;
  169. #if FALSE
  170. bool IsObjectType() const;
  171. JsTypeValueInfo * AsObjectType();
  172. bool IsEquivalentTypeSet() const;
  173. EquivalentTypeSetValueInfo * AsEquivalentTypeSet();
  174. #endif
  175. bool IsArrayValueInfo() const;
  176. const ArrayValueInfo * AsArrayValueInfo() const;
  177. ArrayValueInfo * AsArrayValueInfo();
  178. public:
  179. bool HasIntConstantValue(const bool includeLikelyInt = false) const;
  180. bool TryGetIntConstantValue(int32 *const intValueRef, const bool includeLikelyInt = false) const;
  181. bool TryGetIntConstantValue(int64 *const intValueRef, const bool isUnsigned) const;
  182. bool TryGetInt64ConstantValue(int64 *const intValueRef, const bool isUnsigned) const;
  183. bool TryGetIntConstantLowerBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
  184. bool TryGetIntConstantUpperBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
  185. bool TryGetIntConstantBounds(IntConstantBounds *const intConstantBoundsRef, const bool includeLikelyInt = false) const;
  186. bool WasNegativeZeroPreventedByBailout() const;
  187. public:
  188. static bool IsEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  189. static bool IsNotEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  190. private:
  191. static bool IsEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  192. static bool IsNotEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  193. public:
  194. static bool IsGreaterThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  195. static bool IsGreaterThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  196. static bool IsLessThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  197. static bool IsLessThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  198. public:
  199. 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);
  200. 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);
  201. private:
  202. 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);
  203. 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);
  204. public:
  205. ValueInfo *SpecializeToInt32(JitArenaAllocator *const allocator, const bool isForLoopBackEdgeCompensation = false);
  206. ValueInfo *SpecializeToFloat64(JitArenaAllocator *const allocator);
  207. // SIMD_JS
  208. ValueInfo *SpecializeToSimd128(IRType type, JitArenaAllocator *const allocator);
  209. ValueInfo *SpecializeToSimd128F4(JitArenaAllocator *const allocator);
  210. ValueInfo *SpecializeToSimd128I4(JitArenaAllocator *const allocator);
  211. public:
  212. Sym * GetSymStore() const { return this->symStore; }
  213. void SetSymStore(Sym * sym)
  214. {
  215. // Sym store should always be a var sym
  216. Assert(sym == nullptr || sym->IsPropertySym() || !sym->AsStackSym()->IsTypeSpec()); // property syms always have a var stack sym
  217. this->symStore = sym;
  218. }
  219. bool GetIsShared() const;
  220. void SetIsShared();
  221. ValueInfo * Copy(JitArenaAllocator * allocator);
  222. ValueInfo * CopyWithGenericStructureKind(JitArenaAllocator * allocator) const
  223. {
  224. return JitAnew(allocator, ValueInfo, *this, false);
  225. }
  226. bool GetIntValMinMax(int *pMin, int *pMax, bool doAggressiveIntTypeSpec);
  227. #if DBG_DUMP
  228. void Dump();
  229. #endif
  230. #if DBG
  231. // Add a vtable in debug builds so that the actual can been inspected easily in the debugger without having to manually cast
  232. virtual void AddVtable() { Assert(false); }
  233. #endif
  234. };
  235. class Value
  236. {
  237. private:
  238. const ValueNumber valueNumber;
  239. ValueInfo *valueInfo;
  240. protected:
  241. Value(const ValueNumber valueNumber, ValueInfo *valueInfo)
  242. : valueNumber(valueNumber), valueInfo(valueInfo)
  243. {
  244. };
  245. public:
  246. static Value *New(JitArenaAllocator *const allocator, const ValueNumber valueNumber, ValueInfo *valueInfo)
  247. {
  248. return JitAnew(allocator, Value, valueNumber, valueInfo);
  249. }
  250. ValueNumber GetValueNumber() const { return this->valueNumber; }
  251. ValueInfo * GetValueInfo() { return this->valueInfo; }
  252. ValueInfo const * GetValueInfo() const { return this->valueInfo; }
  253. ValueInfo * ShareValueInfo() const { this->valueInfo->SetIsShared(); return this->valueInfo; }
  254. void SetValueInfo(ValueInfo * newValueInfo) { Assert(newValueInfo); this->valueInfo = newValueInfo; }
  255. Value * Copy(JitArenaAllocator * allocator, ValueNumber newValueNumber) const { return Value::New(allocator, newValueNumber, this->ShareValueInfo()); }
  256. #if DBG_DUMP
  257. _NOINLINE void Dump() const { Output::Print(_u("0x%X ValueNumber: %3d, -> "), this, this->valueNumber); this->valueInfo->Dump(); }
  258. #endif
  259. };
  260. template<> inline
  261. ValueNumber JsUtil::ValueToKey<ValueNumber, Value *>::ToKey(Value *const &value)
  262. {
  263. Assert(value);
  264. return value->GetValueNumber();
  265. }
  266. template <typename T, typename U, ValueStructureKind kind>
  267. class _IntConstantValueInfo : public ValueInfo
  268. {
  269. private:
  270. const T intValue;
  271. public:
  272. static U *New(JitArenaAllocator *const allocator, const T intValue)
  273. {
  274. return JitAnew(allocator, U, intValue);
  275. }
  276. U *Copy(JitArenaAllocator *const allocator) const
  277. {
  278. return JitAnew(allocator, U, *((U*)this));
  279. }
  280. _IntConstantValueInfo(const T intValue)
  281. : ValueInfo(GetInt(IsTaggable(intValue)), kind),
  282. intValue(intValue)
  283. {}
  284. static bool IsTaggable(const T i)
  285. {
  286. return U::IsTaggable(i);
  287. }
  288. T IntValue() const
  289. {
  290. return intValue;
  291. }
  292. };
  293. class IntConstantValueInfo : public _IntConstantValueInfo<int, IntConstantValueInfo, ValueStructureKind::IntConstant>
  294. {
  295. public:
  296. static IntConstantValueInfo *New(JitArenaAllocator *const allocator, const int intValue)
  297. {
  298. return _IntConstantValueInfo::New(allocator, intValue);
  299. }
  300. private:
  301. IntConstantValueInfo(int value) : _IntConstantValueInfo(value) {};
  302. static bool IsTaggable(const int i)
  303. {
  304. #if INT32VAR
  305. // All 32-bit ints are taggable on 64-bit architectures
  306. return true;
  307. #else
  308. return i >= Js::Constants::Int31MinValue && i <= Js::Constants::Int31MaxValue;
  309. #endif
  310. }
  311. friend _IntConstantValueInfo;
  312. };
  313. class Int64ConstantValueInfo : public _IntConstantValueInfo<int64, Int64ConstantValueInfo, ValueStructureKind::Int64Constant>
  314. {
  315. public:
  316. static Int64ConstantValueInfo *New(JitArenaAllocator *const allocator, const int64 intValue)
  317. {
  318. return _IntConstantValueInfo::New(allocator, intValue);
  319. }
  320. private:
  321. static bool IsTaggable(const int64 i) { return false; }
  322. Int64ConstantValueInfo(int64 value) : _IntConstantValueInfo(value) {};
  323. friend _IntConstantValueInfo;
  324. };
  325. class IntRangeValueInfo : public ValueInfo, public IntConstantBounds
  326. {
  327. private:
  328. // Definitely-int values are inherently not negative zero. This member variable, if true, indicates that this value was
  329. // produced by an int-specialized instruction that prevented a negative zero result using a negative zero bailout
  330. // (BailOutOnNegativeZero). Negative zero tracking in the dead-store phase tracks this information to see if some of these
  331. // negative zero bailout checks can be removed.
  332. bool wasNegativeZeroPreventedByBailout;
  333. protected:
  334. IntRangeValueInfo(
  335. const IntConstantBounds &constantBounds,
  336. const bool wasNegativeZeroPreventedByBailout,
  337. const ValueStructureKind structureKind = ValueStructureKind::IntRange)
  338. : ValueInfo(constantBounds.GetValueType(), structureKind),
  339. IntConstantBounds(constantBounds),
  340. wasNegativeZeroPreventedByBailout(wasNegativeZeroPreventedByBailout)
  341. {
  342. Assert(!wasNegativeZeroPreventedByBailout || constantBounds.LowerBound() <= 0 && constantBounds.UpperBound() >= 0);
  343. }
  344. public:
  345. static IntRangeValueInfo *New(
  346. JitArenaAllocator *const allocator,
  347. const int32 lowerBound,
  348. const int32 upperBound,
  349. const bool wasNegativeZeroPreventedByBailout)
  350. {
  351. return
  352. JitAnew(
  353. allocator,
  354. IntRangeValueInfo,
  355. IntConstantBounds(lowerBound, upperBound),
  356. wasNegativeZeroPreventedByBailout);
  357. }
  358. IntRangeValueInfo *Copy(JitArenaAllocator *const allocator) const
  359. {
  360. return JitAnew(allocator, IntRangeValueInfo, *this);
  361. }
  362. public:
  363. bool WasNegativeZeroPreventedByBailout() const
  364. {
  365. return wasNegativeZeroPreventedByBailout;
  366. }
  367. };
  368. class FloatConstantValueInfo : public ValueInfo
  369. {
  370. private:
  371. const FloatConstType floatValue;
  372. public:
  373. FloatConstantValueInfo(const FloatConstType floatValue)
  374. : ValueInfo(Float, ValueStructureKind::FloatConstant), floatValue(floatValue)
  375. {
  376. }
  377. static FloatConstantValueInfo *New(
  378. JitArenaAllocator *const allocator,
  379. const FloatConstType floatValue)
  380. {
  381. return JitAnew(allocator, FloatConstantValueInfo, floatValue);
  382. }
  383. FloatConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
  384. {
  385. return JitAnew(allocator, FloatConstantValueInfo, *this);
  386. }
  387. public:
  388. FloatConstType FloatValue() const
  389. {
  390. return floatValue;
  391. }
  392. };
  393. class VarConstantValueInfo : public ValueInfo
  394. {
  395. private:
  396. Js::Var const varValue;
  397. Js::Var const localVarValue;
  398. bool isFunction;
  399. public:
  400. VarConstantValueInfo(Js::Var varValue, ValueType valueType, bool isFunction = false, Js::Var localVarValue = nullptr)
  401. : ValueInfo(valueType, ValueStructureKind::VarConstant),
  402. varValue(varValue), localVarValue(localVarValue), isFunction(isFunction)
  403. {
  404. }
  405. static VarConstantValueInfo *New(JitArenaAllocator *const allocator, Js::Var varValue, ValueType valueType, bool isFunction = false, Js::Var localVarValue = nullptr)
  406. {
  407. return JitAnew(allocator, VarConstantValueInfo, varValue, valueType, isFunction, localVarValue);
  408. }
  409. VarConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
  410. {
  411. return JitAnew(allocator, VarConstantValueInfo, *this);
  412. }
  413. public:
  414. Js::Var VarValue(bool useLocal = false) const
  415. {
  416. if(useLocal && this->localVarValue)
  417. {
  418. return this->localVarValue;
  419. }
  420. else
  421. {
  422. return this->varValue;
  423. }
  424. }
  425. bool IsFunction() const
  426. {
  427. return this->isFunction;
  428. }
  429. };
  430. struct ObjectTypePropertyEntry
  431. {
  432. ObjTypeSpecFldInfo* fldInfo;
  433. uint blockNumber;
  434. };
  435. typedef JsUtil::BaseDictionary<Js::PropertyId, ObjectTypePropertyEntry, JitArenaAllocator> ObjectTypePropertyMap;
  436. class JsTypeValueInfo : public ValueInfo
  437. {
  438. private:
  439. JITTypeHolder jsType;
  440. Js::EquivalentTypeSet * jsTypeSet;
  441. bool isShared;
  442. public:
  443. JsTypeValueInfo(JITTypeHolder type)
  444. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  445. jsType(type), jsTypeSet(nullptr), isShared(false)
  446. {
  447. }
  448. JsTypeValueInfo(Js::EquivalentTypeSet * typeSet)
  449. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  450. jsType(nullptr), jsTypeSet(typeSet), isShared(false)
  451. {
  452. }
  453. JsTypeValueInfo(const JsTypeValueInfo& other)
  454. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  455. jsType(other.jsType), jsTypeSet(other.jsTypeSet)
  456. {
  457. }
  458. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, JITTypeHolder typeSet)
  459. {
  460. return JitAnew(allocator, JsTypeValueInfo, typeSet);
  461. }
  462. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::EquivalentTypeSet * typeSet)
  463. {
  464. return JitAnew(allocator, JsTypeValueInfo, typeSet);
  465. }
  466. JsTypeValueInfo(const JITTypeHolder type, Js::EquivalentTypeSet * typeSet)
  467. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  468. jsType(type), jsTypeSet(typeSet), isShared(false)
  469. {
  470. }
  471. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet)
  472. {
  473. return JitAnew(allocator, JsTypeValueInfo, type, typeSet);
  474. }
  475. public:
  476. JsTypeValueInfo * Copy(JitArenaAllocator *const allocator) const
  477. {
  478. JsTypeValueInfo * newInfo = JitAnew(allocator, JsTypeValueInfo, *this);
  479. newInfo->isShared = false;
  480. return newInfo;
  481. }
  482. JITTypeHolder GetJsType() const
  483. {
  484. return this->jsType;
  485. }
  486. void SetJsType(const JITTypeHolder value)
  487. {
  488. Assert(!this->isShared);
  489. this->jsType = value;
  490. }
  491. Js::EquivalentTypeSet * GetJsTypeSet() const
  492. {
  493. return this->jsTypeSet;
  494. }
  495. void SetJsTypeSet(Js::EquivalentTypeSet * value)
  496. {
  497. Assert(!this->isShared);
  498. this->jsTypeSet = value;
  499. }
  500. bool GetIsShared() const { return this->isShared; }
  501. void SetIsShared() { this->isShared = true; }
  502. };
  503. class ArrayValueInfo : public ValueInfo
  504. {
  505. private:
  506. StackSym *const headSegmentSym;
  507. StackSym *const headSegmentLengthSym;
  508. StackSym *const lengthSym;
  509. private:
  510. ArrayValueInfo(
  511. const ValueType valueType,
  512. StackSym *const headSegmentSym,
  513. StackSym *const headSegmentLengthSym,
  514. StackSym *const lengthSym,
  515. Sym *const symStore = nullptr)
  516. : ValueInfo(valueType, ValueStructureKind::Array),
  517. headSegmentSym(headSegmentSym),
  518. headSegmentLengthSym(headSegmentLengthSym),
  519. lengthSym(lengthSym)
  520. {
  521. Assert(valueType.IsAnyOptimizedArray());
  522. Assert(!(valueType.IsLikelyTypedArray() && !valueType.IsOptimizedTypedArray()));
  523. // For typed arrays, the head segment length is the same as the array length. For objects with internal arrays, the
  524. // length behaves like a regular object's property rather than like an array length.
  525. Assert(!lengthSym || valueType.IsLikelyArray());
  526. Assert(!lengthSym || lengthSym != headSegmentLengthSym);
  527. if(symStore)
  528. {
  529. SetSymStore(symStore);
  530. }
  531. }
  532. public:
  533. static ArrayValueInfo *New(
  534. JitArenaAllocator *const allocator,
  535. const ValueType valueType,
  536. StackSym *const headSegmentSym,
  537. StackSym *const headSegmentLengthSym,
  538. StackSym *const lengthSym,
  539. Sym *const symStore = nullptr)
  540. {
  541. Assert(allocator);
  542. return JitAnew(allocator, ArrayValueInfo, valueType, headSegmentSym, headSegmentLengthSym, lengthSym, symStore);
  543. }
  544. ValueInfo *Copy(
  545. JitArenaAllocator *const allocator,
  546. const bool copyHeadSegment = true,
  547. const bool copyHeadSegmentLength = true,
  548. const bool copyLength = true) const
  549. {
  550. Assert(allocator);
  551. return
  552. (copyHeadSegment && headSegmentSym) || (copyHeadSegmentLength && headSegmentLengthSym) || (copyLength && lengthSym)
  553. ? New(
  554. allocator,
  555. Type(),
  556. copyHeadSegment ? headSegmentSym : nullptr,
  557. copyHeadSegmentLength ? headSegmentLengthSym : nullptr,
  558. copyLength ? lengthSym : nullptr,
  559. GetSymStore())
  560. : CopyWithGenericStructureKind(allocator);
  561. }
  562. public:
  563. StackSym *HeadSegmentSym() const
  564. {
  565. return headSegmentSym;
  566. }
  567. StackSym *HeadSegmentLengthSym() const
  568. {
  569. return headSegmentLengthSym;
  570. }
  571. StackSym *LengthSym() const
  572. {
  573. return lengthSym;
  574. }
  575. IR::ArrayRegOpnd *CreateOpnd(
  576. IR::RegOpnd *const previousArrayOpnd,
  577. const bool needsHeadSegment,
  578. const bool needsHeadSegmentLength,
  579. const bool needsLength,
  580. const bool eliminatedLowerBoundCheck,
  581. const bool eliminatedUpperBoundCheck,
  582. Func *const func) const
  583. {
  584. Assert(previousArrayOpnd);
  585. Assert(func);
  586. return
  587. IR::ArrayRegOpnd::New(
  588. previousArrayOpnd,
  589. Type(),
  590. needsHeadSegment ? headSegmentSym : nullptr,
  591. needsHeadSegmentLength ? headSegmentLengthSym : nullptr,
  592. needsLength ? lengthSym : nullptr,
  593. eliminatedLowerBoundCheck,
  594. eliminatedUpperBoundCheck,
  595. func);
  596. }
  597. };