summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGAbstractValue.h
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
commit43a42f108af6bcbd91f2672731c3047c26213af1 (patch)
tree7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/dfg/DFGAbstractValue.h
parentd9cf437c840c6eb7417bdd97e6c40979255d3158 (diff)
downloadqtwebkit-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.h161
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