ValueInfo.h 24 KB

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