summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractState.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp253
1 files changed, 65 insertions, 188 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 43b5a03f3..5f79f666f 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -108,24 +108,6 @@ void AbstractState::initialize(Graph& graph)
root->valuesAtHead.argument(i).set(SpecInt32);
else if (isBooleanSpeculation(prediction))
root->valuesAtHead.argument(i).set(SpecBoolean);
- else if (isInt8ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecInt8Array);
- else if (isInt16ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecInt16Array);
- else if (isInt32ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecInt32Array);
- else if (isUint8ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecUint8Array);
- else if (isUint8ClampedArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecUint8ClampedArray);
- else if (isUint16ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecUint16Array);
- else if (isUint32ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecUint32Array);
- else if (isFloat32ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecFloat32Array);
- else if (isFloat64ArraySpeculation(prediction))
- root->valuesAtHead.argument(i).set(SpecFloat64Array);
else if (isCellSpeculation(prediction))
root->valuesAtHead.argument(i).set(SpecCell);
else
@@ -626,14 +608,9 @@ bool AbstractState::execute(unsigned indexInBlock)
Node& child = m_graph[node.child1()];
if (isBooleanSpeculation(child.prediction()))
speculateBooleanUnary(node);
- else if (child.shouldSpeculateFinalObjectOrOther()) {
- node.setCanExit(
- !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecFinalObject | SpecOther);
- } else if (child.shouldSpeculateArrayOrOther()) {
- node.setCanExit(
- !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecArray | SpecOther);
+ else if (child.shouldSpeculateNonStringCellOrOther()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
@@ -751,45 +728,32 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
- if (Node::shouldSpeculateFinalObject(left, right)) {
- filter = SpecFinalObject;
- checker = isFinalObjectSpeculation;
- } else if (Node::shouldSpeculateArray(left, right)) {
- filter = SpecArray;
- checker = isArraySpeculation;
- } else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
- node.setCanExit(
- !isFinalObjectSpeculation(forNode(node.child1()).m_type)
- || !isFinalObjectOrOtherSpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecFinalObject);
- forNode(node.child2()).filter(SpecFinalObject | SpecOther);
+ if (left.shouldSpeculateString() || right.shouldSpeculateString()) {
+ node.setCanExit(false);
break;
- } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
- node.setCanExit(
- !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type)
- || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecFinalObject | SpecOther);
- forNode(node.child2()).filter(SpecFinalObject);
+ }
+ if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCellOrOther()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter(SpecCell & ~SpecString);
+ forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
break;
- } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
- node.setCanExit(
- !isArraySpeculation(forNode(node.child1()).m_type)
- || !isArrayOrOtherSpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecArray);
- forNode(node.child2()).filter(SpecArray | SpecOther);
+ }
+ if (left.shouldSpeculateNonStringCellOrOther() && right.shouldSpeculateNonStringCell()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
+ forNode(node.child2()).filter(SpecCell & ~SpecString);
break;
- } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
- node.setCanExit(
- !isArrayOrOtherSpeculation(forNode(node.child1()).m_type)
- || !isArraySpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecArray | SpecOther);
- forNode(node.child2()).filter(SpecArray);
+ }
+ if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCell()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter(SpecCell & ~SpecString);
+ forNode(node.child2()).filter(SpecCell & ~SpecString);
break;
- } else {
- filter = SpecTop;
- checker = isAnySpeculation;
- clobberWorld(node.codeOrigin, indexInBlock);
}
+
+ filter = SpecTop;
+ checker = isAnySpeculation;
+ clobberWorld(node.codeOrigin, indexInBlock);
} else {
filter = SpecTop;
checker = isAnySpeculation;
@@ -837,22 +801,16 @@ bool AbstractState::execute(unsigned indexInBlock)
speculateNumberBinary(node);
break;
}
- if (Node::shouldSpeculateFinalObject(
- m_graph[node.child1()], m_graph[node.child2()])) {
- node.setCanExit(
- !isFinalObjectSpeculation(forNode(node.child1()).m_type)
- || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecFinalObject);
- forNode(node.child2()).filter(SpecFinalObject);
+ Node& leftNode = m_graph[node.child1()];
+ Node& rightNode = m_graph[node.child2()];
+ if (leftNode.shouldSpeculateString() || rightNode.shouldSpeculateString()) {
+ node.setCanExit(false);
break;
}
- if (Node::shouldSpeculateArray(
- m_graph[node.child1()], m_graph[node.child2()])) {
- node.setCanExit(
- !isArraySpeculation(forNode(node.child1()).m_type)
- || !isArraySpeculation(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(SpecArray);
- forNode(node.child2()).filter(SpecArray);
+ if (leftNode.shouldSpeculateNonStringCell() && rightNode.shouldSpeculateNonStringCell()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
+ forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
break;
}
node.setCanExit(false);
@@ -887,55 +845,47 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).makeTop();
break;
case Array::String:
- forNode(node.child1()).filter(SpecString);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecString);
break;
case Array::Arguments:
- forNode(node.child1()).filter(SpecArguments);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
case Array::JSArray:
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).makeTop();
+ break;
case Array::JSArrayOutOfBounds:
- // FIXME: We should have more conservative handling of the out-of-bounds
- // case.
- forNode(node.child1()).filter(SpecCell);
forNode(node.child2()).filter(SpecInt32);
+ clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
case Array::Int8Array:
- forNode(node.child1()).filter(SpecInt8Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Int16Array:
- forNode(node.child1()).filter(SpecInt16Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Int32Array:
- forNode(node.child1()).filter(SpecInt32Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Uint8Array:
- forNode(node.child1()).filter(SpecUint8Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Uint8ClampedArray:
- forNode(node.child1()).filter(SpecUint8ClampedArray);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Uint16Array:
- forNode(node.child1()).filter(SpecUint16Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecInt32);
break;
case Array::Uint32Array:
- forNode(node.child1()).filter(SpecUint32Array);
forNode(node.child2()).filter(SpecInt32);
if (node.shouldSpeculateInteger())
forNode(nodeIndex).set(SpecInt32);
@@ -943,12 +893,10 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).set(SpecDouble);
break;
case Array::Float32Array:
- forNode(node.child1()).filter(SpecFloat32Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecDouble);
break;
case Array::Float64Array:
- forNode(node.child1()).filter(SpecFloat64Array);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecDouble);
break;
@@ -959,7 +907,6 @@ bool AbstractState::execute(unsigned indexInBlock)
case PutByVal:
case PutByValAlias: {
node.setCanExit(true);
- Edge child1 = m_graph.varArgChild(node, 0);
Edge child2 = m_graph.varArgChild(node, 1);
Edge child3 = m_graph.varArgChild(node, 2);
switch (modeForPut(node.arrayMode())) {
@@ -970,20 +917,16 @@ bool AbstractState::execute(unsigned indexInBlock)
clobberWorld(node.codeOrigin, indexInBlock);
break;
case Array::JSArray:
- forNode(child1).filter(SpecCell);
forNode(child2).filter(SpecInt32);
break;
case Array::JSArrayOutOfBounds:
- forNode(child1).filter(SpecCell);
forNode(child2).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
break;
case Array::Arguments:
- forNode(child1).filter(SpecArguments);
forNode(child2).filter(SpecInt32);
break;
case Array::Int8Array:
- forNode(child1).filter(SpecInt8Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -991,7 +934,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Int16Array:
- forNode(child1).filter(SpecInt16Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -999,7 +941,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Int32Array:
- forNode(child1).filter(SpecInt32Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -1007,7 +948,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Uint8Array:
- forNode(child1).filter(SpecUint8Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -1015,7 +955,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Uint8ClampedArray:
- forNode(child1).filter(SpecUint8ClampedArray);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -1023,7 +962,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Uint16Array:
- forNode(child1).filter(SpecUint16Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -1031,7 +969,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Uint32Array:
- forNode(child1).filter(SpecUint32Array);
forNode(child2).filter(SpecInt32);
if (m_graph[child3].shouldSpeculateInteger())
forNode(child3).filter(SpecInt32);
@@ -1039,12 +976,10 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(child3).filter(SpecNumber);
break;
case Array::Float32Array:
- forNode(child1).filter(SpecFloat32Array);
forNode(child2).filter(SpecInt32);
forNode(child3).filter(SpecNumber);
break;
case Array::Float64Array:
- forNode(child1).filter(SpecFloat64Array);
forNode(child2).filter(SpecInt32);
forNode(child3).filter(SpecNumber);
break;
@@ -1057,13 +992,11 @@ bool AbstractState::execute(unsigned indexInBlock)
case ArrayPush:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).set(SpecNumber);
break;
case ArrayPop:
node.setCanExit(true);
- forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
@@ -1102,14 +1035,9 @@ bool AbstractState::execute(unsigned indexInBlock)
Node& child = m_graph[node.child1()];
if (child.shouldSpeculateBoolean())
speculateBooleanUnary(node);
- else if (child.shouldSpeculateFinalObjectOrOther()) {
- node.setCanExit(
- !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecFinalObject | SpecOther);
- } else if (child.shouldSpeculateArrayOrOther()) {
- node.setCanExit(
- !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecArray | SpecOther);
+ else if (child.shouldSpeculateNonStringCellOrOther()) {
+ node.setCanExit(true);
+ forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
@@ -1235,7 +1163,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case CreateActivation:
node.setCanExit(false);
- forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get());
+ forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->activationStructure());
m_haveStructures = true;
break;
@@ -1347,80 +1275,8 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case GetArrayLength:
- switch (node.arrayMode()) {
- case Array::Undecided:
- ASSERT_NOT_REACHED();
- break;
- case Array::ForceExit:
- m_isValid = false;
- break;
- case Array::Generic:
- ASSERT_NOT_REACHED();
- break;
- case Array::String:
- node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecString);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::JSArray:
- node.setCanExit(true);
- forNode(node.child1()).filter(SpecCell);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::JSArrayOutOfBounds:
- ASSERT_NOT_REACHED();
- break;
- case Array::Arguments:
- node.setCanExit(true);
- forNode(node.child1()).filter(SpecArguments);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Int8Array:
- node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecInt8Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Int16Array:
- node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecInt16Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Int32Array:
- node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecInt32Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Uint8Array:
- node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecUint8Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Uint8ClampedArray:
- node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecUint8ClampedArray);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Uint16Array:
- node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecUint16Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Uint32Array:
- node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecUint32Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Float32Array:
- node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecFloat32Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Float64Array:
- node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(SpecFloat64Array);
- forNode(nodeIndex).set(SpecInt32);
- break;
- }
+ node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
+ forNode(nodeIndex).set(SpecInt32);
break;
case CheckStructure:
@@ -1492,8 +1348,13 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).clear(); // The result is not a JS value.
break;
- case GetIndexedPropertyStorage: {
- node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
+ case CheckArray: {
+ if (modeAlreadyChecked(forNode(node.child1()), node.arrayMode())) {
+ m_foundConstants = true;
+ node.setCanExit(false);
+ break;
+ }
+ node.setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
switch (node.arrayMode()) {
case Array::String:
forNode(node.child1()).filter(SpecString);
@@ -1504,6 +1365,9 @@ bool AbstractState::execute(unsigned indexInBlock)
// CFA tracking of array mode speculations, but we don't have that, yet.
forNode(node.child1()).filter(SpecCell);
break;
+ case Array::Arguments:
+ forNode(node.child1()).filter(SpecArguments);
+ break;
case Array::Int8Array:
forNode(node.child1()).filter(SpecInt8Array);
break;
@@ -1535,6 +1399,19 @@ bool AbstractState::execute(unsigned indexInBlock)
ASSERT_NOT_REACHED();
break;
}
+ break;
+ }
+ case GetIndexedPropertyStorage: {
+ switch (node.arrayMode()) {
+ case Array::String:
+ // Strings are weird - we may spec fail if the string was a rope. That is of course
+ // stupid, and we should fix that, but for now let's at least be honest about it.
+ node.setCanExit(true);
+ break;
+ default:
+ node.setCanExit(false);
+ break;
+ }
forNode(nodeIndex).clear();
break;
}