ValueInfo.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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. #include "Backend.h"
  6. bool ValueInfo::HasIntConstantValue(const bool includeLikelyInt) const
  7. {
  8. int32 constantValue;
  9. return TryGetIntConstantValue(&constantValue, includeLikelyInt);
  10. }
  11. bool ValueInfo::TryGetInt64ConstantValue(int64 *const intValueRef, const bool isUnsigned) const
  12. {
  13. Assert(intValueRef);
  14. if (TryGetIntConstantValue(intValueRef, isUnsigned))
  15. {
  16. return true;
  17. }
  18. else
  19. {
  20. int32 int32ValueRef;
  21. if (TryGetIntConstantValue(&int32ValueRef, false))
  22. {
  23. if (isUnsigned)
  24. {
  25. *intValueRef = (uint)int32ValueRef;
  26. }
  27. else
  28. {
  29. *intValueRef = int32ValueRef;
  30. }
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36. bool ValueInfo::TryGetIntConstantValue(int64 *const intValueRef, const bool isUnsigned) const
  37. {
  38. Assert(intValueRef);
  39. if (structureKind == ValueStructureKind::Int64Constant)
  40. {
  41. *intValueRef = AsInt64Constant()->IntValue();
  42. return true;
  43. }
  44. return false;
  45. }
  46. bool ValueInfo::TryGetIntConstantValue(int32 *const intValueRef, const bool includeLikelyInt) const
  47. {
  48. Assert(intValueRef);
  49. if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
  50. {
  51. return false;
  52. }
  53. switch (structureKind)
  54. {
  55. case ValueStructureKind::IntConstant:
  56. if (!includeLikelyInt || IsInt())
  57. {
  58. *intValueRef = AsIntConstant()->IntValue();
  59. return true;
  60. }
  61. break;
  62. case ValueStructureKind::IntRange:
  63. Assert(includeLikelyInt && !IsInt() || !AsIntRange()->IsConstant());
  64. break;
  65. case ValueStructureKind::IntBounded:
  66. {
  67. const IntConstantBounds bounds(AsIntBounded()->Bounds()->ConstantBounds());
  68. if (bounds.IsConstant())
  69. {
  70. *intValueRef = bounds.LowerBound();
  71. return true;
  72. }
  73. break;
  74. }
  75. }
  76. return false;
  77. }
  78. bool ValueInfo::TryGetIntConstantLowerBound(int32 *const intConstantBoundRef, const bool includeLikelyInt) const
  79. {
  80. Assert(intConstantBoundRef);
  81. if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
  82. {
  83. return false;
  84. }
  85. switch (structureKind)
  86. {
  87. case ValueStructureKind::IntConstant:
  88. if (!includeLikelyInt || IsInt())
  89. {
  90. *intConstantBoundRef = AsIntConstant()->IntValue();
  91. return true;
  92. }
  93. break;
  94. case ValueStructureKind::IntRange:
  95. if (!includeLikelyInt || IsInt())
  96. {
  97. *intConstantBoundRef = AsIntRange()->LowerBound();
  98. return true;
  99. }
  100. break;
  101. case ValueStructureKind::IntBounded:
  102. *intConstantBoundRef = AsIntBounded()->Bounds()->ConstantLowerBound();
  103. return true;
  104. }
  105. *intConstantBoundRef = IsTaggedInt() ? Js::Constants::Int31MinValue : IntConstMin;
  106. return true;
  107. }
  108. bool ValueInfo::TryGetIntConstantUpperBound(int32 *const intConstantBoundRef, const bool includeLikelyInt) const
  109. {
  110. Assert(intConstantBoundRef);
  111. if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
  112. {
  113. return false;
  114. }
  115. switch (structureKind)
  116. {
  117. case ValueStructureKind::IntConstant:
  118. if (!includeLikelyInt || IsInt())
  119. {
  120. *intConstantBoundRef = AsIntConstant()->IntValue();
  121. return true;
  122. }
  123. break;
  124. case ValueStructureKind::IntRange:
  125. if (!includeLikelyInt || IsInt())
  126. {
  127. *intConstantBoundRef = AsIntRange()->UpperBound();
  128. return true;
  129. }
  130. break;
  131. case ValueStructureKind::IntBounded:
  132. *intConstantBoundRef = AsIntBounded()->Bounds()->ConstantUpperBound();
  133. return true;
  134. }
  135. *intConstantBoundRef = IsTaggedInt() ? Js::Constants::Int31MaxValue : IntConstMax;
  136. return true;
  137. }
  138. bool ValueInfo::TryGetIntConstantBounds(IntConstantBounds *const intConstantBoundsRef, const bool includeLikelyInt) const
  139. {
  140. Assert(intConstantBoundsRef);
  141. if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
  142. {
  143. return false;
  144. }
  145. switch (structureKind)
  146. {
  147. case ValueStructureKind::IntConstant:
  148. if (!includeLikelyInt || IsInt())
  149. {
  150. const int32 intValue = AsIntConstant()->IntValue();
  151. *intConstantBoundsRef = IntConstantBounds(intValue, intValue);
  152. return true;
  153. }
  154. break;
  155. case ValueStructureKind::IntRange:
  156. if (!includeLikelyInt || IsInt())
  157. {
  158. *intConstantBoundsRef = *AsIntRange();
  159. return true;
  160. }
  161. break;
  162. case ValueStructureKind::IntBounded:
  163. *intConstantBoundsRef = AsIntBounded()->Bounds()->ConstantBounds();
  164. return true;
  165. }
  166. *intConstantBoundsRef =
  167. IsTaggedInt()
  168. ? IntConstantBounds(Js::Constants::Int31MinValue, Js::Constants::Int31MaxValue)
  169. : IntConstantBounds(INT32_MIN, INT32_MAX);
  170. return true;
  171. }
  172. bool ValueInfo::WasNegativeZeroPreventedByBailout() const
  173. {
  174. if (!IsInt())
  175. {
  176. return false;
  177. }
  178. switch (structureKind)
  179. {
  180. case ValueStructureKind::IntRange:
  181. return AsIntRange()->WasNegativeZeroPreventedByBailout();
  182. case ValueStructureKind::IntBounded:
  183. return AsIntBounded()->WasNegativeZeroPreventedByBailout();
  184. }
  185. return false;
  186. }
  187. bool ValueInfo::IsEqualTo(
  188. const Value *const src1Value,
  189. const int32 min1,
  190. const int32 max1,
  191. const Value *const src2Value,
  192. const int32 min2,
  193. const int32 max2)
  194. {
  195. const bool result =
  196. IsEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2) ||
  197. IsEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1);
  198. Assert(!result || !IsNotEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2));
  199. Assert(!result || !IsNotEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1));
  200. return result;
  201. }
  202. bool ValueInfo::IsNotEqualTo(
  203. const Value *const src1Value,
  204. const int32 min1,
  205. const int32 max1,
  206. const Value *const src2Value,
  207. const int32 min2,
  208. const int32 max2)
  209. {
  210. const bool result =
  211. IsNotEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2) ||
  212. IsNotEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1);
  213. Assert(!result || !IsEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2));
  214. Assert(!result || !IsEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1));
  215. return result;
  216. }
  217. bool ValueInfo::IsEqualTo_NoConverse(
  218. const Value *const src1Value,
  219. const int32 min1,
  220. const int32 max1,
  221. const Value *const src2Value,
  222. const int32 min2,
  223. const int32 max2)
  224. {
  225. return
  226. IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2) &&
  227. IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2);
  228. }
  229. bool ValueInfo::IsNotEqualTo_NoConverse(
  230. const Value *const src1Value,
  231. const int32 min1,
  232. const int32 max1,
  233. const Value *const src2Value,
  234. const int32 min2,
  235. const int32 max2)
  236. {
  237. return
  238. IsGreaterThan(src1Value, min1, max1, src2Value, min2, max2) ||
  239. IsLessThan(src1Value, min1, max1, src2Value, min2, max2);
  240. }
  241. bool ValueInfo::IsGreaterThanOrEqualTo(
  242. const Value *const src1Value,
  243. const int32 min1,
  244. const int32 max1,
  245. const Value *const src2Value,
  246. const int32 min2,
  247. const int32 max2)
  248. {
  249. return IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 0);
  250. }
  251. bool ValueInfo::IsGreaterThan(
  252. const Value *const src1Value,
  253. const int32 min1,
  254. const int32 max1,
  255. const Value *const src2Value,
  256. const int32 min2,
  257. const int32 max2)
  258. {
  259. return IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 1);
  260. }
  261. bool ValueInfo::IsLessThanOrEqualTo(
  262. const Value *const src1Value,
  263. const int32 min1,
  264. const int32 max1,
  265. const Value *const src2Value,
  266. const int32 min2,
  267. const int32 max2)
  268. {
  269. return IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 0);
  270. }
  271. bool ValueInfo::IsLessThan(
  272. const Value *const src1Value,
  273. const int32 min1,
  274. const int32 max1,
  275. const Value *const src2Value,
  276. const int32 min2,
  277. const int32 max2)
  278. {
  279. return IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, -1);
  280. }
  281. bool ValueInfo::IsGreaterThanOrEqualTo(
  282. const Value *const src1Value,
  283. const int32 min1,
  284. const int32 max1,
  285. const Value *const src2Value,
  286. const int32 min2,
  287. const int32 max2,
  288. const int src2Offset)
  289. {
  290. return
  291. IsGreaterThanOrEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2, src2Offset) ||
  292. src2Offset == IntConstMin ||
  293. IsLessThanOrEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1, -src2Offset);
  294. }
  295. bool ValueInfo::IsLessThanOrEqualTo(
  296. const Value *const src1Value,
  297. const int32 min1,
  298. const int32 max1,
  299. const Value *const src2Value,
  300. const int32 min2,
  301. const int32 max2,
  302. const int src2Offset)
  303. {
  304. return
  305. IsLessThanOrEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2, src2Offset) ||
  306. (
  307. src2Offset != IntConstMin &&
  308. IsGreaterThanOrEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1, -src2Offset)
  309. );
  310. }
  311. bool ValueInfo::IsGreaterThanOrEqualTo_NoConverse(
  312. const Value *const src1Value,
  313. const int32 min1,
  314. const int32 max1,
  315. const Value *const src2Value,
  316. const int32 min2,
  317. const int32 max2,
  318. const int src2Offset)
  319. {
  320. Assert(src1Value || min1 == max1);
  321. Assert(!src1Value || src1Value->GetValueInfo()->IsLikelyInt());
  322. Assert(src2Value || min2 == max2);
  323. Assert(!src2Value || src2Value->GetValueInfo()->IsLikelyInt());
  324. if (src1Value)
  325. {
  326. if (src2Value && src1Value->GetValueNumber() == src2Value->GetValueNumber())
  327. {
  328. return src2Offset <= 0;
  329. }
  330. ValueInfo const * const src1ValueInfo = src1Value->GetValueInfo();
  331. if (src1ValueInfo->structureKind == ValueStructureKind::IntBounded)
  332. {
  333. const IntBounds *const bounds = src1ValueInfo->AsIntBounded()->Bounds();
  334. return
  335. src2Value
  336. ? bounds->IsGreaterThanOrEqualTo(src2Value, src2Offset)
  337. : bounds->IsGreaterThanOrEqualTo(min2, src2Offset);
  338. }
  339. }
  340. return IntBounds::IsGreaterThanOrEqualTo(min1, max2, src2Offset);
  341. }
  342. bool ValueInfo::IsLessThanOrEqualTo_NoConverse(
  343. const Value *const src1Value,
  344. const int32 min1,
  345. const int32 max1,
  346. const Value *const src2Value,
  347. const int32 min2,
  348. const int32 max2,
  349. const int src2Offset)
  350. {
  351. Assert(src1Value || min1 == max1);
  352. Assert(!src1Value || src1Value->GetValueInfo()->IsLikelyInt());
  353. Assert(src2Value || min2 == max2);
  354. Assert(!src2Value || src2Value->GetValueInfo()->IsLikelyInt());
  355. if (src1Value)
  356. {
  357. if (src2Value && src1Value->GetValueNumber() == src2Value->GetValueNumber())
  358. {
  359. return src2Offset >= 0;
  360. }
  361. ValueInfo const * const src1ValueInfo = src1Value->GetValueInfo();
  362. if (src1ValueInfo->structureKind == ValueStructureKind::IntBounded)
  363. {
  364. const IntBounds *const bounds = src1ValueInfo->AsIntBounded()->Bounds();
  365. return
  366. src2Value
  367. ? bounds->IsLessThanOrEqualTo(src2Value, src2Offset)
  368. : bounds->IsLessThanOrEqualTo(min2, src2Offset);
  369. }
  370. }
  371. return IntBounds::IsLessThanOrEqualTo(max1, min2, src2Offset);
  372. }
  373. bool
  374. ValueInfo::IsGeneric() const
  375. {
  376. return structureKind == ValueStructureKind::Generic;
  377. }
  378. bool
  379. ValueInfo::IsIntConstant() const
  380. {
  381. return IsInt() && structureKind == ValueStructureKind::IntConstant;
  382. }
  383. bool
  384. ValueInfo::IsInt64Constant() const
  385. {
  386. return IsInt() && structureKind == ValueStructureKind::Int64Constant;
  387. }
  388. const IntConstantValueInfo *
  389. ValueInfo::AsIntConstant() const
  390. {
  391. Assert(IsIntConstant());
  392. return static_cast<const IntConstantValueInfo *>(this);
  393. }
  394. const Int64ConstantValueInfo *
  395. ValueInfo::AsInt64Constant() const
  396. {
  397. Assert(IsInt64Constant());
  398. return static_cast<const Int64ConstantValueInfo *>(this);
  399. }
  400. bool
  401. ValueInfo::IsIntRange() const
  402. {
  403. return IsInt() && structureKind == ValueStructureKind::IntRange;
  404. }
  405. const IntRangeValueInfo *
  406. ValueInfo::AsIntRange() const
  407. {
  408. Assert(IsIntRange());
  409. return static_cast<const IntRangeValueInfo *>(this);
  410. }
  411. bool
  412. ValueInfo::IsIntBounded() const
  413. {
  414. const bool isIntBounded = IsLikelyInt() && structureKind == ValueStructureKind::IntBounded;
  415. // Bounds for definitely int values should have relative bounds, otherwise those values should use one of the other value
  416. // infos
  417. Assert(!isIntBounded || static_cast<const IntBoundedValueInfo *>(this)->Bounds()->RequiresIntBoundedValueInfo(Type()));
  418. return isIntBounded;
  419. }
  420. const IntBoundedValueInfo *
  421. ValueInfo::AsIntBounded() const
  422. {
  423. Assert(IsIntBounded());
  424. return static_cast<const IntBoundedValueInfo *>(this);
  425. }
  426. bool
  427. ValueInfo::IsFloatConstant() const
  428. {
  429. return IsFloat() && structureKind == ValueStructureKind::FloatConstant;
  430. }
  431. FloatConstantValueInfo *
  432. ValueInfo::AsFloatConstant()
  433. {
  434. Assert(IsFloatConstant());
  435. return static_cast<FloatConstantValueInfo *>(this);
  436. }
  437. const FloatConstantValueInfo *
  438. ValueInfo::AsFloatConstant() const
  439. {
  440. Assert(IsFloatConstant());
  441. return static_cast<const FloatConstantValueInfo *>(this);
  442. }
  443. bool
  444. ValueInfo::IsVarConstant() const
  445. {
  446. return structureKind == ValueStructureKind::VarConstant;
  447. }
  448. VarConstantValueInfo *
  449. ValueInfo::AsVarConstant()
  450. {
  451. Assert(IsVarConstant());
  452. return static_cast<VarConstantValueInfo *>(this);
  453. }
  454. bool
  455. ValueInfo::IsJsType() const
  456. {
  457. Assert(!(structureKind == ValueStructureKind::JsType && !IsUninitialized()));
  458. return structureKind == ValueStructureKind::JsType;
  459. }
  460. JsTypeValueInfo *
  461. ValueInfo::AsJsType()
  462. {
  463. Assert(IsJsType());
  464. return static_cast<JsTypeValueInfo *>(this);
  465. }
  466. const JsTypeValueInfo *
  467. ValueInfo::AsJsType() const
  468. {
  469. Assert(IsJsType());
  470. return static_cast<const JsTypeValueInfo *>(this);
  471. }
  472. bool
  473. ValueInfo::IsArrayValueInfo() const
  474. {
  475. return IsAnyOptimizedArray() && structureKind == ValueStructureKind::Array;
  476. }
  477. const ArrayValueInfo *
  478. ValueInfo::AsArrayValueInfo() const
  479. {
  480. Assert(IsArrayValueInfo());
  481. return static_cast<const ArrayValueInfo *>(this);
  482. }
  483. ArrayValueInfo *
  484. ValueInfo::AsArrayValueInfo()
  485. {
  486. Assert(IsArrayValueInfo());
  487. return static_cast<ArrayValueInfo *>(this);
  488. }
  489. ValueInfo *
  490. ValueInfo::SpecializeToInt32(JitArenaAllocator *const allocator, const bool isForLoopBackEdgeCompensation)
  491. {
  492. // Int specialization in some uncommon loop cases involving dependencies, needs to allow specializing values of arbitrary
  493. // types, even values that are definitely not int, to compensate for aggressive assumptions made by a loop prepass. In all
  494. // other cases, only values that are likely int may be int-specialized.
  495. Assert(IsUninitialized() || IsLikelyInt() || isForLoopBackEdgeCompensation);
  496. if (IsInt())
  497. {
  498. return this;
  499. }
  500. if (!IsIntBounded())
  501. {
  502. ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
  503. newValueInfo->Type() = ValueType::GetInt(true);
  504. return newValueInfo;
  505. }
  506. const IntBoundedValueInfo *const boundedValueInfo = AsIntBounded();
  507. const IntBounds *const bounds = boundedValueInfo->Bounds();
  508. const IntConstantBounds constantBounds = bounds->ConstantBounds();
  509. if (bounds->RequiresIntBoundedValueInfo())
  510. {
  511. IntBoundedValueInfo *const newValueInfo = boundedValueInfo->Copy(allocator);
  512. newValueInfo->Type() = constantBounds.GetValueType();
  513. return newValueInfo;
  514. }
  515. ValueInfo *const newValueInfo =
  516. constantBounds.IsConstant()
  517. ? static_cast<ValueInfo *>(IntConstantValueInfo::New(allocator, constantBounds.LowerBound()))
  518. : IntRangeValueInfo::New(allocator, constantBounds.LowerBound(), constantBounds.UpperBound(), false);
  519. newValueInfo->SetSymStore(GetSymStore());
  520. return newValueInfo;
  521. }
  522. ValueInfo *
  523. ValueInfo::SpecializeToFloat64(JitArenaAllocator *const allocator)
  524. {
  525. if (IsNumber())
  526. {
  527. return this;
  528. }
  529. ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
  530. // If the value type was likely int, after float-specializing, it's preferable to use Int_Number rather than Float, as the
  531. // former is also likely int and allows int specialization later.
  532. newValueInfo->Type() = IsLikelyInt() ? Type().ToDefiniteAnyNumber() : Type().ToDefiniteAnyFloat();
  533. return newValueInfo;
  534. }
  535. // SIMD_JS
  536. ValueInfo *
  537. ValueInfo::SpecializeToSimd128(IRType type, JitArenaAllocator *const allocator)
  538. {
  539. switch (type)
  540. {
  541. case TySimd128F4:
  542. return SpecializeToSimd128F4(allocator);
  543. case TySimd128I4:
  544. return SpecializeToSimd128I4(allocator);
  545. default:
  546. Assert(UNREACHED);
  547. return nullptr;
  548. }
  549. }
  550. ValueInfo *
  551. ValueInfo::SpecializeToSimd128F4(JitArenaAllocator *const allocator)
  552. {
  553. if (IsSimd128Float32x4())
  554. {
  555. return this;
  556. }
  557. ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
  558. newValueInfo->Type() = ValueType::GetSimd128(ObjectType::Simd128Float32x4);
  559. return newValueInfo;
  560. }
  561. ValueInfo *
  562. ValueInfo::SpecializeToSimd128I4(JitArenaAllocator *const allocator)
  563. {
  564. if (IsSimd128Int32x4())
  565. {
  566. return this;
  567. }
  568. ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
  569. newValueInfo->Type() = ValueType::GetSimd128(ObjectType::Simd128Int32x4);
  570. return newValueInfo;
  571. }
  572. bool
  573. ValueInfo::GetIsShared() const
  574. {
  575. return IsJsType() ? AsJsType()->GetIsShared() : false;
  576. }
  577. void
  578. ValueInfo::SetIsShared()
  579. {
  580. if (IsJsType()) AsJsType()->SetIsShared();
  581. }
  582. ValueInfo *
  583. ValueInfo::Copy(JitArenaAllocator * allocator)
  584. {
  585. if (IsIntConstant())
  586. {
  587. return AsIntConstant()->Copy(allocator);
  588. }
  589. if (IsIntRange())
  590. {
  591. return AsIntRange()->Copy(allocator);
  592. }
  593. if (IsIntBounded())
  594. {
  595. return AsIntBounded()->Copy(allocator);
  596. }
  597. if (IsFloatConstant())
  598. {
  599. return AsFloatConstant()->Copy(allocator);
  600. }
  601. if (IsJsType())
  602. {
  603. return AsJsType()->Copy(allocator);
  604. }
  605. if (IsArrayValueInfo())
  606. {
  607. return AsArrayValueInfo()->Copy(allocator);
  608. }
  609. return CopyWithGenericStructureKind(allocator);
  610. }
  611. bool
  612. ValueInfo::GetIntValMinMax(int *pMin, int *pMax, bool doAggressiveIntTypeSpec)
  613. {
  614. IntConstantBounds intConstantBounds;
  615. if (TryGetIntConstantBounds(&intConstantBounds, doAggressiveIntTypeSpec))
  616. {
  617. *pMin = intConstantBounds.LowerBound();
  618. *pMax = intConstantBounds.UpperBound();
  619. return true;
  620. }
  621. Assert(!IsInt());
  622. Assert(!doAggressiveIntTypeSpec || !IsLikelyInt());
  623. return false;
  624. }
  625. ValueInfo *
  626. ValueInfo::MergeLikelyIntValueInfo(JitArenaAllocator* alloc, Value *toDataVal, Value *fromDataVal, ValueType const newValueType)
  627. {
  628. Assert(newValueType.IsLikelyInt());
  629. ValueInfo *const toDataValueInfo = toDataVal->GetValueInfo();
  630. ValueInfo *const fromDataValueInfo = fromDataVal->GetValueInfo();
  631. Assert(toDataValueInfo != fromDataValueInfo);
  632. bool wasNegativeZeroPreventedByBailout;
  633. if(newValueType.IsInt())
  634. {
  635. int32 toDataIntConstantValue, fromDataIntConstantValue;
  636. if (toDataValueInfo->TryGetIntConstantValue(&toDataIntConstantValue) &&
  637. fromDataValueInfo->TryGetIntConstantValue(&fromDataIntConstantValue) &&
  638. toDataIntConstantValue == fromDataIntConstantValue)
  639. {
  640. // A new value number must be created to register the fact that the value has changed. Otherwise, if the value
  641. // changed inside a loop, the sym may look invariant on the loop back-edge (and hence not turned into a number
  642. // value), and its constant value from the first iteration may be incorrectly propagated after the loop.
  643. return IntConstantValueInfo::New(alloc, toDataIntConstantValue);
  644. }
  645. wasNegativeZeroPreventedByBailout =
  646. toDataValueInfo->WasNegativeZeroPreventedByBailout() ||
  647. fromDataValueInfo->WasNegativeZeroPreventedByBailout();
  648. }
  649. else
  650. {
  651. wasNegativeZeroPreventedByBailout = false;
  652. }
  653. const IntBounds *const toDataValBounds =
  654. toDataValueInfo->IsIntBounded() ? toDataValueInfo->AsIntBounded()->Bounds() : nullptr;
  655. const IntBounds *const fromDataValBounds =
  656. fromDataValueInfo->IsIntBounded() ? fromDataValueInfo->AsIntBounded()->Bounds() : nullptr;
  657. if(toDataValBounds || fromDataValBounds)
  658. {
  659. const IntBounds *mergedBounds;
  660. if(toDataValBounds && fromDataValBounds)
  661. {
  662. mergedBounds = IntBounds::Merge(toDataVal, toDataValBounds, fromDataVal, fromDataValBounds);
  663. }
  664. else
  665. {
  666. IntConstantBounds constantBounds;
  667. if(toDataValBounds)
  668. {
  669. mergedBounds =
  670. fromDataValueInfo->TryGetIntConstantBounds(&constantBounds, true)
  671. ? IntBounds::Merge(toDataVal, toDataValBounds, fromDataVal, constantBounds)
  672. : nullptr;
  673. }
  674. else
  675. {
  676. Assert(fromDataValBounds);
  677. mergedBounds =
  678. toDataValueInfo->TryGetIntConstantBounds(&constantBounds, true)
  679. ? IntBounds::Merge(fromDataVal, fromDataValBounds, toDataVal, constantBounds)
  680. : nullptr;
  681. }
  682. }
  683. if(mergedBounds)
  684. {
  685. if(mergedBounds->RequiresIntBoundedValueInfo(newValueType))
  686. {
  687. return IntBoundedValueInfo::New(newValueType, mergedBounds, wasNegativeZeroPreventedByBailout, alloc);
  688. }
  689. mergedBounds->Delete();
  690. }
  691. }
  692. if(newValueType.IsInt())
  693. {
  694. int32 min1, max1, min2, max2;
  695. toDataValueInfo->GetIntValMinMax(&min1, &max1, false);
  696. fromDataValueInfo->GetIntValMinMax(&min2, &max2, false);
  697. return ValueInfo::NewIntRangeValueInfo(alloc, min(min1, min2), max(max1, max2), wasNegativeZeroPreventedByBailout);
  698. }
  699. return ValueInfo::New(alloc, newValueType);
  700. }
  701. ValueInfo * ValueInfo::NewIntRangeValueInfo(JitArenaAllocator * alloc, int32 min, int32 max, bool wasNegativeZeroPreventedByBailout)
  702. {
  703. if (min == max)
  704. {
  705. // Since int constant values are const-propped, negative zero tracking does not track them, and so it's okay to ignore
  706. // 'wasNegativeZeroPreventedByBailout'
  707. return IntConstantValueInfo::New(alloc, max);
  708. }
  709. return IntRangeValueInfo::New(alloc, min, max, wasNegativeZeroPreventedByBailout);
  710. }
  711. #if DBG_DUMP
  712. void ValueInfo::Dump()
  713. {
  714. if (!IsJsType()) // The value type is uninitialized for a type value
  715. {
  716. char typeStr[VALUE_TYPE_MAX_STRING_SIZE];
  717. Type().ToString(typeStr);
  718. Output::Print(_u("%S"), typeStr);
  719. }
  720. IntConstantBounds intConstantBounds;
  721. if (TryGetIntConstantBounds(&intConstantBounds))
  722. {
  723. if (intConstantBounds.IsConstant())
  724. {
  725. Output::Print(_u(" constant:%d"), intConstantBounds.LowerBound());
  726. return;
  727. }
  728. Output::Print(_u(" range:%d - %d"), intConstantBounds.LowerBound(), intConstantBounds.UpperBound());
  729. }
  730. else if (IsFloatConstant())
  731. {
  732. Output::Print(_u(" constant:%g"), AsFloatConstant()->FloatValue());
  733. }
  734. else if (IsJsType())
  735. {
  736. const JITTypeHolder type(AsJsType()->GetJsType());
  737. type != nullptr ? Output::Print(_u("type: 0x%p, "), type->GetAddr()) : Output::Print(_u("type: null, "));
  738. Output::Print(_u("type Set: "));
  739. Js::EquivalentTypeSet* typeSet = AsJsType()->GetJsTypeSet();
  740. if (typeSet != nullptr)
  741. {
  742. uint16 typeCount = typeSet->GetCount();
  743. for (uint16 ti = 0; ti < typeCount - 1; ti++)
  744. {
  745. Output::Print(_u("0x%p, "), typeSet->GetType(ti));
  746. }
  747. Output::Print(_u("0x%p"), typeSet->GetType(typeCount - 1));
  748. }
  749. else
  750. {
  751. Output::Print(_u("null"));
  752. }
  753. }
  754. else if (IsArrayValueInfo())
  755. {
  756. const ArrayValueInfo *const arrayValueInfo = AsArrayValueInfo();
  757. if (arrayValueInfo->HeadSegmentSym())
  758. {
  759. Output::Print(_u(" seg: "));
  760. arrayValueInfo->HeadSegmentSym()->Dump();
  761. }
  762. if (arrayValueInfo->HeadSegmentLengthSym())
  763. {
  764. Output::Print(_u(" segLen: "));
  765. arrayValueInfo->HeadSegmentLengthSym()->Dump();
  766. }
  767. if (arrayValueInfo->LengthSym())
  768. {
  769. Output::Print(_u(" len: "));
  770. arrayValueInfo->LengthSym()->Dump();
  771. }
  772. }
  773. if (this->GetSymStore())
  774. {
  775. Output::Print(_u("\t\tsym:"));
  776. this->GetSymStore()->Dump();
  777. }
  778. }
  779. #endif