summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-09 09:42:44 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-09 09:42:44 +0100
commita59391482883479a9b28a6f1ace6d1ebd08a7ecd (patch)
treefa539db054a20a67bff2fc891c33b0f4ec632916 /Source/JavaScriptCore/dfg/DFGAbstractState.cpp
parentcfd86b747d32ac22246a1aa908eaa720c63a88c1 (diff)
downloadqtwebkit-a59391482883479a9b28a6f1ace6d1ebd08a7ecd.tar.gz
Imported WebKit commit 7bcdfab9a40db7d16b4b95bb77d78b8a59c9e701 (http://svn.webkit.org/repository/webkit/trunk@134025)
New snapshot with numerious build fixes, including MSVC 2012 and ARM Thumb-2.
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractState.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp136
1 files changed, 107 insertions, 29 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index e518c24a8..02e578b29 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -159,7 +159,7 @@ void AbstractState::initialize(Graph& graph)
}
}
-bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr)
+bool AbstractState::endBasicBlock(MergeMode mergeMode)
{
ASSERT(m_block);
@@ -167,6 +167,7 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDi
block->cfaFoundConstants = m_foundConstants;
block->cfaDidFinish = m_isValid;
+ block->cfaBranchDirection = m_branchDirection;
if (!m_isValid) {
reset();
@@ -195,12 +196,8 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDi
ASSERT(mergeMode != DontMerge || !changed);
- BranchDirection branchDirection = m_branchDirection;
- if (branchDirectionPtr)
- *branchDirectionPtr = branchDirection;
-
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection));
+ dataLog(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
#endif
reset();
@@ -208,7 +205,7 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDi
if (mergeMode != MergeToSuccessors)
return changed;
- return mergeToSuccessors(m_graph, block, branchDirection);
+ return mergeToSuccessors(m_graph, block);
}
void AbstractState::reset()
@@ -424,7 +421,10 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(SpecDouble);
+ if (isInt32Speculation(forNode(node.child1()).m_type))
+ forNode(nodeIndex).set(SpecDoubleReal);
+ else
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -448,9 +448,13 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).set(SpecInt32);
break;
}
- if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
+ if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) {
speculateNumberBinary(node);
- forNode(nodeIndex).set(SpecDouble);
+ if (isRealNumberSpeculation(forNode(node.child1()).m_type)
+ && isRealNumberSpeculation(forNode(node.child2()).m_type))
+ forNode(nodeIndex).set(SpecDoubleReal);
+ else
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (node.op() == ValueAdd) {
@@ -522,7 +526,11 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(SpecDouble);
+ if (isRealNumberSpeculation(forNode(node.child1()).m_type)
+ || isRealNumberSpeculation(forNode(node.child2()).m_type))
+ forNode(nodeIndex).set(SpecDoubleReal);
+ else
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -560,7 +568,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
}
- if (Node::shouldSpeculateInteger(
+ if (Node::shouldSpeculateIntegerForArithmetic(
m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger()) {
speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
@@ -580,7 +588,7 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
- if (m_graph[node.child1()].shouldSpeculateInteger()
+ if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
&& node.canSpeculateInteger()) {
speculateInt32Unary(node, true);
forNode(nodeIndex).set(SpecInt32);
@@ -605,12 +613,22 @@ bool AbstractState::execute(unsigned indexInBlock)
}
case LogicalNot: {
+ // First check if we can fold because the source is a constant.
JSValue childConst = forNode(node.child1()).value();
if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec())))) {
m_foundConstants = true;
node.setCanExit(false);
break;
}
+ // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
+ if (isCellSpeculation(forNode(node.child1()).m_type)
+ && forNode(node.child1()).m_currentKnownStructure.hasSingleton()
+ && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
+ && trySetConstant(nodeIndex, jsBoolean(false))) {
+ m_foundConstants = true;
+ node.setCanExit(false);
+ break;
+ }
Node& child = m_graph[node.child1()];
if (isBooleanSpeculation(child.prediction()))
speculateBooleanUnary(node);
@@ -678,12 +696,13 @@ bool AbstractState::execute(unsigned indexInBlock)
case CompareGreater:
case CompareGreaterEq:
case CompareEq: {
+ bool constantWasSet = false;
+
JSValue leftConst = forNode(node.child1()).value();
JSValue rightConst = forNode(node.child2()).value();
if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
double a = leftConst.asNumber();
double b = rightConst.asNumber();
- bool constantWasSet;
switch (node.op()) {
case CompareLess:
constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
@@ -705,11 +724,20 @@ bool AbstractState::execute(unsigned indexInBlock)
constantWasSet = false;
break;
}
- if (constantWasSet) {
- m_foundConstants = true;
- node.setCanExit(false);
- break;
- }
+ }
+
+ if (!constantWasSet && node.op() == CompareEq) {
+ SpeculatedType leftType = forNode(node.child1()).m_type;
+ SpeculatedType rightType = forNode(node.child2()).m_type;
+ if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
+ || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
+ constantWasSet = trySetConstant(nodeIndex, jsBoolean(false));
+ }
+
+ if (constantWasSet) {
+ m_foundConstants = true;
+ node.setCanExit(false);
+ break;
}
forNode(nodeIndex).set(SpecBoolean);
@@ -842,6 +870,7 @@ bool AbstractState::execute(unsigned indexInBlock)
switch (node.arrayMode().type()) {
case Array::SelectUsingPredictions:
case Array::Unprofiled:
+ case Array::Undecided:
ASSERT_NOT_REACHED();
break;
case Array::ForceExit:
@@ -859,6 +888,22 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
+ case Array::Int32:
+ forNode(node.child2()).filter(SpecInt32);
+ if (node.arrayMode().isOutOfBounds()) {
+ clobberWorld(node.codeOrigin, indexInBlock);
+ forNode(nodeIndex).makeTop();
+ } else
+ forNode(nodeIndex).set(SpecInt32);
+ break;
+ case Array::Double:
+ forNode(node.child2()).filter(SpecInt32);
+ if (node.arrayMode().isOutOfBounds()) {
+ clobberWorld(node.codeOrigin, indexInBlock);
+ forNode(nodeIndex).makeTop();
+ } else
+ forNode(nodeIndex).set(SpecDoubleReal);
+ break;
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
@@ -926,6 +971,20 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::Generic:
clobberWorld(node.codeOrigin, indexInBlock);
break;
+ case Array::Int32:
+ forNode(child1).filter(SpecCell);
+ forNode(child2).filter(SpecInt32);
+ forNode(child3).filter(SpecInt32);
+ if (node.arrayMode().isOutOfBounds())
+ clobberWorld(node.codeOrigin, indexInBlock);
+ break;
+ case Array::Double:
+ forNode(child1).filter(SpecCell);
+ forNode(child2).filter(SpecInt32);
+ forNode(child3).filter(SpecRealNumber);
+ if (node.arrayMode().isOutOfBounds())
+ clobberWorld(node.codeOrigin, indexInBlock);
+ break;
case Array::Contiguous:
case Array::ArrayStorage:
forNode(child1).filter(SpecCell);
@@ -1018,6 +1077,16 @@ bool AbstractState::execute(unsigned indexInBlock)
case ArrayPush:
node.setCanExit(true);
+ switch (node.arrayMode().type()) {
+ case Array::Int32:
+ forNode(node.child2()).filter(SpecInt32);
+ break;
+ case Array::Double:
+ forNode(node.child2()).filter(SpecRealNumber);
+ break;
+ default:
+ break;
+ }
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).set(SpecNumber);
break;
@@ -1043,6 +1112,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case Branch: {
+ // First check if we can fold because the source is a constant.
JSValue value = forNode(node.child1()).value();
if (value) {
bool booleanValue = value.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec());
@@ -1053,6 +1123,14 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
+ // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
+ if (isCellSpeculation(forNode(node.child1()).m_type)
+ && forNode(node.child1()).m_currentKnownStructure.hasSingleton()
+ && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))) {
+ m_branchDirection = TakeTrue;
+ node.setCanExit(false);
+ break;
+ }
// FIXME: The above handles the trivial cases of sparse conditional
// constant propagation, but we can do better:
// 1) If the abstract value does not have a concrete value but describes
@@ -1122,13 +1200,13 @@ bool AbstractState::execute(unsigned indexInBlock)
case NewArray:
node.setCanExit(true);
- forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
m_haveStructures = true;
break;
case NewArrayBuffer:
node.setCanExit(true);
- forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
m_haveStructures = true;
break;
@@ -1384,11 +1462,11 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::String:
forNode(node.child1()).filter(SpecString);
break;
+ case Array::Int32:
+ case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
- // This doesn't filter anything meaningful right now. We may want to add
- // CFA tracking of array mode speculations, but we don't have that, yet.
forNode(node.child1()).filter(SpecCell);
break;
case Array::Arguments:
@@ -1722,7 +1800,7 @@ inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
}
inline bool AbstractState::mergeToSuccessors(
- Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection)
+ Graph& graph, BasicBlock* basicBlock)
{
Node& terminal = graph[basicBlock->last()];
@@ -1730,7 +1808,7 @@ inline bool AbstractState::mergeToSuccessors(
switch (terminal.op()) {
case Jump: {
- ASSERT(branchDirection == InvalidBranchDirection);
+ ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
#endif
@@ -1738,17 +1816,17 @@ inline bool AbstractState::mergeToSuccessors(
}
case Branch: {
- ASSERT(branchDirection != InvalidBranchDirection);
+ ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
bool changed = false;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
#endif
- if (branchDirection != TakeFalse)
+ if (basicBlock->cfaBranchDirection != TakeFalse)
changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
#endif
- if (branchDirection != TakeTrue)
+ if (basicBlock->cfaBranchDirection != TakeTrue)
changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
return changed;
}
@@ -1756,7 +1834,7 @@ inline bool AbstractState::mergeToSuccessors(
case Return:
case Throw:
case ThrowReferenceError:
- ASSERT(branchDirection == InvalidBranchDirection);
+ ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
return false;
default: