diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-22 15:40:17 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-22 15:40:17 +0200 |
commit | 43a42f108af6bcbd91f2672731c3047c26213af1 (patch) | |
tree | 7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/dfg/DFGAbstractValue.h | |
parent | d9cf437c840c6eb7417bdd97e6c40979255d3158 (diff) | |
download | qtwebkit-43a42f108af6bcbd91f2672731c3047c26213af1.tar.gz |
Imported WebKit commit 302e7806bff028bd1167a1ec7c86a1ee00ecfb49 (http://svn.webkit.org/repository/webkit/trunk@132067)
New snapshot that fixes build without QtWidgets
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractValue.h')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGAbstractValue.h | 161 |
1 files changed, 120 insertions, 41 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h index ff1c6d205..5382cd3ad 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h @@ -30,6 +30,7 @@ #if ENABLE(DFG_JIT) +#include "ArrayProfile.h" #include "DFGStructureAbstractValue.h" #include "JSCell.h" #include "SpeculatedType.h" @@ -40,12 +41,14 @@ namespace JSC { namespace DFG { struct AbstractValue { AbstractValue() : m_type(SpecNone) + , m_arrayModes(0) { } void clear() { m_type = SpecNone; + m_arrayModes = 0; m_currentKnownStructure.clear(); m_futurePossibleStructure.clear(); m_value = JSValue(); @@ -54,7 +57,7 @@ struct AbstractValue { bool isClear() const { - bool result = m_type == SpecNone && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear(); + bool result = m_type == SpecNone && !m_arrayModes && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear(); if (result) ASSERT(!m_value); return result; @@ -63,6 +66,7 @@ struct AbstractValue { void makeTop() { m_type = SpecTop; + m_arrayModes = ALL_ARRAY_MODES; m_currentKnownStructure.makeTop(); m_futurePossibleStructure.makeTop(); m_value = JSValue(); @@ -71,13 +75,16 @@ struct AbstractValue { void clobberStructures() { - if (m_type & SpecCell) + if (m_type & SpecCell) { m_currentKnownStructure.makeTop(); - else + clobberArrayModes(); + } else { ASSERT(m_currentKnownStructure.isClear()); + ASSERT(!m_arrayModes); + } checkConsistency(); } - + void clobberValue() { m_value = JSValue(); @@ -105,29 +112,17 @@ struct AbstractValue { return result; } - void setFuturePossibleStructure(Structure* structure) - { - if (structure->transitionWatchpointSetIsStillValid()) - m_futurePossibleStructure = structure; - else - m_futurePossibleStructure.makeTop(); - } - - void filterFuturePossibleStructure(Structure* structure) - { - if (structure->transitionWatchpointSetIsStillValid()) - m_futurePossibleStructure.filter(StructureAbstractValue(structure)); - } - void setMostSpecific(JSValue value) { if (!!value && value.isCell()) { Structure* structure = value.asCell()->structure(); m_currentKnownStructure = structure; setFuturePossibleStructure(structure); + m_arrayModes = asArrayModes(structure->indexingType()); } else { m_currentKnownStructure.clear(); m_futurePossibleStructure.clear(); + m_arrayModes = 0; } m_type = speculationFromValue(value); @@ -140,10 +135,14 @@ struct AbstractValue { { if (!!value && value.isCell()) { m_currentKnownStructure.makeTop(); - setFuturePossibleStructure(value.asCell()->structure()); + Structure* structure = value.asCell()->structure(); + setFuturePossibleStructure(structure); + m_arrayModes = asArrayModes(structure->indexingType()); + clobberArrayModes(); } else { m_currentKnownStructure.clear(); m_futurePossibleStructure.clear(); + m_arrayModes = 0; } m_type = speculationFromValue(value); @@ -156,6 +155,7 @@ struct AbstractValue { { m_currentKnownStructure = structure; setFuturePossibleStructure(structure); + m_arrayModes = asArrayModes(structure->indexingType()); m_type = speculationFromStructure(structure); m_value = JSValue(); @@ -167,9 +167,11 @@ struct AbstractValue { if (type & SpecCell) { m_currentKnownStructure.makeTop(); m_futurePossibleStructure.makeTop(); + m_arrayModes = ALL_ARRAY_MODES; } else { m_currentKnownStructure.clear(); m_futurePossibleStructure.clear(); + m_arrayModes = 0; } m_type = type; m_value = JSValue(); @@ -179,6 +181,7 @@ struct AbstractValue { bool operator==(const AbstractValue& other) const { return m_type == other.m_type + && m_arrayModes == other.m_arrayModes && m_currentKnownStructure == other.m_currentKnownStructure && m_futurePossibleStructure == other.m_futurePossibleStructure && m_value == other.m_value; @@ -199,6 +202,7 @@ struct AbstractValue { result = !other.isClear(); } else { result |= mergeSpeculation(m_type, other.m_type); + result |= mergeArrayModes(m_arrayModes, other.m_arrayModes); result |= m_currentKnownStructure.addAll(other.m_currentKnownStructure); result |= m_futurePossibleStructure.addAll(other.m_futurePossibleStructure); if (m_value != other.m_value) { @@ -218,6 +222,7 @@ struct AbstractValue { if (type & SpecCell) { m_currentKnownStructure.makeTop(); m_futurePossibleStructure.makeTop(); + m_arrayModes = ALL_ARRAY_MODES; } m_value = JSValue(); @@ -227,6 +232,7 @@ struct AbstractValue { void filter(const StructureSet& other) { m_type &= other.speculationFromStructures(); + m_arrayModes &= other.arrayModesFromStructures(); m_currentKnownStructure.filter(other); if (m_currentKnownStructure.isClear()) m_futurePossibleStructure.clear(); @@ -241,11 +247,24 @@ struct AbstractValue { m_currentKnownStructure.filter(m_type); m_futurePossibleStructure.filter(m_type); + filterArrayModesByType(); filterValueByType(); checkConsistency(); } + void filterArrayModes(ArrayModes arrayModes) + { + ASSERT(arrayModes); + + m_type &= SpecCell; + m_arrayModes &= arrayModes; + + // I could do more fancy filtering here. But it probably won't make any difference. + + checkConsistency(); + } + void filter(SpeculatedType type) { if (type == SpecTop) @@ -258,31 +277,13 @@ struct AbstractValue { // the new type (None) rather than the one passed (Array). m_currentKnownStructure.filter(m_type); m_futurePossibleStructure.filter(m_type); - + + filterArrayModesByType(); filterValueByType(); checkConsistency(); } - // We could go further, and ensure that if the futurePossibleStructure contravenes - // the value, then we could clear both of those things. But that's unlikely to help - // in any realistic scenario, so we don't do it. Simpler is better. - void filterValueByType() - { - if (!!m_type) { - // The type is still non-empty. This implies that regardless of what filtering - // was done, we either didn't have a value to begin with, or that value is still - // valid. - ASSERT(!m_value || validateType(m_value)); - return; - } - - // The type has been rendered empty. That means that the value must now be invalid, - // as well. - ASSERT(!m_value || !validateType(m_value)); - m_value = JSValue(); - } - bool validateType(JSValue value) const { if (isTop()) @@ -319,7 +320,8 @@ struct AbstractValue { ASSERT(m_type & SpecCell); Structure* structure = value.asCell()->structure(); return m_currentKnownStructure.contains(structure) - && m_futurePossibleStructure.contains(structure); + && m_futurePossibleStructure.contains(structure) + && (m_arrayModes & asArrayModes(structure->indexingType())); } return true; @@ -330,6 +332,7 @@ struct AbstractValue { if (!(m_type & SpecCell)) { ASSERT(m_currentKnownStructure.isClear()); ASSERT(m_futurePossibleStructure.isClear()); + ASSERT(!m_arrayModes); } if (isClear()) @@ -346,7 +349,7 @@ struct AbstractValue { void dump(FILE* out) const { - fprintf(out, "(%s, ", speculationToString(m_type)); + fprintf(out, "(%s, %s, ", speculationToString(m_type), arrayModesToString(m_arrayModes)); m_currentKnownStructure.dump(out); dataLog(", "); m_futurePossibleStructure.dump(out); @@ -437,6 +440,13 @@ struct AbstractValue { // unified with the set of all objects with structure 0x12345. SpeculatedType m_type; + // This is a proven constraint on the possible indexing types that this value + // can have right now. It also implicitly constraints the set of structures + // that the value may have right now, since a structure has an immutable + // indexing type. This is subject to change upon reassignment, or any side + // effect that makes non-obvious changes to the heap. + ArrayModes m_arrayModes; + // This is a proven constraint on the possible values that this value can // have now or any time in the future, unless it is reassigned. Note that this // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value) @@ -444,6 +454,75 @@ struct AbstractValue { // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue() // means TOP. JSValue m_value; + +private: + void clobberArrayModes() + { + if (m_arrayModes == ALL_ARRAY_MODES) + return; + + if (LIKELY(m_arrayModes & asArrayModes(NonArray))) + m_arrayModes = ALL_ARRAY_MODES; + else + clobberArrayModesSlow(); + } + + void clobberArrayModesSlow() + { + if (m_arrayModes & asArrayModes(ArrayClass)) + m_arrayModes = ALL_ARRAY_MODES; + else if (m_arrayModes & asArrayModes(NonArrayWithContiguous)) + m_arrayModes |= asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage); + else if (m_arrayModes & asArrayModes(ArrayWithContiguous)) + m_arrayModes |= asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage); + else if (m_arrayModes & asArrayModes(NonArrayWithArrayStorage)) + m_arrayModes |= asArrayModes(NonArrayWithSlowPutArrayStorage); + else if (m_arrayModes & asArrayModes(ArrayWithArrayStorage)) + m_arrayModes |= asArrayModes(ArrayWithArrayStorage); + } + + void setFuturePossibleStructure(Structure* structure) + { + if (structure->transitionWatchpointSetIsStillValid()) + m_futurePossibleStructure = structure; + else + m_futurePossibleStructure.makeTop(); + } + + void filterFuturePossibleStructure(Structure* structure) + { + if (structure->transitionWatchpointSetIsStillValid()) + m_futurePossibleStructure.filter(StructureAbstractValue(structure)); + } + + // We could go further, and ensure that if the futurePossibleStructure contravenes + // the value, then we could clear both of those things. But that's unlikely to help + // in any realistic scenario, so we don't do it. Simpler is better. + void filterValueByType() + { + if (!!m_type) { + // The type is still non-empty. This implies that regardless of what filtering + // was done, we either didn't have a value to begin with, or that value is still + // valid. + ASSERT(!m_value || validateType(m_value)); + return; + } + + // The type has been rendered empty. That means that the value must now be invalid, + // as well. + ASSERT(!m_value || !validateType(m_value)); + m_value = JSValue(); + } + + void filterArrayModesByType() + { + if (!(m_type & SpecCell)) + m_arrayModes = 0; + else if (!(m_type & ~SpecArray)) + m_arrayModes &= ALL_ARRAY_ARRAY_MODES; + else if (!(m_type & SpecArray)) + m_arrayModes &= ALL_NON_ARRAY_ARRAY_MODES; + } }; } } // namespace JSC::DFG |