summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-08-21 10:57:44 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-08-21 10:57:44 +0200
commit5ef7c8a6a70875d4430752d146bdcb069605d71d (patch)
treef6256640b6c46d7da221435803cae65326817ba2 /Source/JavaScriptCore/dfg/DFGAbstractState.cpp
parentdecad929f578d8db641febc8740649ca6c574638 (diff)
downloadqtwebkit-5ef7c8a6a70875d4430752d146bdcb069605d71d.tar.gz
Imported WebKit commit 356d83016b090995d08ad568f2d2c243aa55e831 (http://svn.webkit.org/repository/webkit/trunk@126147)
New snapshot including various build fixes for newer Qt 5
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractState.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp87
1 files changed, 60 insertions, 27 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 4f02ee793..5c53f6d78 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -62,13 +62,13 @@ void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
m_variables = basicBlock->valuesAtHead;
m_haveStructures = false;
for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
- if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
+ if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
m_haveStructures = true;
break;
}
}
for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
- if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
+ if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
m_haveStructures = true;
break;
}
@@ -106,8 +106,6 @@ void AbstractState::initialize(Graph& graph)
SpeculatedType prediction = node.variableAccessData()->prediction();
if (isInt32Speculation(prediction))
root->valuesAtHead.argument(i).set(SpecInt32);
- else if (isArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecArray);
else if (isBooleanSpeculation(prediction))
root->valuesAtHead.argument(i).set(SpecBoolean);
else if (isInt8ArraySpeculation(prediction))
@@ -160,6 +158,16 @@ void AbstractState::initialize(Graph& graph)
block->valuesAtHead.local(i).clear();
block->valuesAtTail.local(i).clear();
}
+ if (!block->isOSRTarget)
+ continue;
+ if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
+ continue;
+ for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
+ AbstractValue value;
+ value.setMostSpecific(graph.m_mustHandleValues[i]);
+ block->valuesAtHead.operand(graph.m_mustHandleValues.operandForIndex(i)).merge(value);
+ }
+ block->cfaShouldRevisit = true;
}
}
@@ -290,10 +298,7 @@ bool AbstractState::execute(unsigned indexInBlock)
SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
if (isInt32Speculation(predictedType))
speculateInt32Unary(node);
- else if (isArraySpeculation(predictedType)) {
- node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecArray);
- } else if (isCellSpeculation(predictedType)) {
+ else if (isCellSpeculation(predictedType)) {
node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
forNode(node.child1()).filter(SpecCell);
} else if (isBooleanSpeculation(predictedType))
@@ -867,7 +872,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
+ if (!m_graph[node.child2()].shouldSpeculateInteger() || (!node.child3() && !m_graph[node.child1()].shouldSpeculateArguments())) {
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
@@ -942,8 +947,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).set(SpecDouble);
break;
}
- ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
@@ -962,7 +966,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!m_graph[child2].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[child1].prediction())
+ if (!m_graph[child2].shouldSpeculateInteger()
#if USE(JSVALUE32_64)
|| m_graph[child1].shouldSpeculateArguments()
#endif
@@ -1053,8 +1057,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
}
- ASSERT(m_graph[child1].shouldSpeculateArray());
- forNode(child1).filter(SpecArray);
+ forNode(child1).filter(SpecCell);
forNode(child2).filter(SpecInt32);
if (node.op() == PutByValSafe)
clobberWorld(node.codeOrigin, indexInBlock);
@@ -1063,13 +1066,13 @@ bool AbstractState::execute(unsigned indexInBlock)
case ArrayPush:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).set(SpecNumber);
break;
case ArrayPop:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
@@ -1354,7 +1357,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetArrayLength:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).set(SpecInt32);
break;
@@ -1420,19 +1423,52 @@ bool AbstractState::execute(unsigned indexInBlock)
case ForwardCheckStructure: {
// FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
AbstractValue& value = forNode(node.child1());
+ // If this structure check is attempting to prove knowledge already held in
+ // the futurePossibleStructure set then the constant folding phase should
+ // turn this into a watchpoint instead.
+ StructureSet& set = node.structureSet();
+ if (value.m_futurePossibleStructure.isSubsetOf(set))
+ m_foundConstants = true;
node.setCanExit(
- !value.m_structure.isSubsetOf(node.structureSet())
+ !value.m_currentKnownStructure.isSubsetOf(set)
|| !isCellSpeculation(value.m_type));
- value.filter(node.structureSet());
+ value.filter(set);
+ // This is likely to be unnecessary, but it's conservative, and that's a good thing.
+ // This is trying to avoid situations where the CFA proves that this structure check
+ // must fail due to a future structure proof. We have two options at that point. We
+ // can either compile all subsequent code as we would otherwise, or we can ensure
+ // that the subsequent code is never reachable. The former is correct because the
+ // Proof Is Infallible (TM) -- hence even if we don't force the subsequent code to
+ // be unreachable, it must be unreachable nonetheless. But imagine what would happen
+ // if the proof was borked. In the former case, we'd get really bizarre bugs where
+ // we assumed that the structure of this object was known even though it wasn't. In
+ // the latter case, we'd have a slight performance pathology because this would be
+ // turned into an OSR exit unnecessarily. Which would you rather have?
+ if (value.m_currentKnownStructure.isClear()
+ || value.m_futurePossibleStructure.isClear())
+ m_isValid = false;
m_haveStructures = true;
break;
}
- case StructureTransitionWatchpoint: {
- // FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
+ case StructureTransitionWatchpoint:
+ case ForwardStructureTransitionWatchpoint: {
AbstractValue& value = forNode(node.child1());
+
+ // It's only valid to issue a structure transition watchpoint if we already
+ // know that the watchpoint covers a superset of the structures known to
+ // belong to the set of future structures that this value may have.
+ // Currently, we only issue singleton watchpoints (that check one structure)
+ // and our futurePossibleStructure set can only contain zero, one, or an
+ // infinity of structures.
+ ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node.structure())));
+
ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.
value.filter(node.structure());
+ // See comment in CheckStructure for why this is here.
+ if (value.m_currentKnownStructure.isClear()
+ || value.m_futurePossibleStructure.isClear())
+ m_isValid = false;
m_haveStructures = true;
node.setCanExit(true);
break;
@@ -1453,12 +1489,9 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).clear(); // The result is not a JS value.
break;
case GetIndexedPropertyStorage: {
+ ASSERT(m_graph[node.child1()].prediction());
+ ASSERT(m_graph[node.child2()].shouldSpeculateInteger());
node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
- SpeculatedType basePrediction = m_graph[node.child2()].prediction();
- if (!(basePrediction & SpecInt32) && basePrediction) {
- forNode(nodeIndex).clear();
- break;
- }
if (m_graph[node.child1()].shouldSpeculateArguments()) {
ASSERT_NOT_REACHED();
break;
@@ -1514,7 +1547,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).clear();
break;
}
- forNode(node.child1()).filter(SpecArray);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).clear();
break;
}