DFGAbstractValue.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*
  2. * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef DFGAbstractValue_h
  26. #define DFGAbstractValue_h
  27. #include <wtf/Platform.h>
  28. #if ENABLE(DFG_JIT)
  29. #include "ArrayProfile.h"
  30. #include "DFGStructureAbstractValue.h"
  31. #include "JSCell.h"
  32. #include "SpeculatedType.h"
  33. #include "StructureSet.h"
  34. namespace JSC { namespace DFG {
  35. struct AbstractValue {
  36. AbstractValue()
  37. : m_type(SpecNone)
  38. , m_arrayModes(0)
  39. {
  40. }
  41. void clear()
  42. {
  43. m_type = SpecNone;
  44. m_arrayModes = 0;
  45. m_currentKnownStructure.clear();
  46. m_futurePossibleStructure.clear();
  47. m_value = JSValue();
  48. checkConsistency();
  49. }
  50. bool isClear() const
  51. {
  52. bool result = m_type == SpecNone && !m_arrayModes && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear();
  53. if (result)
  54. ASSERT(!m_value);
  55. return result;
  56. }
  57. void makeTop()
  58. {
  59. m_type |= SpecTop; // The state may have included SpecEmpty, in which case we want this to become SpecEmptyOrTop.
  60. m_arrayModes = ALL_ARRAY_MODES;
  61. m_currentKnownStructure.makeTop();
  62. m_futurePossibleStructure.makeTop();
  63. m_value = JSValue();
  64. checkConsistency();
  65. }
  66. void clobberStructures()
  67. {
  68. if (m_type & SpecCell) {
  69. m_currentKnownStructure.makeTop();
  70. clobberArrayModes();
  71. } else {
  72. ASSERT(m_currentKnownStructure.isClear());
  73. ASSERT(!m_arrayModes);
  74. }
  75. checkConsistency();
  76. }
  77. void clobberValue()
  78. {
  79. m_value = JSValue();
  80. }
  81. bool isTop() const
  82. {
  83. return m_type == SpecTop && m_currentKnownStructure.isTop() && m_futurePossibleStructure.isTop();
  84. }
  85. bool valueIsTop() const
  86. {
  87. return !m_value && m_type;
  88. }
  89. JSValue value() const
  90. {
  91. return m_value;
  92. }
  93. static AbstractValue top()
  94. {
  95. AbstractValue result;
  96. result.makeTop();
  97. return result;
  98. }
  99. void setMostSpecific(JSValue value)
  100. {
  101. if (!!value && value.isCell()) {
  102. Structure* structure = value.asCell()->structure();
  103. m_currentKnownStructure = structure;
  104. setFuturePossibleStructure(structure);
  105. m_arrayModes = asArrayModes(structure->indexingType());
  106. } else {
  107. m_currentKnownStructure.clear();
  108. m_futurePossibleStructure.clear();
  109. m_arrayModes = 0;
  110. }
  111. m_type = speculationFromValue(value);
  112. m_value = value;
  113. checkConsistency();
  114. }
  115. void set(JSValue value)
  116. {
  117. if (!!value && value.isCell()) {
  118. m_currentKnownStructure.makeTop();
  119. Structure* structure = value.asCell()->structure();
  120. setFuturePossibleStructure(structure);
  121. m_arrayModes = asArrayModes(structure->indexingType());
  122. clobberArrayModes();
  123. } else {
  124. m_currentKnownStructure.clear();
  125. m_futurePossibleStructure.clear();
  126. m_arrayModes = 0;
  127. }
  128. m_type = speculationFromValue(value);
  129. m_value = value;
  130. checkConsistency();
  131. }
  132. void set(Structure* structure)
  133. {
  134. m_currentKnownStructure = structure;
  135. setFuturePossibleStructure(structure);
  136. m_arrayModes = asArrayModes(structure->indexingType());
  137. m_type = speculationFromStructure(structure);
  138. m_value = JSValue();
  139. checkConsistency();
  140. }
  141. void set(SpeculatedType type)
  142. {
  143. if (type & SpecCell) {
  144. m_currentKnownStructure.makeTop();
  145. m_futurePossibleStructure.makeTop();
  146. m_arrayModes = ALL_ARRAY_MODES;
  147. } else {
  148. m_currentKnownStructure.clear();
  149. m_futurePossibleStructure.clear();
  150. m_arrayModes = 0;
  151. }
  152. m_type = type;
  153. m_value = JSValue();
  154. checkConsistency();
  155. }
  156. bool operator==(const AbstractValue& other) const
  157. {
  158. return m_type == other.m_type
  159. && m_arrayModes == other.m_arrayModes
  160. && m_currentKnownStructure == other.m_currentKnownStructure
  161. && m_futurePossibleStructure == other.m_futurePossibleStructure
  162. && m_value == other.m_value;
  163. }
  164. bool operator!=(const AbstractValue& other) const
  165. {
  166. return !(*this == other);
  167. }
  168. bool merge(const AbstractValue& other)
  169. {
  170. if (other.isClear())
  171. return false;
  172. #if !ASSERT_DISABLED
  173. AbstractValue oldMe = *this;
  174. #endif
  175. bool result = false;
  176. if (isClear()) {
  177. *this = other;
  178. result = !other.isClear();
  179. } else {
  180. result |= mergeSpeculation(m_type, other.m_type);
  181. result |= mergeArrayModes(m_arrayModes, other.m_arrayModes);
  182. result |= m_currentKnownStructure.addAll(other.m_currentKnownStructure);
  183. result |= m_futurePossibleStructure.addAll(other.m_futurePossibleStructure);
  184. if (m_value != other.m_value) {
  185. result |= !!m_value;
  186. m_value = JSValue();
  187. }
  188. }
  189. checkConsistency();
  190. ASSERT(result == (*this != oldMe));
  191. return result;
  192. }
  193. void merge(SpeculatedType type)
  194. {
  195. mergeSpeculation(m_type, type);
  196. if (type & SpecCell) {
  197. m_currentKnownStructure.makeTop();
  198. m_futurePossibleStructure.makeTop();
  199. m_arrayModes = ALL_ARRAY_MODES;
  200. }
  201. m_value = JSValue();
  202. checkConsistency();
  203. }
  204. void filter(const StructureSet& other)
  205. {
  206. // FIXME: This could be optimized for the common case of m_type not
  207. // having structures, array modes, or a specific value.
  208. // https://bugs.webkit.org/show_bug.cgi?id=109663
  209. m_type &= other.speculationFromStructures();
  210. m_arrayModes &= other.arrayModesFromStructures();
  211. m_currentKnownStructure.filter(other);
  212. if (m_currentKnownStructure.isClear())
  213. m_futurePossibleStructure.clear();
  214. else if (m_currentKnownStructure.hasSingleton())
  215. filterFuturePossibleStructure(m_currentKnownStructure.singleton());
  216. // It's possible that prior to the above two statements we had (Foo, TOP), where
  217. // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
  218. // case, we will now have (None, [someStructure]). In general, we need to make
  219. // sure that new information gleaned from the SpeculatedType needs to be fed back
  220. // into the information gleaned from the StructureSet.
  221. m_currentKnownStructure.filter(m_type);
  222. m_futurePossibleStructure.filter(m_type);
  223. filterArrayModesByType();
  224. filterValueByType();
  225. checkConsistency();
  226. }
  227. void filterArrayModes(ArrayModes arrayModes)
  228. {
  229. ASSERT(arrayModes);
  230. m_type &= SpecCell;
  231. m_arrayModes &= arrayModes;
  232. // I could do more fancy filtering here. But it probably won't make any difference.
  233. checkConsistency();
  234. }
  235. void filter(SpeculatedType type)
  236. {
  237. if (type == SpecTop)
  238. return;
  239. m_type &= type;
  240. // It's possible that prior to this filter() call we had, say, (Final, TOP), and
  241. // the passed type is Array. At this point we'll have (None, TOP). The best way
  242. // to ensure that the structure filtering does the right thing is to filter on
  243. // the new type (None) rather than the one passed (Array).
  244. m_currentKnownStructure.filter(m_type);
  245. m_futurePossibleStructure.filter(m_type);
  246. filterArrayModesByType();
  247. filterValueByType();
  248. checkConsistency();
  249. }
  250. void filterByValue(JSValue value)
  251. {
  252. filter(speculationFromValue(value));
  253. if (m_type)
  254. m_value = value;
  255. }
  256. bool validateType(JSValue value) const
  257. {
  258. if (isTop())
  259. return true;
  260. if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
  261. return false;
  262. if (value.isEmpty()) {
  263. ASSERT(m_type & SpecEmpty);
  264. return true;
  265. }
  266. return true;
  267. }
  268. bool validate(JSValue value) const
  269. {
  270. if (isTop())
  271. return true;
  272. if (!!m_value && m_value != value)
  273. return false;
  274. if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
  275. return false;
  276. if (value.isEmpty()) {
  277. ASSERT(m_type & SpecEmpty);
  278. return true;
  279. }
  280. if (!!value && value.isCell()) {
  281. ASSERT(m_type & SpecCell);
  282. Structure* structure = value.asCell()->structure();
  283. return m_currentKnownStructure.contains(structure)
  284. && m_futurePossibleStructure.contains(structure)
  285. && (m_arrayModes & asArrayModes(structure->indexingType()));
  286. }
  287. return true;
  288. }
  289. Structure* bestProvenStructure() const
  290. {
  291. if (m_currentKnownStructure.hasSingleton())
  292. return m_currentKnownStructure.singleton();
  293. if (m_futurePossibleStructure.hasSingleton())
  294. return m_futurePossibleStructure.singleton();
  295. return 0;
  296. }
  297. void checkConsistency() const
  298. {
  299. if (!(m_type & SpecCell)) {
  300. ASSERT(m_currentKnownStructure.isClear());
  301. ASSERT(m_futurePossibleStructure.isClear());
  302. ASSERT(!m_arrayModes);
  303. }
  304. if (isClear())
  305. ASSERT(!m_value);
  306. if (!!m_value)
  307. ASSERT(mergeSpeculations(m_type, speculationFromValue(m_value)) == m_type);
  308. // Note that it's possible for a prediction like (Final, []). This really means that
  309. // the value is bottom and that any code that uses the value is unreachable. But
  310. // we don't want to get pedantic about this as it would only increase the computational
  311. // complexity of the code.
  312. }
  313. void dump(PrintStream& out) const
  314. {
  315. out.print(
  316. "(", SpeculationDump(m_type), ", ", ArrayModesDump(m_arrayModes), ", ",
  317. m_currentKnownStructure, ", ", m_futurePossibleStructure);
  318. if (!!m_value)
  319. out.print(", ", m_value);
  320. out.print(")");
  321. }
  322. // A great way to think about the difference between m_currentKnownStructure and
  323. // m_futurePossibleStructure is to consider these four examples:
  324. //
  325. // 1) x = foo();
  326. //
  327. // In this case x's m_currentKnownStructure and m_futurePossibleStructure will
  328. // both be TOP, since we don't know anything about x for sure, yet.
  329. //
  330. // 2) x = foo();
  331. // y = x.f;
  332. //
  333. // Where x will later have a new property added to it, 'g'. Because of the
  334. // known but not-yet-executed property addition, x's currently structure will
  335. // not be watchpointable; hence we have no way of statically bounding the set
  336. // of possible structures that x may have if a clobbering event happens. So,
  337. // x's m_currentKnownStructure will be whatever structure we check to get
  338. // property 'f', and m_futurePossibleStructure will be TOP.
  339. //
  340. // 3) x = foo();
  341. // y = x.f;
  342. //
  343. // Where x has a terminal structure that is still watchpointable. In this case,
  344. // x's m_currentKnownStructure and m_futurePossibleStructure will both be
  345. // whatever structure we checked for when getting 'f'.
  346. //
  347. // 4) x = foo();
  348. // y = x.f;
  349. // bar();
  350. //
  351. // Where x has a terminal structure that is still watchpointable. In this
  352. // case, m_currentKnownStructure will be TOP because bar() may potentially
  353. // change x's structure and we have no way of proving otherwise, but
  354. // x's m_futurePossibleStructure will be whatever structure we had checked
  355. // when getting property 'f'.
  356. // NB. All fields in this struct must have trivial destructors.
  357. // This is a proven constraint on the structures that this value can have right
  358. // now. The structure of the current value must belong to this set. The set may
  359. // be TOP, indicating that it is the set of all possible structures, in which
  360. // case the current value can have any structure. The set may be BOTTOM (empty)
  361. // in which case this value cannot be a cell. This is all subject to change
  362. // anytime a new value is assigned to this one, anytime there is a control flow
  363. // merge, or most crucially, anytime a side-effect or structure check happens.
  364. // In case of a side-effect, we typically must assume that any value may have
  365. // had its structure changed, hence contravening our proof. We make the proof
  366. // valid again by switching this to TOP (i.e. claiming that we have proved that
  367. // this value may have any structure). Of note is that the proof represented by
  368. // this field is not subject to structure transition watchpoints - even if one
  369. // fires, we can be sure that this proof is still valid.
  370. StructureAbstractValue m_currentKnownStructure;
  371. // This is a proven constraint on the structures that this value can have now
  372. // or any time in the future subject to the structure transition watchpoints of
  373. // all members of this set not having fired. This set is impervious to side-
  374. // effects; even if one happens the side-effect can only cause the value to
  375. // change to at worst another structure that is also a member of this set. But,
  376. // the theorem being proved by this field is predicated upon there not being
  377. // any new structure transitions introduced into any members of this set. In
  378. // cases where there is no way for us to guard this happening, the set must be
  379. // TOP. But in cases where we can guard new structure transitions (all members
  380. // of the set have still-valid structure transition watchpoints) then this set
  381. // will be finite. Anytime that we make use of the finite nature of this set,
  382. // we must first issue a structure transition watchpoint, which will effectively
  383. // result in m_currentKnownStructure being filtered according to
  384. // m_futurePossibleStructure.
  385. StructureAbstractValue m_futurePossibleStructure;
  386. // This is a proven constraint on the possible types that this value can have
  387. // now or any time in the future, unless it is reassigned. This field is
  388. // impervious to side-effects unless the side-effect can reassign the value
  389. // (for example if we're talking about a captured variable). The relationship
  390. // between this field, and the structure fields above, is as follows. The
  391. // fields above constraint the structures that a cell may have, but they say
  392. // nothing about whether or not the value is known to be a cell. More formally,
  393. // the m_currentKnownStructure is itself an abstract value that consists of the
  394. // union of the set of all non-cell values and the set of cell values that have
  395. // the given structure. This abstract value is then the intersection of the
  396. // m_currentKnownStructure and the set of values whose type is m_type. So, for
  397. // example if m_type is SpecFinal|SpecInt32 and m_currentKnownStructure is
  398. // [0x12345] then this abstract value corresponds to the set of all integers
  399. // unified with the set of all objects with structure 0x12345.
  400. SpeculatedType m_type;
  401. // This is a proven constraint on the possible indexing types that this value
  402. // can have right now. It also implicitly constraints the set of structures
  403. // that the value may have right now, since a structure has an immutable
  404. // indexing type. This is subject to change upon reassignment, or any side
  405. // effect that makes non-obvious changes to the heap.
  406. ArrayModes m_arrayModes;
  407. // This is a proven constraint on the possible values that this value can
  408. // have now or any time in the future, unless it is reassigned. Note that this
  409. // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value)
  410. // means either BOTTOM or TOP depending on the state of m_type: if m_type is
  411. // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue()
  412. // means TOP.
  413. JSValue m_value;
  414. private:
  415. void clobberArrayModes()
  416. {
  417. // FIXME: We could make this try to predict the set of array modes that this object
  418. // could have in the future. For now, just do the simple thing.
  419. m_arrayModes = ALL_ARRAY_MODES;
  420. }
  421. void setFuturePossibleStructure(Structure* structure)
  422. {
  423. if (structure->transitionWatchpointSetIsStillValid())
  424. m_futurePossibleStructure = structure;
  425. else
  426. m_futurePossibleStructure.makeTop();
  427. }
  428. void filterFuturePossibleStructure(Structure* structure)
  429. {
  430. if (structure->transitionWatchpointSetIsStillValid())
  431. m_futurePossibleStructure.filter(StructureAbstractValue(structure));
  432. }
  433. // We could go further, and ensure that if the futurePossibleStructure contravenes
  434. // the value, then we could clear both of those things. But that's unlikely to help
  435. // in any realistic scenario, so we don't do it. Simpler is better.
  436. void filterValueByType()
  437. {
  438. if (!!m_type) {
  439. // The type is still non-empty. This implies that regardless of what filtering
  440. // was done, we either didn't have a value to begin with, or that value is still
  441. // valid.
  442. ASSERT(!m_value || validateType(m_value));
  443. return;
  444. }
  445. // The type has been rendered empty. That means that the value must now be invalid,
  446. // as well.
  447. ASSERT(!m_value || !validateType(m_value));
  448. m_value = JSValue();
  449. }
  450. void filterArrayModesByType()
  451. {
  452. if (!(m_type & SpecCell))
  453. m_arrayModes = 0;
  454. else if (!(m_type & ~SpecArray))
  455. m_arrayModes &= ALL_ARRAY_ARRAY_MODES;
  456. // NOTE: If m_type doesn't have SpecArray set, that doesn't mean that the
  457. // array modes have to be a subset of ALL_NON_ARRAY_ARRAY_MODES, since
  458. // in the speculated type type-system, RegExpMatchesArry and ArrayPrototype
  459. // are Otherobj (since they are not *exactly* JSArray) but in the ArrayModes
  460. // type system they are arrays (since they expose the magical length
  461. // property and are otherwise allocated using array allocation). Hence the
  462. // following would be wrong:
  463. //
  464. // if (!(m_type & SpecArray))
  465. // m_arrayModes &= ALL_NON_ARRAY_ARRAY_MODES;
  466. }
  467. };
  468. } } // namespace JSC::DFG
  469. #endif // ENABLE(DFG_JIT)
  470. #endif // DFGAbstractValue_h