summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp614
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.h32
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractValue.h74
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentPosition.h15
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp123
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h15
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp319
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h28
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp61
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp225
-rw-r--r--Source/JavaScriptCore/dfg/DFGCapabilities.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGCommon.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp48
-rw-r--r--Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h5
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGFixupPhase.cpp25
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.cpp27
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h26
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.cpp34
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.h12
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h111
-rw-r--r--Source/JavaScriptCore/dfg/DFGNodeType.h14
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExit.cpp1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExit.h1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp10
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp148
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp115
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp58
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h152
-rw-r--r--Source/JavaScriptCore/dfg/DFGPhase.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGPhase.h11
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp187
-rw-r--r--Source/JavaScriptCore/dfg/DFGRepatch.cpp33
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp190
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h69
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp328
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp313
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGVariableAccessData.h36
40 files changed, 2175 insertions, 1303 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index a0849acea..94e96853d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -99,31 +99,31 @@ void AbstractState::initialize(Graph& graph)
continue;
}
- PredictedType prediction = node.variableAccessData()->prediction();
- if (isInt32Prediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt32);
- else if (isArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictArray);
- else if (isBooleanPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictBoolean);
- else if (isInt8ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt8Array);
- else if (isInt16ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt16Array);
- else if (isInt32ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictInt32Array);
- else if (isUint8ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictUint8Array);
- else if (isUint8ClampedArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictUint8ClampedArray);
- else if (isUint16ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictUint16Array);
- else if (isUint32ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictUint32Array);
- else if (isFloat32ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictFloat32Array);
- else if (isFloat64ArrayPrediction(prediction))
- root->valuesAtHead.argument(i).set(PredictFloat64Array);
+ 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))
+ 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
root->valuesAtHead.argument(i).makeTop();
@@ -219,7 +219,9 @@ bool AbstractState::execute(unsigned indexInBlock)
{
ASSERT(m_block);
ASSERT(m_isValid);
-
+
+ m_didClobber = false;
+
NodeIndex nodeIndex = m_block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
@@ -237,24 +239,29 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
+ if (variableAccessData->prediction() == SpecNone) {
+ m_isValid = false;
+ node.setCanExit(true);
+ break;
+ }
bool canExit = false;
- canExit |= variableAccessData->prediction() == PredictNone;
- if (variableAccessData->isCaptured())
- forNode(nodeIndex) = m_variables.operand(variableAccessData->local());
- else {
- AbstractValue value = m_variables.operand(variableAccessData->local());
+ AbstractValue value = m_variables.operand(variableAccessData->local());
+ if (!variableAccessData->isCaptured()) {
if (value.isClear())
canExit |= true;
- if (value.value())
- m_foundConstants = true;
- forNode(nodeIndex) = value;
}
+ if (value.value())
+ m_foundConstants = true;
+ forNode(nodeIndex) = value;
node.setCanExit(canExit);
break;
}
case GetLocalUnlinked: {
- forNode(nodeIndex) = m_variables.operand(node.unlinkedLocal());
+ AbstractValue value = m_variables.operand(node.unlinkedLocal());
+ if (value.value())
+ m_foundConstants = true;
+ forNode(nodeIndex) = value;
node.setCanExit(false);
break;
}
@@ -268,17 +275,17 @@ bool AbstractState::execute(unsigned indexInBlock)
if (node.variableAccessData()->shouldUseDoubleFormat()) {
speculateNumberUnary(node);
- m_variables.operand(node.local()).set(PredictDouble);
+ m_variables.operand(node.local()).set(SpecDouble);
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
- if (isInt32Prediction(predictedType))
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ if (isInt32Speculation(predictedType))
speculateInt32Unary(node);
- else if (isArrayPrediction(predictedType)) {
- node.setCanExit(!isArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray);
- } else if (isBooleanPrediction(predictedType))
+ else if (isArraySpeculation(predictedType)) {
+ node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ } else if (isBooleanSpeculation(predictedType))
speculateBooleanUnary(node);
else
node.setCanExit(false);
@@ -331,7 +338,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateInt32Binary(node);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -345,10 +352,10 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
if (!node.canSpeculateInteger()) {
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
node.setCanExit(false);
} else {
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
node.setCanExit(true);
}
break;
@@ -367,8 +374,8 @@ bool AbstractState::execute(unsigned indexInBlock)
}
}
node.setCanExit(true);
- forNode(node.child1()).filter(PredictNumber);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecNumber);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -392,7 +399,7 @@ bool AbstractState::execute(unsigned indexInBlock)
else
node.setCanExit(false);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
@@ -405,12 +412,12 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
case CheckNumber:
- forNode(node.child1()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecNumber);
break;
case ValueAdd:
@@ -426,17 +433,17 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.addShouldSpeculateInteger(node)) {
speculateInt32Binary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (node.op() == ValueAdd) {
clobberWorld(node.codeOrigin, indexInBlock);
- forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber);
+ forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
node.setCanExit(false);
break;
}
@@ -458,11 +465,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.addShouldSpeculateInteger(node)) {
speculateInt32Binary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -477,11 +484,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph.negateShouldSpeculateInteger(node)) {
speculateInt32Unary(
node, !nodeCanTruncateInteger(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -499,11 +506,11 @@ bool AbstractState::execute(unsigned indexInBlock)
node,
!nodeCanTruncateInteger(node.arithNodeFlags())
|| !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -541,11 +548,11 @@ bool AbstractState::execute(unsigned indexInBlock)
m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger()) {
speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberBinary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -560,11 +567,11 @@ bool AbstractState::execute(unsigned indexInBlock)
if (m_graph[node.child1()].shouldSpeculateInteger()
&& node.canSpeculateInteger()) {
speculateInt32Unary(node, true);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -577,7 +584,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -585,27 +592,28 @@ bool AbstractState::execute(unsigned indexInBlock)
JSValue childConst = forNode(node.child1()).value();
if (childConst) {
forNode(nodeIndex).set(jsBoolean(!childConst.toBoolean()));
+ m_foundConstants = true;
node.setCanExit(false);
break;
}
Node& child = m_graph[node.child1()];
- if (isBooleanPrediction(child.prediction()))
+ if (isBooleanSpeculation(child.prediction()))
speculateBooleanUnary(node);
else if (child.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
} else if (child.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
speculateNumberUnary(node);
else
node.setCanExit(false);
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
break;
}
@@ -643,7 +651,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
break;
}
@@ -682,18 +690,18 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
Node& left = m_graph[node.child1()];
Node& right = m_graph[node.child2()];
- PredictedType filter;
- PredictionChecker checker;
+ SpeculatedType filter;
+ SpeculatedTypeChecker checker;
if (Node::shouldSpeculateInteger(left, right)) {
- filter = PredictInt32;
- checker = isInt32Prediction;
+ filter = SpecInt32;
+ checker = isInt32Speculation;
} else if (Node::shouldSpeculateNumber(left, right)) {
- filter = PredictNumber;
- checker = isNumberPrediction;
+ filter = SpecNumber;
+ checker = isNumberSpeculation;
} else if (node.op() == CompareEq) {
if ((m_graph.isConstant(node.child1().index())
&& m_graph.valueOfJSConstant(node.child1().index()).isNull())
@@ -705,47 +713,47 @@ bool AbstractState::execute(unsigned indexInBlock)
}
if (Node::shouldSpeculateFinalObject(left, right)) {
- filter = PredictFinalObject;
- checker = isFinalObjectPrediction;
+ filter = SpecFinalObject;
+ checker = isFinalObjectSpeculation;
} else if (Node::shouldSpeculateArray(left, right)) {
- filter = PredictArray;
- checker = isArrayPrediction;
+ filter = SpecArray;
+ checker = isArraySpeculation;
} else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectOrOtherPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject);
- forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectOrOtherSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject);
+ forNode(node.child2()).filter(SpecFinalObject | SpecOther);
break;
} else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
- forNode(node.child2()).filter(PredictFinalObject);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
+ forNode(node.child2()).filter(SpecFinalObject);
break;
} else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayPrediction(forNode(node.child1()).m_type)
- || !isArrayOrOtherPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictArray | PredictOther);
+ !isArraySpeculation(forNode(node.child1()).m_type)
+ || !isArrayOrOtherSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecArray | SpecOther);
break;
} else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type)
- || !isArrayPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
- forNode(node.child2()).filter(PredictArray);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type)
+ || !isArraySpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
+ forNode(node.child2()).filter(SpecArray);
break;
} else {
- filter = PredictTop;
- checker = isAnyPrediction;
+ filter = SpecTop;
+ checker = isAnySpeculation;
clobberWorld(node.codeOrigin, indexInBlock);
}
} else {
- filter = PredictTop;
- checker = isAnyPrediction;
+ filter = SpecTop;
+ checker = isAnySpeculation;
clobberWorld(node.codeOrigin, indexInBlock);
}
node.setCanExit(
@@ -765,7 +773,7 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
- forNode(nodeIndex).set(PredictBoolean);
+ forNode(nodeIndex).set(SpecBoolean);
if (m_graph.isJSConstant(node.child1().index())) {
JSValue value = m_graph.valueOfJSConstant(node.child1().index());
if (!value.isNumber() && !value.isString()) {
@@ -793,19 +801,19 @@ bool AbstractState::execute(unsigned indexInBlock)
if (Node::shouldSpeculateFinalObject(
m_graph[node.child1()], m_graph[node.child2()])) {
node.setCanExit(
- !isFinalObjectPrediction(forNode(node.child1()).m_type)
- || !isFinalObjectPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictFinalObject);
- forNode(node.child2()).filter(PredictFinalObject);
+ !isFinalObjectSpeculation(forNode(node.child1()).m_type)
+ || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject);
+ forNode(node.child2()).filter(SpecFinalObject);
break;
}
if (Node::shouldSpeculateArray(
m_graph[node.child1()], m_graph[node.child2()])) {
node.setCanExit(
- !isArrayPrediction(forNode(node.child1()).m_type)
- || !isArrayPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictArray);
+ !isArraySpeculation(forNode(node.child1()).m_type)
+ || !isArraySpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecArray);
break;
}
node.setCanExit(false);
@@ -814,16 +822,16 @@ bool AbstractState::execute(unsigned indexInBlock)
case StringCharCodeAt:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
case StringCharAt:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictString);
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecString);
break;
case GetByVal: {
@@ -832,84 +840,84 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
}
if (m_graph[node.child1()].shouldSpeculateArguments()) {
- forNode(node.child1()).filter(PredictArguments);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
}
- if (m_graph[node.child1()].prediction() == PredictString) {
- forNode(node.child1()).filter(PredictString);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictString);
+ if (m_graph[node.child1()].prediction() == SpecString) {
+ forNode(node.child1()).filter(SpecString);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecString);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (node.shouldSpeculateInteger())
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
else
- forNode(nodeIndex).set(PredictDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(nodeIndex).set(PredictDouble);
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
}
@@ -921,7 +929,7 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[node.child1()].prediction())
#if USE(JSVALUE32_64)
|| m_graph[node.child1()].shouldSpeculateArguments()
#endif
@@ -933,110 +941,112 @@ bool AbstractState::execute(unsigned indexInBlock)
}
if (m_graph[node.child1()].shouldSpeculateArguments()) {
- forNode(node.child1()).filter(PredictArguments);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(node.child2()).filter(SpecInt32);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(node.child2()).filter(SpecInt32);
if (m_graph[node.child3()].shouldSpeculateInteger())
- forNode(node.child3()).filter(PredictInt32);
+ forNode(node.child3()).filter(SpecInt32);
else
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(node.child2()).filter(PredictInt32);
- forNode(node.child3()).filter(PredictNumber);
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(node.child2()).filter(SpecInt32);
+ forNode(node.child3()).filter(SpecNumber);
break;
}
ASSERT(m_graph[node.child1()].shouldSpeculateArray());
- forNode(node.child1()).filter(PredictArray);
- forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(node.child2()).filter(SpecInt32);
+ if (node.op() == PutByVal)
+ clobberWorld(node.codeOrigin, indexInBlock);
break;
}
case ArrayPush:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
- forNode(nodeIndex).set(PredictNumber);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(nodeIndex).set(SpecNumber);
break;
case ArrayPop:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
+ forNode(node.child1()).filter(SpecArray);
forNode(nodeIndex).makeTop();
break;
case RegExpExec:
case RegExpTest:
node.setCanExit(
- !isCellPrediction(forNode(node.child1()).m_type)
- || !isCellPrediction(forNode(node.child2()).m_type));
- forNode(node.child1()).filter(PredictCell);
- forNode(node.child2()).filter(PredictCell);
+ !isCellSpeculation(forNode(node.child1()).m_type)
+ || !isCellSpeculation(forNode(node.child2()).m_type));
+ forNode(node.child1()).filter(SpecCell);
+ forNode(node.child2()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
@@ -1067,12 +1077,12 @@ bool AbstractState::execute(unsigned indexInBlock)
speculateBooleanUnary(node);
else if (child.shouldSpeculateFinalObjectOrOther()) {
node.setCanExit(
- !isFinalObjectOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+ !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFinalObject | SpecOther);
} else if (child.shouldSpeculateArrayOrOther()) {
node.setCanExit(
- !isArrayOrOtherPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictArray | PredictOther);
+ !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecArray | SpecOther);
} else if (child.shouldSpeculateInteger())
speculateInt32Unary(node);
else if (child.shouldSpeculateNumber())
@@ -1106,17 +1116,17 @@ bool AbstractState::execute(unsigned indexInBlock)
Node& child = m_graph[node.child1()];
if (child.shouldSpeculateInteger()) {
speculateInt32Unary(node);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
break;
}
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- PredictedType type = source.m_type;
- if (type & ~(PredictNumber | PredictString | PredictBoolean)) {
- type &= (PredictNumber | PredictString | PredictBoolean);
- type |= PredictString;
+ SpeculatedType type = source.m_type;
+ if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
+ type &= (SpecNumber | SpecString | SpecBoolean);
+ type |= SpecString;
}
destination.set(type);
node.setCanExit(false);
@@ -1125,7 +1135,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case StrCat:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictString);
+ forNode(nodeIndex).set(SpecString);
break;
case NewArray:
@@ -1146,7 +1156,7 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- if (isObjectPrediction(source.m_type)) {
+ if (isObjectSpeculation(source.m_type)) {
// This is the simple case. We already know that the source is an
// object, so there's nothing to do. I don't think this case will
// be hit, but then again, you never know.
@@ -1157,20 +1167,20 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(true);
- if (isOtherPrediction(child.prediction())) {
- source.filter(PredictOther);
- destination.set(PredictObjectOther);
+ if (isOtherSpeculation(child.prediction())) {
+ source.filter(SpecOther);
+ destination.set(SpecObjectOther);
break;
}
- if (isObjectPrediction(child.prediction())) {
- source.filter(PredictObjectMask);
+ if (isObjectSpeculation(child.prediction())) {
+ source.filter(SpecObjectMask);
destination = source;
break;
}
destination = source;
- destination.merge(PredictObjectOther);
+ destination.merge(SpecObjectOther);
break;
}
@@ -1178,10 +1188,10 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- node.setCanExit(!isCellPrediction(source.m_type));
+ node.setCanExit(!isCellSpeculation(source.m_type));
- source.filter(PredictFunction);
- destination.set(PredictFinalObject);
+ source.filter(SpecFunction);
+ destination.set(SpecFinalObject);
break;
}
@@ -1210,10 +1220,13 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case CheckArgumentsNotCreated:
- node.setCanExit(
- !isEmptyPrediction(
+ if (isEmptySpeculation(
m_variables.operand(
- m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
+ m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
+ node.setCanExit(false);
+ m_foundConstants = true;
+ } else
+ node.setCanExit(true);
break;
case GetMyArgumentsLength:
@@ -1224,9 +1237,9 @@ bool AbstractState::execute(unsigned indexInBlock)
if (node.codeOrigin.inlineCallFrame)
forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
else
- forNode(nodeIndex).set(PredictInt32);
+ forNode(nodeIndex).set(SpecInt32);
node.setCanExit(
- !isEmptyPrediction(
+ !isEmptySpeculation(
m_variables.operand(
m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
break;
@@ -1246,7 +1259,7 @@ bool AbstractState::execute(unsigned indexInBlock)
// We know that this executable does not escape its arguments, so we can optimize
// the arguments a bit. Note that this ends up being further optimized by the
// ArgumentsSimplificationPhase.
- forNode(node.child1()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
@@ -1256,7 +1269,7 @@ bool AbstractState::execute(unsigned indexInBlock)
// a getter. We don't speculate against this.
clobberWorld(node.codeOrigin, indexInBlock);
// But we do speculate that the index is an integer.
- forNode(node.child1()).filter(PredictInt32);
+ forNode(node.child1()).filter(SpecInt32);
// And the result is unknown.
forNode(nodeIndex).makeTop();
break;
@@ -1270,12 +1283,12 @@ bool AbstractState::execute(unsigned indexInBlock)
case GetCallee:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictFunction);
+ forNode(nodeIndex).set(SpecFunction);
break;
case GetScopeChain:
node.setCanExit(false);
- forNode(nodeIndex).set(PredictCellOther);
+ forNode(nodeIndex).set(SpecCellOther);
break;
case GetScopedVar:
@@ -1295,74 +1308,74 @@ bool AbstractState::execute(unsigned indexInBlock)
m_isValid = false;
break;
}
- if (isCellPrediction(m_graph[node.child1()].prediction()))
- forNode(node.child1()).filter(PredictCell);
+ if (isCellSpeculation(m_graph[node.child1()].prediction()))
+ forNode(node.child1()).filter(SpecCell);
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
break;
case GetArrayLength:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArray);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecArray);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetArgumentsLength:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictArguments);
- forNode(nodeIndex).set(PredictInt32);
+ forNode(node.child1()).filter(SpecArguments);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetStringLength:
- node.setCanExit(!isStringPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictString);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecString);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt8ArrayLength:
- node.setCanExit(!isInt8ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt8Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt8Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt16ArrayLength:
- node.setCanExit(!isInt16ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt16Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt16Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetInt32ArrayLength:
- node.setCanExit(!isInt32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictInt32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecInt32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint8ArrayLength:
- node.setCanExit(!isUint8ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint8Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint8Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint8ClampedArrayLength:
- node.setCanExit(!isUint8ClampedArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint8ClampedArray);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint16ArrayLength:
- node.setCanExit(!isUint16ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetUint32ArrayLength:
- node.setCanExit(!isUint32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictUint32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecUint32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetFloat32ArrayLength:
- node.setCanExit(!isFloat32ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFloat32Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFloat32Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case GetFloat64ArrayLength:
- node.setCanExit(!isFloat64ArrayPrediction(forNode(node.child1()).m_type));
- forNode(node.child1()).filter(PredictFloat64Array);
- forNode(nodeIndex).set(PredictInt32);
+ node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
+ forNode(node.child1()).filter(SpecFloat64Array);
+ forNode(nodeIndex).set(SpecInt32);
break;
case CheckStructure: {
@@ -1370,11 +1383,20 @@ bool AbstractState::execute(unsigned indexInBlock)
AbstractValue& value = forNode(node.child1());
node.setCanExit(
!value.m_structure.isSubsetOf(node.structureSet())
- || !isCellPrediction(value.m_type));
+ || !isCellSpeculation(value.m_type));
value.filter(node.structureSet());
m_haveStructures = true;
break;
}
+
+ case StructureTransitionWatchpoint: {
+ // FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
+ AbstractValue& value = forNode(node.child1());
+ ASSERT(isCellSpeculation(value.m_type));
+ value.filter(node.structure());
+ node.setCanExit(true);
+ break;
+ }
case PutStructure:
case PhantomPutStructure:
@@ -1385,13 +1407,13 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case GetPropertyStorage:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ 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.
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- if (!(basePrediction & PredictInt32) && basePrediction) {
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ if (!(basePrediction & SpecInt32) && basePrediction) {
forNode(nodeIndex).clear();
break;
}
@@ -1399,82 +1421,82 @@ bool AbstractState::execute(unsigned indexInBlock)
ASSERT_NOT_REACHED();
break;
}
- if (m_graph[node.child1()].prediction() == PredictString) {
- forNode(node.child1()).filter(PredictString);
+ if (m_graph[node.child1()].prediction() == SpecString) {
+ forNode(node.child1()).filter(SpecString);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
- forNode(node.child1()).filter(PredictInt8Array);
+ forNode(node.child1()).filter(SpecInt8Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
- forNode(node.child1()).filter(PredictInt16Array);
+ forNode(node.child1()).filter(SpecInt16Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
- forNode(node.child1()).filter(PredictInt32Array);
+ forNode(node.child1()).filter(SpecInt32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
- forNode(node.child1()).filter(PredictUint8Array);
+ forNode(node.child1()).filter(SpecUint8Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
- forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(node.child1()).filter(SpecUint8ClampedArray);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
- forNode(node.child1()).filter(PredictUint16Array);
- forNode(nodeIndex).set(PredictOther);
+ forNode(node.child1()).filter(SpecUint16Array);
+ forNode(nodeIndex).set(SpecOther);
break;
}
if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
- forNode(node.child1()).filter(PredictUint32Array);
+ forNode(node.child1()).filter(SpecUint32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
- forNode(node.child1()).filter(PredictFloat32Array);
+ forNode(node.child1()).filter(SpecFloat32Array);
forNode(nodeIndex).clear();
break;
}
if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
- forNode(node.child1()).filter(PredictFloat64Array);
+ forNode(node.child1()).filter(SpecFloat64Array);
forNode(nodeIndex).clear();
break;
}
- forNode(node.child1()).filter(PredictArray);
+ forNode(node.child1()).filter(SpecArray);
forNode(nodeIndex).clear();
break;
}
case GetByOffset:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
forNode(nodeIndex).makeTop();
break;
case PutByOffset:
node.setCanExit(false);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
break;
case CheckFunction:
node.setCanExit(true); // Lies! We can do better.
- forNode(node.child1()).filter(PredictFunction);
+ forNode(node.child1()).filter(SpecFunction);
// FIXME: Should be able to propagate the fact that we know what the function is.
break;
-
+
case PutById:
case PutByIdDirect:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
clobberWorld(node.codeOrigin, indexInBlock);
break;
@@ -1482,24 +1504,29 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
forNode(nodeIndex).makeTop();
break;
+
+ case GlobalVarWatchpoint:
+ node.setCanExit(true);
+ break;
case PutGlobalVar:
+ case PutGlobalVarCheck:
node.setCanExit(false);
break;
case CheckHasInstance:
node.setCanExit(true);
- forNode(node.child1()).filter(PredictCell);
+ forNode(node.child1()).filter(SpecCell);
// Sadly, we don't propagate the fact that we've done CheckHasInstance
break;
case InstanceOf:
node.setCanExit(true);
// Again, sadly, we don't propagate the fact that we've done InstanceOf
- if (!(m_graph[node.child1()].prediction() & ~PredictCell) && !(forNode(node.child1()).m_type & ~PredictCell))
- forNode(node.child1()).filter(PredictCell);
- forNode(node.child3()).filter(PredictCell);
- forNode(nodeIndex).set(PredictBoolean);
+ if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
+ forNode(node.child1()).filter(SpecCell);
+ forNode(node.child3()).filter(SpecCell);
+ forNode(nodeIndex).set(SpecBoolean);
break;
case Phi:
@@ -1572,6 +1599,7 @@ inline void AbstractState::clobberStructures(unsigned indexInBlock)
for (size_t i = m_variables.numberOfLocals(); i--;)
m_variables.local(i).clobberStructures();
m_haveStructures = false;
+ m_didClobber = true;
}
inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
@@ -1625,7 +1653,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract
// before and after setting it.
if (node.variableAccessData()->shouldUseDoubleFormat()) {
// FIXME: This unnecessarily loses precision.
- source.set(PredictDouble);
+ source.set(SpecDouble);
} else
source = forNode(node.child1());
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index 4b0a248f3..9bb74cd86 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -193,6 +193,9 @@ public:
// of Throw.
bool execute(unsigned);
+ // Did the last executed node clobber the world?
+ bool didClobber() const { return m_didClobber; }
+
// Is the execution state still valid? This will be false if execute() has
// returned false previously.
bool isValid() const { return m_isValid; }
@@ -223,22 +226,22 @@ private:
void speculateInt32Unary(Node& node, bool forceCanExit = false)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(forceCanExit || !isInt32Prediction(childValue.m_type));
- childValue.filter(PredictInt32);
+ node.setCanExit(forceCanExit || !isInt32Speculation(childValue.m_type));
+ childValue.filter(SpecInt32);
}
void speculateNumberUnary(Node& node)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isNumberPrediction(childValue.m_type));
- childValue.filter(PredictNumber);
+ node.setCanExit(!isNumberSpeculation(childValue.m_type));
+ childValue.filter(SpecNumber);
}
void speculateBooleanUnary(Node& node)
{
AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isBooleanPrediction(childValue.m_type));
- childValue.filter(PredictBoolean);
+ node.setCanExit(!isBooleanSpeculation(childValue.m_type));
+ childValue.filter(SpecBoolean);
}
void speculateInt32Binary(Node& node, bool forceCanExit = false)
@@ -247,10 +250,10 @@ private:
AbstractValue& childValue2 = forNode(node.child2());
node.setCanExit(
forceCanExit
- || !isInt32Prediction(childValue1.m_type)
- || !isInt32Prediction(childValue2.m_type));
- childValue1.filter(PredictInt32);
- childValue2.filter(PredictInt32);
+ || !isInt32Speculation(childValue1.m_type)
+ || !isInt32Speculation(childValue2.m_type));
+ childValue1.filter(SpecInt32);
+ childValue2.filter(SpecInt32);
}
void speculateNumberBinary(Node& node)
@@ -258,10 +261,10 @@ private:
AbstractValue& childValue1 = forNode(node.child1());
AbstractValue& childValue2 = forNode(node.child2());
node.setCanExit(
- !isNumberPrediction(childValue1.m_type)
- || !isNumberPrediction(childValue2.m_type));
- childValue1.filter(PredictNumber);
- childValue2.filter(PredictNumber);
+ !isNumberSpeculation(childValue1.m_type)
+ || !isNumberSpeculation(childValue2.m_type));
+ childValue1.filter(SpecNumber);
+ childValue2.filter(SpecNumber);
}
CodeBlock* m_codeBlock;
@@ -274,6 +277,7 @@ private:
bool m_foundConstants;
bool m_isValid;
+ bool m_didClobber;
BranchDirection m_branchDirection; // This is only set for blocks that end in Branch and that execute to completion (i.e. m_isValid == true).
};
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
index c61a383eb..f81af4ecf 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
@@ -31,7 +31,7 @@
#if ENABLE(DFG_JIT)
#include "JSCell.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "StructureSet.h"
namespace JSC { namespace DFG {
@@ -225,9 +225,9 @@ public:
m_structure = 0;
}
- void filter(PredictedType other)
+ void filter(SpeculatedType other)
{
- if (!(other & PredictCell)) {
+ if (!(other & SpecCell)) {
clear();
return;
}
@@ -235,7 +235,7 @@ public:
if (isClearOrTop())
return;
- if (!(predictionFromStructure(m_structure) & other))
+ if (!(speculationFromStructure(m_structure) & other))
m_structure = 0;
}
@@ -273,13 +273,13 @@ public:
return at(0);
}
- PredictedType predictionFromStructures() const
+ SpeculatedType speculationFromStructures() const
{
if (isTop())
- return PredictCell;
+ return SpecCell;
if (isClear())
- return PredictNone;
- return predictionFromStructure(m_structure);
+ return SpecNone;
+ return speculationFromStructure(m_structure);
}
bool operator==(const StructureAbstractValue& other) const
@@ -309,13 +309,13 @@ private:
struct AbstractValue {
AbstractValue()
- : m_type(PredictNone)
+ : m_type(SpecNone)
{
}
void clear()
{
- m_type = PredictNone;
+ m_type = SpecNone;
m_structure.clear();
m_value = JSValue();
checkConsistency();
@@ -323,7 +323,7 @@ struct AbstractValue {
bool isClear() const
{
- bool result = m_type == PredictNone && m_structure.isClear();
+ bool result = m_type == SpecNone && m_structure.isClear();
if (result)
ASSERT(!m_value);
return result;
@@ -331,7 +331,7 @@ struct AbstractValue {
void makeTop()
{
- m_type = PredictTop;
+ m_type = SpecTop;
m_structure.makeTop();
m_value = JSValue();
checkConsistency();
@@ -339,7 +339,7 @@ struct AbstractValue {
void clobberStructures()
{
- if (m_type & PredictCell)
+ if (m_type & SpecCell)
m_structure.makeTop();
else
ASSERT(m_structure.isClear());
@@ -353,7 +353,7 @@ struct AbstractValue {
bool isTop() const
{
- return m_type == PredictTop && m_structure.isTop();
+ return m_type == SpecTop && m_structure.isTop();
}
bool valueIsTop() const
@@ -386,7 +386,7 @@ struct AbstractValue {
} else
m_structure.clear();
- m_type = predictionFromValue(value);
+ m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
@@ -397,15 +397,15 @@ struct AbstractValue {
m_structure.clear();
m_structure.add(structure);
- m_type = predictionFromStructure(structure);
+ m_type = speculationFromStructure(structure);
m_value = JSValue();
checkConsistency();
}
- void set(PredictedType type)
+ void set(SpeculatedType type)
{
- if (type & PredictCell)
+ if (type & SpecCell)
m_structure.makeTop();
else
m_structure.clear();
@@ -435,7 +435,7 @@ struct AbstractValue {
*this = other;
result = !other.isClear();
} else {
- result |= mergePrediction(m_type, other.m_type);
+ result |= mergeSpeculation(m_type, other.m_type);
result |= m_structure.addAll(other.m_structure);
if (m_value != other.m_value) {
result |= !!m_value;
@@ -447,11 +447,11 @@ struct AbstractValue {
return result;
}
- void merge(PredictedType type)
+ void merge(SpeculatedType type)
{
- mergePrediction(m_type, type);
+ mergeSpeculation(m_type, type);
- if (type & PredictCell)
+ if (type & SpecCell)
m_structure.makeTop();
m_value = JSValue();
@@ -460,13 +460,13 @@ struct AbstractValue {
void filter(const StructureSet& other)
{
- m_type &= other.predictionFromStructures();
+ m_type &= other.speculationFromStructures();
m_structure.filter(other);
// It's possible that prior to the above two statements we had (Foo, TOP), where
- // Foo is a PredictedType that is disjoint with the passed StructureSet. In that
+ // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
// case, we will now have (None, [someStructure]). In general, we need to make
- // sure that new information gleaned from the PredictedType needs to be fed back
+ // sure that new information gleaned from the SpeculatedType needs to be fed back
// into the information gleaned from the StructureSet.
m_structure.filter(m_type);
@@ -476,9 +476,9 @@ struct AbstractValue {
checkConsistency();
}
- void filter(PredictedType type)
+ void filter(SpeculatedType type)
{
- if (type == PredictTop)
+ if (type == SpecTop)
return;
m_type &= type;
@@ -499,11 +499,11 @@ struct AbstractValue {
if (isTop())
return true;
- if (mergePredictions(m_type, predictionFromValue(value)) != m_type)
+ if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
return false;
if (value.isEmpty()) {
- ASSERT(m_type & PredictEmpty);
+ ASSERT(m_type & SpecEmpty);
return true;
}
@@ -511,7 +511,7 @@ struct AbstractValue {
return true;
if (!!value && value.isCell()) {
- ASSERT(m_type & PredictCell);
+ ASSERT(m_type & SpecCell);
return m_structure.contains(value.asCell()->structure());
}
@@ -526,11 +526,11 @@ struct AbstractValue {
if (!!m_value)
return m_value == value;
- if (mergePredictions(m_type, predictionFromValue(value)) != m_type)
+ if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
return false;
if (value.isEmpty()) {
- ASSERT(m_type & PredictEmpty);
+ ASSERT(m_type & SpecEmpty);
return true;
}
@@ -538,7 +538,7 @@ struct AbstractValue {
return true;
if (!!value && value.isCell()) {
- ASSERT(m_type & PredictCell);
+ ASSERT(m_type & SpecCell);
return m_structure.contains(value.asCell()->structure());
}
@@ -547,14 +547,14 @@ struct AbstractValue {
void checkConsistency() const
{
- if (!(m_type & PredictCell))
+ if (!(m_type & SpecCell))
ASSERT(m_structure.isClear());
if (isClear())
ASSERT(!m_value);
if (!!m_value)
- ASSERT(mergePredictions(m_type, predictionFromValue(m_value)) == m_type);
+ ASSERT(mergeSpeculations(m_type, speculationFromValue(m_value)) == m_type);
// Note that it's possible for a prediction like (Final, []). This really means that
// the value is bottom and that any code that uses the value is unreachable. But
@@ -564,7 +564,7 @@ struct AbstractValue {
void dump(FILE* out) const
{
- fprintf(out, "(%s, ", predictionToString(m_type));
+ fprintf(out, "(%s, ", speculationToString(m_type));
m_structure.dump(out);
if (!!m_value)
fprintf(out, ", %s", m_value.description());
@@ -572,7 +572,7 @@ struct AbstractValue {
}
StructureAbstractValue m_structure;
- PredictedType m_type;
+ SpeculatedType m_type;
JSValue m_value;
};
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentPosition.h b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
index ed447ff91..05d1cb048 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
+++ b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
@@ -28,14 +28,14 @@
#include "DFGDoubleFormatState.h"
#include "DFGVariableAccessData.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
namespace JSC { namespace DFG {
class ArgumentPosition {
public:
ArgumentPosition()
- : m_prediction(PredictNone)
+ : m_prediction(SpecNone)
, m_doubleFormatState(EmptyDoubleFormatState)
{
}
@@ -49,7 +49,7 @@ public:
{
bool changed = false;
for (unsigned i = 0; i < m_variables.size(); ++i) {
- changed |= mergePrediction(m_prediction, m_variables[i]->argumentAwarePrediction());
+ changed |= mergeSpeculation(m_prediction, m_variables[i]->argumentAwarePrediction());
changed |= mergeDoubleFormatState(m_doubleFormatState, m_variables[i]->doubleFormatState());
}
if (!changed)
@@ -62,8 +62,15 @@ public:
return changed;
}
+ SpeculatedType prediction() const { return m_prediction; }
+ DoubleFormatState doubleFormatState() const { return m_doubleFormatState; }
+ bool shouldUseDoubleFormat() const
+ {
+ return doubleFormatState() == UsingDoubleFormat;
+ }
+
private:
- PredictedType m_prediction;
+ SpeculatedType m_prediction;
DoubleFormatState m_doubleFormatState;
Vector<VariableAccessData*, 2> m_variables;
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index 48163a91b..28e686aef 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -170,9 +170,17 @@ public:
break;
}
+ case TearOffArguments: {
+ // Ignore arguments tear off, because it's only relevant if we actually
+ // need to create the arguments.
+ break;
+ }
+
case SetLocal: {
Node& source = m_graph[node.child1()];
VariableAccessData* variableAccessData = node.variableAccessData();
+ int argumentsRegister =
+ m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
if (source.op() != CreateArguments) {
// Make sure that the source of the SetLocal knows that if it's
// a variable that we think is aliased to the arguments, then it
@@ -180,8 +188,28 @@ public:
// aliasing. But not yet.
observeBadArgumentsUse(node.child1());
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ // If this is an assignment to the arguments register, then
+ // pretend as if the arguments were created. We don't want to
+ // optimize code that explicitly assigns to the arguments,
+ // because that seems too ugly.
+
+ // But, before getting rid of CreateArguments, we will have
+ // an assignment to the arguments registers with JSValue().
+ // That's because CSE will refuse to get rid of the
+ // init_lazy_reg since it treats CreateArguments as reading
+ // local variables. That could be fixed, but it's easier to
+ // work around this here.
+ if (source.op() == JSConstant
+ && !source.valueOfJSConstant(codeBlock()))
+ break;
+
+ if (argumentsRegister != InvalidVirtualRegister
+ && (variableAccessData->local() == argumentsRegister
+ || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister)))
+ m_createsArguments.add(node.codeOrigin.inlineCallFrame);
break;
+ }
// Make sure that if it's a variable that we think is aliased to
// the arguments, that we know that it might actually not be.
@@ -191,11 +219,9 @@ public:
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
break;
}
- int argumentsRegister =
- m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
- if (variableAccessData->local() == argumentsRegister
- || variableAccessData->local() ==
- unmodifiedArgumentsRegister(argumentsRegister)) {
+ if (argumentsRegister != InvalidVirtualRegister
+ && (variableAccessData->local() == argumentsRegister
+ || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister))) {
if (node.codeOrigin.inlineCallFrame == source.codeOrigin.inlineCallFrame)
break;
m_createsArguments.add(source.codeOrigin.inlineCallFrame);
@@ -258,7 +284,7 @@ public:
break;
}
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction())
|| !m_graph[node.child2()].shouldSpeculateInteger()) {
observeBadArgumentsUses(node);
break;
@@ -398,10 +424,25 @@ public:
if (source.op() != CreateArguments)
break;
+ if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
+ break;
+
VariableAccessData* variableAccessData = node.variableAccessData();
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ ASSERT(m_graph.argumentsRegisterFor(node.codeOrigin) == variableAccessData->local()
+ || unmodifiedArgumentsRegister(m_graph.argumentsRegisterFor(node.codeOrigin)) == variableAccessData->local());
+ // The child of this store should really be the empty value.
+ Node emptyJSValue(JSConstant, node.codeOrigin, OpInfo(codeBlock()->addOrFindConstant(JSValue())));
+ emptyJSValue.ref();
+ NodeIndex emptyJSValueIndex = m_graph.size();
+ m_graph.deref(node.child1());
+ node.children.child1() = Edge(emptyJSValueIndex);
+ m_graph.append(emptyJSValue);
+ insertionSet.append(indexInBlock, emptyJSValueIndex);
+ changed = true;
break;
+ }
// If this is a store into a VariableAccessData* that is marked as
// arguments aliasing for an InlineCallFrame* that does not create
@@ -410,11 +451,8 @@ public:
// things. Note also that the SetLocal should become dead as soon as
// we replace all uses of this variable with GetMyArgumentsLength and
// GetMyArgumentByVal.
- if (m_argumentsAliasing.find(variableAccessData)->second.isValid()
- && !m_createsArguments.contains(source.codeOrigin.inlineCallFrame)) {
- changed |= variableAccessData->mergeIsArgumentsAlias(true);
- break;
- }
+ ASSERT(m_argumentsAliasing.find(variableAccessData)->second.isValid());
+ changed |= variableAccessData->mergeIsArgumentsAlias(true);
break;
}
@@ -439,7 +477,7 @@ public:
|| !m_graph[node.child2()].prediction())
break;
- if (!isActionableArrayPrediction(m_graph[node.child1()].prediction())
+ if (!isActionableArraySpeculation(m_graph[node.child1()].prediction())
|| !m_graph[node.child2()].shouldSpeculateInteger())
break;
@@ -487,19 +525,21 @@ public:
node.setOp(GetMyArgumentsLength);
changed = true;
}
- if (!node.codeOrigin.inlineCallFrame)
+
+ CodeOrigin codeOrigin = node.codeOrigin;
+ if (!codeOrigin.inlineCallFrame)
break;
// We know exactly what this will return. But only after we have checked
// that nobody has escaped our arguments.
- Node check(CheckArgumentsNotCreated, node.codeOrigin);
+ Node check(CheckArgumentsNotCreated, codeOrigin);
check.ref();
NodeIndex checkIndex = m_graph.size();
m_graph.append(check);
insertionSet.append(indexInBlock, checkIndex);
m_graph.convertToConstant(
- nodeIndex, jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
+ nodeIndex, jsNumber(codeOrigin.inlineCallFrame->arguments.size() - 1));
changed = true;
break;
}
@@ -559,6 +599,16 @@ public:
break;
}
+ case TearOffArguments: {
+ if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
+ continue;
+
+ node.setOpAndDefaultFlags(Nop);
+ m_graph.clearAndDerefChild1(node);
+ node.setRefCount(0);
+ break;
+ }
+
default:
break;
}
@@ -573,8 +623,6 @@ public:
for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
NodeIndex nodeIndex = block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
- if (!node.shouldGenerate())
- continue;
if (node.op() != CreateArguments)
continue;
// If this is a CreateArguments for an InlineCallFrame* that does
@@ -583,14 +631,16 @@ public:
// empty value) in DFG and arguments creation for OSR exit.
if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
continue;
- Node phantom(Phantom, node.codeOrigin);
- phantom.children = node.children;
- phantom.ref();
+ if (node.shouldGenerate()) {
+ Node phantom(Phantom, node.codeOrigin);
+ phantom.children = node.children;
+ phantom.ref();
+ NodeIndex phantomNodeIndex = m_graph.size();
+ m_graph.append(phantom);
+ insertionSet.append(indexInBlock, phantomNodeIndex);
+ }
node.setOpAndDefaultFlags(PhantomArguments);
node.children.reset();
- NodeIndex phantomNodeIndex = m_graph.size();
- m_graph.append(phantom);
- insertionSet.append(indexInBlock, phantomNodeIndex);
}
insertionSet.execute(*block);
}
@@ -622,7 +672,10 @@ private:
}
case GetLocal: {
- if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)) {
+ int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin);
+ if (argumentsRegister != InvalidVirtualRegister
+ && (child.local() == argumentsRegister
+ || child.local() == unmodifiedArgumentsRegister(argumentsRegister))) {
m_createsArguments.add(child.codeOrigin.inlineCallFrame);
break;
}
@@ -684,25 +737,31 @@ private:
bool isOKToOptimize(Node& source)
{
+ if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
+ return false;
+
switch (source.op()) {
case GetLocal: {
VariableAccessData* variableAccessData = source.variableAccessData();
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(source.codeOrigin);
+ if (argumentsRegister == InvalidVirtualRegister)
+ break;
+ if (argumentsRegister == variableAccessData->local())
+ return true;
+ if (unmodifiedArgumentsRegister(argumentsRegister) == variableAccessData->local())
+ return true;
break;
+ }
ArgumentsAliasingData& data =
m_argumentsAliasing.find(variableAccessData)->second;
if (!data.isValid())
break;
- if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
- break;
return true;
}
case CreateArguments: {
- if (m_createsArguments.contains(source.codeOrigin.inlineCallFrame))
- break;
-
return true;
}
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
index 9087eec57..f86c15e65 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
@@ -115,21 +115,6 @@ public:
#endif
}
- static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register));
- }
-
- static Address tagForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
- }
-
- static Address payloadForGlobalVar(GPRReg global, int32_t varNumber)
- {
- return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- }
-
static Address addressFor(VirtualRegister virtualRegister)
{
return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 358171029..317a08504 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -93,7 +93,10 @@ private:
// Handle setting the result of an intrinsic.
void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex);
// Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
- bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction);
+ bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
+ void handleGetById(
+ int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
+ const GetByIdStatus&);
// Prepare to parse a block.
void prepareToParseBlock();
// Parse a single basic block of bytecode instructions.
@@ -109,7 +112,7 @@ private:
template<PhiStackType stackType>
void processPhiStack();
- void fixVariableAccessPredictions();
+ void fixVariableAccessSpeculations();
// Add spill locations to nodes.
void allocateVirtualRegisters();
@@ -159,17 +162,17 @@ private:
setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
}
- NodeIndex injectLazyOperandPrediction(NodeIndex nodeIndex)
+ NodeIndex injectLazyOperandSpeculation(NodeIndex nodeIndex)
{
Node& node = m_graph[nodeIndex];
ASSERT(node.op() == GetLocal);
ASSERT(node.codeOrigin.bytecodeIndex == m_currentIndex);
- PredictedType prediction =
+ SpeculatedType prediction =
m_inlineStackTop->m_lazyOperands.prediction(
LazyOperandValueProfileKey(m_currentIndex, node.local()));
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("Lazy operand [@%u, bc#%u, r%d] prediction: %s\n",
- nodeIndex, m_currentIndex, node.local(), predictionToString(prediction));
+ nodeIndex, m_currentIndex, node.local(), speculationToString(prediction));
#endif
node.variableAccessData()->predict(prediction);
return nodeIndex;
@@ -192,7 +195,7 @@ private:
if (flushChild.op() == Phi) {
VariableAccessData* variableAccessData = flushChild.variableAccessData();
variableAccessData->mergeIsCaptured(isCaptured);
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
return nodeIndex;
}
@@ -213,7 +216,7 @@ private:
if (nodePtr->op() == GetLocal)
nodeIndex = nodePtr->child1().index();
- return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
}
if (nodePtr->op() == GetLocal)
@@ -230,7 +233,7 @@ private:
NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
m_currentBlock->variablesAtHead.setLocalFirstTime(operand, nodeIndex);
@@ -274,7 +277,7 @@ private:
if (flushChild.op() == Phi) {
VariableAccessData* variableAccessData = flushChild.variableAccessData();
variableAccessData->mergeIsCaptured(isCaptured);
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
return nodeIndex;
}
@@ -290,7 +293,7 @@ private:
// We're getting an argument in the first basic block; link
// the GetLocal to the SetArgument.
ASSERT(nodePtr->local() == static_cast<VirtualRegister>(operand));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
return nodeIndex;
}
@@ -298,7 +301,7 @@ private:
if (isCaptured) {
if (nodePtr->op() == GetLocal)
nodeIndex = nodePtr->child1().index();
- return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+ return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
}
if (nodePtr->op() == GetLocal)
@@ -312,7 +315,7 @@ private:
NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
- nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+ nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, nodeIndex);
@@ -725,7 +728,7 @@ private:
{
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
prediction = getPrediction();
@@ -747,23 +750,44 @@ private:
return call;
}
- PredictedType getPredictionWithoutOSRExit(NodeIndex nodeIndex, unsigned bytecodeIndex)
+ NodeIndex addStructureTransitionCheck(JSCell* object, Structure* structure)
+ {
+ // Add a weak JS constant for the object regardless, since the code should
+ // be jettisoned if the object ever dies.
+ NodeIndex objectIndex = cellConstant(object);
+
+ if (object->structure() == structure && structure->transitionWatchpointSetIsStillValid()) {
+ addToGraph(StructureTransitionWatchpoint, OpInfo(structure), objectIndex);
+ return objectIndex;
+ }
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectIndex);
+
+ return objectIndex;
+ }
+
+ NodeIndex addStructureTransitionCheck(JSCell* object)
+ {
+ return addStructureTransitionCheck(object, object->structure());
+ }
+
+ SpeculatedType getPredictionWithoutOSRExit(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
UNUSED_PARAM(nodeIndex);
- PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
+ SpeculatedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
+ dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, speculationToString(prediction));
#endif
return prediction;
}
- PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
+ SpeculatedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
- PredictedType prediction = getPredictionWithoutOSRExit(nodeIndex, bytecodeIndex);
+ SpeculatedType prediction = getPredictionWithoutOSRExit(nodeIndex, bytecodeIndex);
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
// We have no information about what values this node generates. Give up
// on executing this code, since we're likely to do more damage than good.
addToGraph(ForceOSRExit);
@@ -772,12 +796,12 @@ private:
return prediction;
}
- PredictedType getPredictionWithoutOSRExit()
+ SpeculatedType getPredictionWithoutOSRExit()
{
return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
}
- PredictedType getPrediction()
+ SpeculatedType getPrediction()
{
return getPrediction(m_graph.size(), m_currentProfilingIndex);
}
@@ -1020,7 +1044,7 @@ private:
VirtualRegister m_returnValue;
- // Predictions about variable types collected from the profiled code block,
+ // Speculations about variable types collected from the profiled code block,
// which are based on OSR exit profiles that past DFG compilatins of this
// code block had gathered.
LazyOperandValueProfileParser m_lazyOperands;
@@ -1147,7 +1171,7 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
int resultOperand = 0; // make compiler happy
unsigned nextOffset = m_currentIndex + OPCODE_LENGTH(op_call);
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
resultOperand = putInstruction[1].u.operand;
usesResult = true;
@@ -1231,6 +1255,9 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// Does the code block's size match the heuristics/requirements for being
// an inline candidate?
CodeBlock* profiledBlock = executable->profiledCodeBlockFor(kind);
+ if (!profiledBlock)
+ return false;
+
if (!mightInlineFunctionFor(profiledBlock, kind))
return false;
@@ -1270,6 +1297,8 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
for (size_t i = 0; i < m_graph.m_blocks.size(); ++i)
m_graph.m_blocks[i]->ensureLocals(newNumLocals);
}
+
+ size_t argumentPositionStart = m_graph.m_argumentPositions.size();
InlineStackEntry inlineStackEntry(
this, codeBlock, profiledBlock, m_graph.m_blocks.size() - 1,
@@ -1284,7 +1313,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
m_currentIndex = 0;
m_currentProfilingIndex = 0;
- addToGraph(InlineStart);
+ addToGraph(InlineStart, OpInfo(argumentPositionStart));
parseCodeBlock();
@@ -1418,7 +1447,7 @@ bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType o
// FIXME: We dead-code-eliminate unused Math intrinsics, but that's invalid because
// they need to perform the ToNumber conversion, which can have side-effects.
-bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction)
+bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction)
{
switch (intrinsic) {
case AbsIntrinsic: {
@@ -1482,7 +1511,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
int thisOperand = registerOffset + argumentToOperand(0);
- if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+ if (!(m_graph[get(thisOperand)].prediction() & SpecString))
return false;
int indexOperand = registerOffset + argumentToOperand(1);
@@ -1499,7 +1528,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
int thisOperand = registerOffset + argumentToOperand(0);
- if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+ if (!(m_graph[get(thisOperand)].prediction() & SpecString))
return false;
int indexOperand = registerOffset + argumentToOperand(1);
@@ -1538,6 +1567,80 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
}
}
+void ByteCodeParser::handleGetById(
+ int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber,
+ const GetByIdStatus& getByIdStatus)
+{
+ if (!getByIdStatus.isSimple()
+ || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
+ set(destinationOperand,
+ addToGraph(
+ getByIdStatus.makesCalls() ? GetByIdFlush : GetById,
+ OpInfo(identifierNumber), OpInfo(prediction), base));
+ return;
+ }
+
+ ASSERT(getByIdStatus.structureSet().size());
+
+ // The implementation of GetByOffset does not know to terminate speculative
+ // execution if it doesn't have a prediction, so we do it manually.
+ if (prediction == SpecNone)
+ addToGraph(ForceOSRExit);
+
+ NodeIndex originalBaseForBaselineJIT = base;
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
+
+ bool useInlineStorage;
+ if (!getByIdStatus.chain().isEmpty()) {
+ Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
+ JSObject* currentObject = 0;
+ for (unsigned i = 0; i < getByIdStatus.chain().size(); ++i) {
+ currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
+ currentStructure = getByIdStatus.chain()[i];
+ base = addStructureTransitionCheck(currentObject, currentStructure);
+ }
+ useInlineStorage = currentStructure->isUsingInlineStorage();
+ } else
+ useInlineStorage = getByIdStatus.structureSet().allAreUsingInlinePropertyStorage();
+
+ // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
+ // ensure that the base of the original get_by_id is kept alive until we're done with
+ // all of the speculations. We only insert the Phantom if there had been a CheckStructure
+ // on something other than the base following the CheckStructure on base, or if the
+ // access was compiled to a WeakJSConstant specific value, in which case we might not
+ // have any explicit use of the base at all.
+ if (getByIdStatus.specificValue() || originalBaseForBaselineJIT != base)
+ addToGraph(Phantom, originalBaseForBaselineJIT);
+
+ if (getByIdStatus.specificValue()) {
+ ASSERT(getByIdStatus.specificValue().isCell());
+
+ set(destinationOperand, cellConstant(getByIdStatus.specificValue().asCell()));
+ return;
+ }
+
+ NodeIndex propertyStorage;
+ size_t offsetOffset;
+ if (useInlineStorage) {
+ propertyStorage = base;
+ ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
+ offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
+ } else {
+ propertyStorage = addToGraph(GetPropertyStorage, base);
+ offsetOffset = 0;
+ }
+ set(destinationOperand,
+ addToGraph(
+ GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction),
+ propertyStorage));
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+}
+
void ByteCodeParser::prepareToParseBlock()
{
for (unsigned i = 0; i < m_constants.size(); ++i)
@@ -1972,7 +2075,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// === Property access operations ===
case op_get_by_val: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
@@ -1997,7 +2100,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
@@ -2020,18 +2123,22 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// but the slow path (i.e. the normal get_by_id) never fired.
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
- if (methodCallStatus.needsPrototypeCheck())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
-
+ if (methodCallStatus.needsPrototypeCheck()) {
+ addStructureTransitionCheck(
+ methodCallStatus.prototype(), methodCallStatus.prototypeStructure());
+ addToGraph(Phantom, base);
+ }
set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
- } else
- set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
+ } else {
+ handleGetById(
+ getInstruction[1].u.operand, prediction, base, identifier, getByIdStatus);
+ }
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
}
case op_get_scoped_var: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
int dst = currentInstruction[1].u.operand;
int slot = currentInstruction[2].u.operand;
int depth = currentInstruction[3].u.operand;
@@ -2049,7 +2156,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_put_scoped_var);
}
case op_get_by_id: {
- PredictedType prediction = getPredictionWithoutOSRExit();
+ SpeculatedType prediction = getPredictionWithoutOSRExit();
NodeIndex base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
@@ -2058,34 +2165,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
- if (getByIdStatus.isSimpleDirect()
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- ASSERT(getByIdStatus.structureSet().size());
-
- // The implementation of GetByOffset does not know to terminate speculative
- // execution if it doesn't have a prediction, so we do it manually.
- if (prediction == PredictNone)
- addToGraph(ForceOSRExit);
-
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
- NodeIndex propertyStorage;
- size_t offsetOffset;
- if (getByIdStatus.structureSet().allAreUsingInlinePropertyStorage()) {
- propertyStorage = base;
- ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
- offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
- } else {
- propertyStorage = addToGraph(GetPropertyStorage, base);
- offsetOffset = 0;
- }
- set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage));
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
- } else
- set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+ handleGetById(
+ currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus);
NEXT_OPCODE(op_get_by_id);
}
@@ -2134,23 +2215,20 @@ bool ByteCodeParser::parseBlock(unsigned limit)
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
if (!direct) {
- if (!putByIdStatus.oldStructure()->storedPrototype().isNull())
- addToGraph(
- CheckStructure,
- OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure()->storedPrototype().asCell()->structure())),
- cellConstant(putByIdStatus.oldStructure()->storedPrototype().asCell()));
+ if (!putByIdStatus.oldStructure()->storedPrototype().isNull()) {
+ addStructureTransitionCheck(
+ putByIdStatus.oldStructure()->storedPrototype().asCell());
+ }
for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
JSValue prototype = (*it)->storedPrototype();
if (prototype.isNull())
continue;
ASSERT(prototype.isCell());
- addToGraph(
- CheckStructure,
- OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())),
- cellConstant(prototype.asCell()));
+ addStructureTransitionCheck(prototype.asCell());
}
}
+ ASSERT(putByIdStatus.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
addToGraph(
PutStructure,
OpInfo(
@@ -2192,19 +2270,94 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_get_global_var: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
- NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand), OpInfo(prediction));
+ JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
+
+ NodeIndex getGlobalVar = addToGraph(
+ GetGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(prediction));
set(currentInstruction[1].u.operand, getGlobalVar);
NEXT_OPCODE(op_get_global_var);
}
+
+ case op_get_global_var_watchable: {
+ SpeculatedType prediction = getPrediction();
+
+ JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
+
+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
+ Identifier identifier = m_codeBlock->identifier(identifierNumber);
+ SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl());
+ if (!entry.couldBeWatched()) {
+ NodeIndex getGlobalVar = addToGraph(
+ GetGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(prediction));
+ set(currentInstruction[1].u.operand, getGlobalVar);
+ NEXT_OPCODE(op_get_global_var_watchable);
+ }
+
+ // The watchpoint is still intact! This means that we will get notified if the
+ // current value in the global variable changes. So, we can inline that value.
+ // Moreover, currently we can assume that this value is a JSFunction*, which
+ // implies that it's a cell. This simplifies things, since in general we'd have
+ // to use a JSConstant for non-cells and a WeakJSConstant for cells. So instead
+ // of having both cases we just assert that the value is a cell.
+
+ // NB. If it wasn't for CSE, GlobalVarWatchpoint would have no need for the
+ // register pointer. But CSE tracks effects on global variables by comparing
+ // register pointers. Because CSE executes multiple times while the backend
+ // executes once, we use the following performance trade-off:
+ // - The node refers directly to the register pointer to make CSE super cheap.
+ // - To perform backend code generation, the node only contains the identifier
+ // number, from which it is possible to get (via a few average-time O(1)
+ // lookups) to the WatchpointSet.
+
+ addToGraph(
+ GlobalVarWatchpoint,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[2].u.registerPointer)),
+ OpInfo(identifierNumber));
+
+ JSValue specificValue = globalObject->registerAt(entry.getIndex()).get();
+ ASSERT(specificValue.isCell());
+ set(currentInstruction[1].u.operand, cellConstant(specificValue.asCell()));
+
+ NEXT_OPCODE(op_get_global_var_watchable);
+ }
case op_put_global_var: {
NodeIndex value = get(currentInstruction[2].u.operand);
- addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
+ addToGraph(
+ PutGlobalVar,
+ OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ value);
NEXT_OPCODE(op_put_global_var);
}
+ case op_put_global_var_check: {
+ NodeIndex value = get(currentInstruction[2].u.operand);
+ CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
+ JSGlobalObject* globalObject = codeBlock->globalObject();
+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[4].u.operand];
+ Identifier identifier = m_codeBlock->identifier(identifierNumber);
+ SymbolTableEntry entry = globalObject->symbolTable().get(identifier.impl());
+ if (!entry.couldBeWatched()) {
+ addToGraph(
+ PutGlobalVar,
+ OpInfo(globalObject->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ value);
+ NEXT_OPCODE(op_put_global_var_check);
+ }
+ addToGraph(
+ PutGlobalVarCheck,
+ OpInfo(codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
+ OpInfo(identifierNumber),
+ value);
+ NEXT_OPCODE(op_put_global_var_check);
+ }
+
// === Block terminators. ===
case op_jmp: {
@@ -2433,7 +2586,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call_varargs);
- PredictedType prediction = PredictNone;
+ SpeculatedType prediction = SpecNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call_varargs);
prediction = getPrediction();
@@ -2471,7 +2624,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
LAST_OPCODE(op_jneq_ptr);
case op_resolve: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
@@ -2482,7 +2635,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_resolve_base: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
@@ -2493,7 +2646,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_resolve_global: {
- PredictedType prediction = getPrediction();
+ SpeculatedType prediction = getPrediction();
NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
m_graph.m_resolveGlobalData.append(ResolveGlobalData());
@@ -2747,7 +2900,7 @@ void ByteCodeParser::processPhiStack()
}
}
-void ByteCodeParser::fixVariableAccessPredictions()
+void ByteCodeParser::fixVariableAccessSpeculations()
{
for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
VariableAccessData* data = &m_graph.m_variableAccessData[i];
@@ -2843,7 +2996,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
, m_caller(byteCodeParser->m_inlineStackTop)
{
m_argumentPositions.resize(argumentCountIncludingThis);
- for (unsigned i = argumentCountIncludingThis; i--;) {
+ for (int i = 0; i < argumentCountIncludingThis; ++i) {
byteCodeParser->m_graph.m_argumentPositions.append(ArgumentPosition());
ArgumentPosition* argumentPosition = &byteCodeParser->m_graph.m_argumentPositions.last();
m_argumentPositions[i] = argumentPosition;
@@ -3073,7 +3226,7 @@ bool ByteCodeParser::parse()
m_graph.m_blocks[blockIndex].clear();
}
- fixVariableAccessPredictions();
+ fixVariableAccessSpeculations();
m_graph.m_preservedVars = m_preservedVars;
m_graph.m_localVars = m_numLocals;
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index dc3af636e..4cacd45c1 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -94,6 +94,12 @@ public:
addCallArgument(arg1);
addCallArgument(arg2);
}
+
+ ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
+ {
+ resetCallArguments();
+ addCallArgument(arg1);
+ }
ALWAYS_INLINE void setupArgumentsExecState()
{
@@ -216,6 +222,15 @@ public:
addCallArgument(arg4);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
{
resetCallArguments();
@@ -424,6 +439,11 @@ public:
{
setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
}
+
+ ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
+ {
+ move(arg1, GPRInfo::argumentGPR0);
+ }
ALWAYS_INLINE void setupArgumentsExecState()
{
@@ -554,6 +574,14 @@ public:
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
+ {
+ move(arg3, GPRInfo::argumentGPR3);
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3)
{
move(arg2, GPRInfo::argumentGPR2);
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index 0f0a22562..161f51e30 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -288,7 +288,7 @@ private:
if (child.op() != GetLocal)
return;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" Considering GetLocal at @%u.\n", edge.index());
+ dataLog(" Considering GetLocal at @%u, local r%d.\n", edge.index(), child.local());
#endif
if (child.variableAccessData()->isCaptured()) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
@@ -302,6 +302,10 @@ private:
#endif
ASSERT(originalNodeIndex != NoNode);
Node* originalNode = &m_graph[originalNodeIndex];
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog(" Original has local r%d.\n", originalNode->local());
+#endif
+ ASSERT(child.local() == originalNode->local());
if (changeRef)
ASSERT(originalNode->shouldGenerate());
// Possibilities:
@@ -389,7 +393,7 @@ private:
if (myNode.op() == GetLocal)
myNodeIndex = myNode.child1().index();
for (unsigned j = 0; j < AdjacencyList::Size; ++j)
- removePotentiallyDeadPhiReference(myNodeIndex, phiNode, j);
+ removePotentiallyDeadPhiReference(myNodeIndex, phiNode, j, sourceBlock->isReachable);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog("\n");
#endif
@@ -414,14 +418,14 @@ private:
fixPhis(blockIndex, jettisonedBlockIndex);
}
- void removePotentiallyDeadPhiReference(NodeIndex myNodeIndex, Node& phiNode, unsigned edgeIndex)
+ void removePotentiallyDeadPhiReference(NodeIndex myNodeIndex, Node& phiNode, unsigned edgeIndex, bool changeRef)
{
if (phiNode.children.child(edgeIndex).indexUnchecked() != myNodeIndex)
return;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Removing reference at child %u.", edgeIndex);
#endif
- if (phiNode.shouldGenerate())
+ if (changeRef && phiNode.shouldGenerate())
m_graph.deref(myNodeIndex);
phiNode.children.removeEdgeFromBag(edgeIndex);
}
@@ -600,6 +604,8 @@ private:
NodeIndex nodeIndex = secondBlock->at(i);
Node& node = m_graph[nodeIndex];
+ bool childrenAlreadyFixed = false;
+
switch (node.op()) {
case Phantom: {
if (!node.child1())
@@ -611,8 +617,12 @@ private:
NodeIndex setLocalIndex =
firstBlock->variablesAtTail.operand(possibleLocalOp.local());
Node& setLocal = m_graph[setLocalIndex];
- if (setLocal.op() == SetLocal)
+ if (setLocal.op() == SetLocal) {
m_graph.changeEdge(node.children.child1(), setLocal.child1());
+ ASSERT(!node.child2());
+ ASSERT(!node.child3());
+ childrenAlreadyFixed = true;
+ }
}
break;
}
@@ -632,6 +642,19 @@ private:
NodeIndex atFirstIndex = firstBlock->variablesAtTail.operand(node.local());
m_graph.changeEdge(node.children.child1(), Edge(skipGetLocal(atFirstIndex)), node.shouldGenerate());
+ childrenAlreadyFixed = true;
+
+ if (node.op() != GetLocal)
+ break;
+
+ NodeIndex atFirstHeadIndex = firstBlock->variablesAtHead.operand(node.local());
+ if (atFirstHeadIndex == NoNode)
+ break;
+
+ if (m_graph[atFirstHeadIndex].op() != Phi)
+ break;
+
+ firstBlock->variablesAtHead.operand(node.local()) = nodeIndex;
break;
}
@@ -639,20 +662,22 @@ private:
break;
}
- bool changeRef = node.shouldGenerate();
+ if (!childrenAlreadyFixed) {
+ bool changeRef = node.shouldGenerate();
- // If the child is a GetLocal, then we might like to fix it.
- if (node.flags() & NodeHasVarArgs) {
- for (unsigned childIdx = node.firstChild();
- childIdx < node.firstChild() + node.numChildren();
- ++childIdx)
- fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
- } else if (!!node.child1()) {
- fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef);
- if (!!node.child2()) {
- fixPossibleGetLocal(firstBlock, node.children.child2(), changeRef);
- if (!!node.child3())
- fixPossibleGetLocal(firstBlock, node.children.child3(), changeRef);
+ // If the child is a GetLocal, then we might like to fix it.
+ if (node.flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node.firstChild();
+ childIdx < node.firstChild() + node.numChildren();
+ ++childIdx)
+ fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
+ } else if (!!node.child1()) {
+ fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef);
+ if (!!node.child2()) {
+ fixPossibleGetLocal(firstBlock, node.children.child2(), changeRef);
+ if (!!node.child3())
+ fixPossibleGetLocal(firstBlock, node.children.child3(), changeRef);
+ }
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 31488cb1c..a362e6e97 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -48,9 +48,10 @@ public:
bool run()
{
+ m_changed = false;
for (unsigned block = 0; block < m_graph.m_blocks.size(); ++block)
performBlockCSE(m_graph.m_blocks[block].get());
- return true; // Maybe we'll need to make this reason about whether it changed the graph in an actionable way?
+ return m_changed;
}
private:
@@ -193,18 +194,18 @@ private:
return NoNode;
}
- NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject)
+ NodeIndex globalVarLoadElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
switch (node.op()) {
case GetGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return index;
break;
case PutGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return node.child1().index();
break;
default:
@@ -216,7 +217,30 @@ private:
return NoNode;
}
- NodeIndex globalVarStoreElimination(unsigned varNumber, JSGlobalObject* globalObject)
+ bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ Node& node = m_graph[index];
+ switch (node.op()) {
+ case GlobalVarWatchpoint:
+ if (node.registerPointer() == registerPointer)
+ return true;
+ break;
+ case PutGlobalVar:
+ if (node.registerPointer() == registerPointer)
+ return false;
+ break;
+ default:
+ break;
+ }
+ if (m_graph.clobbersWorld(index))
+ break;
+ }
+ return false;
+ }
+
+ NodeIndex globalVarStoreElimination(WriteBarrier<Unknown>* registerPointer)
{
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
@@ -225,12 +249,13 @@ private:
continue;
switch (node.op()) {
case PutGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ case PutGlobalVarCheck:
+ if (node.registerPointer() == registerPointer)
return index;
break;
case GetGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ if (node.registerPointer() == registerPointer)
return NoNode;
break;
@@ -316,6 +341,12 @@ private:
return true;
break;
+ case StructureTransitionWatchpoint:
+ if (node.child1() == child1
+ && structureSet.contains(node.structure()))
+ return true;
+ break;
+
case PutStructure:
if (node.child1() == child1
&& structureSet.contains(node.structureTransitionData().newStructure))
@@ -347,6 +378,53 @@ private:
return false;
}
+ bool structureTransitionWatchpointElimination(Structure* structure, NodeIndex child1)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ if (index == child1)
+ break;
+
+ Node& node = m_graph[index];
+ switch (node.op()) {
+ case CheckStructure:
+ if (node.child1() == child1
+ && node.structureSet().containsOnly(structure))
+ return true;
+ break;
+
+ case PutStructure:
+ ASSERT(node.structureTransitionData().previousStructure != structure);
+ break;
+
+ case PutByOffset:
+ // Setting a property cannot change the structure.
+ break;
+
+ case PutByVal:
+ case PutByValAlias:
+ if (m_graph.byValIsPure(node)) {
+ // If PutByVal speculates that it's accessing an array with an
+ // integer index, then it's impossible for it to cause a structure
+ // change.
+ break;
+ }
+ return false;
+
+ case StructureTransitionWatchpoint:
+ if (node.structure() == structure && node.child1() == child1)
+ return true;
+ break;
+
+ default:
+ if (m_graph.clobbersWorld(index))
+ return false;
+ break;
+ }
+ }
+ return false;
+ }
+
NodeIndex putStructureStoreElimination(NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -538,8 +616,8 @@ private:
Node& node = m_graph[index];
switch (node.op()) {
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
if (node.child1() == child1 && hasIntegerIndexPrediction == nodeHasIntegerIndexPrediction)
return index;
break;
@@ -556,7 +634,7 @@ private:
break;
case PutByVal:
- if (isFixedIndexedStorageObjectPrediction(m_graph[node.child1()].prediction()) && m_graph.byValIsPure(node))
+ if (isFixedIndexedStorageObjectSpeculation(m_graph[node.child1()].prediction()) && m_graph.byValIsPure(node))
break;
return NoNode;
@@ -619,9 +697,22 @@ private:
return NoNode;
}
- // This returns the Flush node that is keeping a SetLocal alive.
- NodeIndex setLocalStoreElimination(VirtualRegister local, NodeIndex expectedNodeIndex)
+ struct SetLocalStoreEliminationResult {
+ SetLocalStoreEliminationResult()
+ : mayBeAccessed(false)
+ , mayExit(false)
+ , mayClobberWorld(false)
+ {
+ }
+
+ bool mayBeAccessed;
+ bool mayExit;
+ bool mayClobberWorld;
+ };
+ SetLocalStoreEliminationResult setLocalStoreElimination(
+ VirtualRegister local, NodeIndex expectedNodeIndex)
{
+ SetLocalStoreEliminationResult result;
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
@@ -631,46 +722,67 @@ private:
case GetLocal:
case Flush:
if (node.local() == local)
- return NoNode;
+ result.mayBeAccessed = true;
break;
case GetLocalUnlinked:
if (node.unlinkedLocal() == local)
- return NoNode;
+ result.mayBeAccessed = true;
break;
case SetLocal: {
if (node.local() != local)
break;
if (index != expectedNodeIndex)
- return NoNode;
+ result.mayBeAccessed = true;
if (m_graph[index].refCount() > 1)
- return NoNode;
- return index;
+ result.mayBeAccessed = true;
+ return result;
}
case GetScopeChain:
if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
- return NoNode;
+ result.mayBeAccessed = true;
+ break;
+
+ case CheckArgumentsNotCreated:
+ case GetMyArgumentsLength:
+ case GetMyArgumentsLengthSafe:
+ if (m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin) == local)
+ result.mayBeAccessed = true;
+ break;
+
+ case GetMyArgumentByVal:
+ case GetMyArgumentByValSafe:
+ result.mayBeAccessed = true;
+ break;
+
+ case GetByVal:
+ // If this is accessing arguments then it's potentially accessing locals.
+ if (m_graph[node.child1()].shouldSpeculateArguments())
+ result.mayBeAccessed = true;
break;
+ case CreateArguments:
case TearOffActivation:
case TearOffArguments:
// If an activation is being torn off then it means that captured variables
// are live. We could be clever here and check if the local qualifies as an
// argument register. But that seems like it would buy us very little since
// any kind of tear offs are rare to begin with.
- return NoNode;
+ result.mayBeAccessed = true;
+ break;
default:
- if (m_graph.clobbersWorld(index))
- return NoNode;
break;
}
- if (node.canExit())
- return NoNode;
+ result.mayExit |= node.canExit();
+ result.mayClobberWorld |= m_graph.clobbersWorld(index);
}
- return NoNode;
+ ASSERT_NOT_REACHED();
+ // Be safe in release mode.
+ result.mayBeAccessed = true;
+ return result;
}
void performSubstitution(Edge& child, bool addRef = true)
@@ -848,35 +960,64 @@ private:
m_graph.ref(phiIndex);
}
}
+ m_changed = true;
break;
}
case GetLocalUnlinked: {
NodeIndex relevantLocalOpIgnored;
- setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored));
+ m_changed |= setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored));
break;
}
case Flush: {
- if (m_fixpointState == FixpointNotConverged)
- break;
VariableAccessData* variableAccessData = node.variableAccessData();
- if (!variableAccessData->isCaptured())
- break;
VirtualRegister local = variableAccessData->local();
- NodeIndex replacementIndex = setLocalStoreElimination(local, node.child1().index());
- if (replacementIndex == NoNode)
- break;
+ NodeIndex replacementIndex = node.child1().index();
Node& replacement = m_graph[replacementIndex];
+ if (replacement.op() != SetLocal)
+ break;
+ ASSERT(replacement.variableAccessData() == variableAccessData);
+ // FIXME: We should be able to remove SetLocals that can exit; we just need
+ // to replace them with appropriate type checks.
+ if (m_fixpointState == FixpointNotConverged) {
+ // Need to be conservative at this time; if the SetLocal has any chance of performing
+ // any speculations then we cannot do anything.
+ if (variableAccessData->isCaptured()) {
+ // Captured SetLocals never speculate and hence never exit.
+ } else {
+ if (variableAccessData->shouldUseDoubleFormat())
+ break;
+ SpeculatedType prediction = variableAccessData->argumentAwarePrediction();
+ if (isInt32Speculation(prediction))
+ break;
+ if (isArraySpeculation(prediction))
+ break;
+ if (isBooleanSpeculation(prediction))
+ break;
+ }
+ } else {
+ if (replacement.canExit())
+ break;
+ }
+ SetLocalStoreEliminationResult result =
+ setLocalStoreElimination(local, replacementIndex);
+ if (result.mayBeAccessed || result.mayClobberWorld)
+ break;
ASSERT(replacement.op() == SetLocal);
ASSERT(replacement.refCount() == 1);
ASSERT(replacement.shouldGenerate());
+ // FIXME: Investigate using mayExit as a further optimization.
node.setOpAndDefaultFlags(Phantom);
NodeIndex dataNodeIndex = replacement.child1().index();
ASSERT(m_graph[dataNodeIndex].hasResult());
m_graph.clearAndDerefChild1(node);
node.children.child1() = Edge(dataNodeIndex);
m_graph.ref(dataNodeIndex);
+ NodeIndex oldTailIndex = m_currentBlock->variablesAtTail.operand(local);
+ if (oldTailIndex == m_compileIndex)
+ m_currentBlock->variablesAtTail.operand(local) = replacementIndex;
+ m_changed = true;
break;
}
@@ -918,13 +1059,19 @@ private:
// Finally handle heap accesses. These are not quite pure, but we can still
// optimize them provided that some subtle conditions are met.
case GetGlobalVar:
- setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+ setReplacement(globalVarLoadElimination(node.registerPointer()));
+ break;
+
+ case GlobalVarWatchpoint:
+ if (globalVarWatchpointElimination(node.registerPointer()))
+ eliminate();
break;
case PutGlobalVar:
+ case PutGlobalVarCheck:
if (m_fixpointState == FixpointNotConverged)
break;
- eliminate(globalVarStoreElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+ eliminate(globalVarStoreElimination(node.registerPointer()));
break;
case GetByVal:
@@ -944,6 +1091,11 @@ private:
eliminate();
break;
+ case StructureTransitionWatchpoint:
+ if (structureTransitionWatchpointElimination(node.structure(), node.child1().index()))
+ eliminate();
+ break;
+
case PutStructure:
if (m_fixpointState == FixpointNotConverged)
break;
@@ -956,8 +1108,8 @@ private:
break;
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction));
break;
}
@@ -1010,6 +1162,7 @@ private:
Vector<NodeIndex, 16> m_replacements;
FixedArray<unsigned, LastNodeType> m_lastSeen;
OptimizationFixpointState m_fixpointState;
+ bool m_changed; // Only tracks changes that have a substantive effect on other optimizations.
};
bool performCSE(Graph& graph, OptimizationFixpointState fixpointState)
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h
index 694e886ee..027b0f78b 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.h
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h
@@ -123,7 +123,9 @@ inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instructi
case op_put_by_id_transition_direct:
case op_put_by_id_transition_normal:
case op_get_global_var:
+ case op_get_global_var_watchable:
case op_put_global_var:
+ case op_put_global_var_check:
case op_jmp:
case op_loop:
case op_jtrue:
diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h
index b2e3bb4ee..fce76c68c 100644
--- a/Source/JavaScriptCore/dfg/DFGCommon.h
+++ b/Source/JavaScriptCore/dfg/DFGCommon.h
@@ -55,6 +55,8 @@
#else
#define DFG_ENABLE_VALIDATION 0
#endif
+// Enable validation on completion of each phase.
+#define DFG_ENABLE_PER_PHASE_VALIDATION 0
// Consistency check contents compiler data structures.
#define DFG_ENABLE_CONSISTENCY_CHECK 0
// Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index 1e75ddea1..9e6720c80 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -56,15 +56,44 @@ public:
continue;
if (!block->cfaFoundConstants)
continue;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+ dataLog("Constant folding considering Block #%u.\n", blockIndex);
+#endif
state.beginBasicBlock(block);
for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
if (!state.isValid())
break;
- state.execute(indexInBlock);
NodeIndex nodeIndex = block->at(indexInBlock);
Node& node = m_graph[nodeIndex];
+
+ bool eliminated = false;
+
+ switch (node.op()) {
+ case CheckArgumentsNotCreated: {
+ if (!isEmptySpeculation(
+ state.variables().operand(
+ m_graph.argumentsRegisterFor(node.codeOrigin)).m_type))
+ break;
+ ASSERT(node.refCount() == 1);
+ node.setOpAndDefaultFlags(Phantom);
+ eliminated = true;
+ break;
+ }
+
+ // FIXME: This would be a great place to remove CheckStructure's.
+
+ default:
+ break;
+ }
+
+ if (eliminated) {
+ changed = true;
+ continue;
+ }
+
+ state.execute(indexInBlock);
if (!node.shouldGenerate()
- || m_graph.clobbersWorld(node)
+ || state.didClobber()
|| node.hasConstant())
continue;
JSValue value = state.forNode(nodeIndex).value();
@@ -74,11 +103,9 @@ public:
Node phantom(Phantom, node.codeOrigin);
if (node.op() == GetLocal) {
- ASSERT(m_graph[node.child1()].op() == Phi);
- ASSERT(!m_graph[node.child1()].hasResult());
-
NodeIndex previousLocalAccess = NoNode;
- if (block->variablesAtHead.operand(node.local()) == nodeIndex) {
+ if (block->variablesAtHead.operand(node.local()) == nodeIndex
+ && m_graph[node.child1()].op() == Phi) {
// We expect this to be the common case.
ASSERT(block->isInPhis(node.child1().index()));
previousLocalAccess = node.child1().index();
@@ -86,7 +113,7 @@ public:
} else {
ASSERT(indexInBlock > 0);
// Must search for the previous access to this local.
- for (BlockIndex subIndexInBlock = indexInBlock - 1; subIndexInBlock--;) {
+ for (BlockIndex subIndexInBlock = indexInBlock; subIndexInBlock--;) {
NodeIndex subNodeIndex = block->at(subIndexInBlock);
Node& subNode = m_graph[subNodeIndex];
if (!subNode.shouldGenerate())
@@ -97,13 +124,6 @@ public:
continue;
// The two must have been unified.
ASSERT(subNode.variableAccessData() == node.variableAccessData());
- // Currently, the previous node must be a flush.
- // NOTE: This assertion should be removed if we ever do
- // constant folding on captured variables. In particular,
- // this code does not require the previous node to be a flush,
- // but we are asserting this anyway because it is a constraint
- // of the IR and this is as good a place as any to assert it.
- ASSERT(subNode.op() == Flush);
previousLocalAccess = subNodeIndex;
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
index bfa149604..93cb49c01 100644
--- a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
+++ b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h
@@ -66,6 +66,11 @@ public:
#endif
}
+ bool isSet()
+ {
+ return m_codeOffset != std::numeric_limits<uint32_t>::max();
+ }
+
void switchToLateJump(MacroAssembler::PatchableJump check)
{
#ifndef NDEBUG
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp
index 6ebe338f5..e932792df 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp
@@ -82,10 +82,11 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
changed |= performConstantFolding(dfg);
changed |= performArgumentsSimplification(dfg);
changed |= performCFGSimplification(dfg);
+ changed |= performCSE(dfg, FixpointNotConverged);
if (!changed)
break;
- performCSE(dfg, FixpointNotConverged);
dfg.resetExitStates();
+ performFixup(dfg);
}
performCSE(dfg, FixpointConverged);
#if DFG_ENABLE(DEBUG_VERBOSE)
@@ -94,10 +95,13 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
dfg.m_dominators.compute(dfg);
performVirtualRegisterAllocation(dfg);
+ GraphDumpMode modeForFinalValidate = DumpGraph;
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("Graph after optimization:\n");
dfg.dump();
+ modeForFinalValidate = DontDumpGraph;
#endif
+ validate(dfg, modeForFinalValidate);
JITCompiler dataFlowJIT(dfg);
bool result;
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index e54d2cfaf..f6e3c0a96 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -74,13 +74,13 @@ private:
switch (op) {
case GetById: {
- if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
+ if (!isInt32Speculation(m_graph[m_compileIndex].prediction()))
break;
if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
break;
- bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
- bool isArguments = isArgumentsPrediction(m_graph[node.child1()].prediction());
- bool isString = isStringPrediction(m_graph[node.child1()].prediction());
+ bool isArray = isArraySpeculation(m_graph[node.child1()].prediction());
+ bool isArguments = isArgumentsSpeculation(m_graph[node.child1()].prediction());
+ bool isString = isStringSpeculation(m_graph[node.child1()].prediction());
bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
@@ -129,10 +129,10 @@ private:
break;
}
case GetIndexedPropertyStorage: {
- PredictedType basePrediction = m_graph[node.child2()].prediction();
- if ((!(basePrediction & PredictInt32) && basePrediction)
+ SpeculatedType basePrediction = m_graph[node.child2()].prediction();
+ if ((!(basePrediction & SpecInt32) && basePrediction)
|| m_graph[node.child1()].shouldSpeculateArguments()
- || !isActionableArrayPrediction(m_graph[node.child1()].prediction())) {
+ || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
node.setOpAndDefaultFlags(Nop);
m_graph.clearAndDerefChild1(node);
m_graph.clearAndDerefChild2(node);
@@ -150,7 +150,8 @@ private:
}
case ValueToInt32: {
- if (m_graph[node.child1()].shouldSpeculateNumber()) {
+ if (m_graph[node.child1()].shouldSpeculateNumber()
+ && node.mustGenerate()) {
node.clearFlags(NodeMustGenerate);
m_graph.deref(m_compileIndex);
}
@@ -284,7 +285,7 @@ private:
Node newDivision = oldDivision;
newDivision.setRefCount(2);
- newDivision.predict(PredictDouble);
+ newDivision.predict(SpecDouble);
NodeIndex newDivisionIndex = m_graph.size();
oldDivision.setOp(DoubleAsInt32);
@@ -318,7 +319,7 @@ private:
break;
if (!m_graph[node.child2()].shouldSpeculateInteger())
break;
- if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+ if (isActionableIntMutableArraySpeculation(m_graph[node.child1()].prediction())) {
if (m_graph[node.child3()].isConstant())
break;
if (m_graph[node.child3()].shouldSpeculateInteger())
@@ -326,7 +327,7 @@ private:
fixDoubleEdge(2);
break;
}
- if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+ if (isActionableFloatMutableArraySpeculation(m_graph[node.child1()].prediction())) {
fixDoubleEdge(2);
break;
}
@@ -390,7 +391,7 @@ private:
m_insertionSet.append(m_indexInBlock, resultIndex);
Node& int32ToDouble = m_graph[resultIndex];
- int32ToDouble.predict(PredictDouble);
+ int32ToDouble.predict(SpecDouble);
int32ToDouble.ref();
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index 4562e30ee..93de024d7 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -76,7 +76,7 @@ const char* Graph::nameOfVariableAccessData(VariableAccessData* variableAccessDa
if (variableAccessData->isCaptured())
*ptr++ = '*';
- ptr.strcat(predictionToAbbreviatedString(variableAccessData->prediction()));
+ ptr.strcat(speculationToAbbreviatedString(variableAccessData->prediction()));
*ptr++ = 0;
@@ -169,7 +169,7 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%s@%u%s",
useKindToString(m_varArgChildren[childIdx].useKind()),
m_varArgChildren[childIdx].index(),
- predictionToAbbreviatedString(
+ speculationToAbbreviatedString(
at(m_varArgChildren[childIdx]).prediction()));
}
} else {
@@ -177,19 +177,19 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%s@%u%s",
useKindToString(node.child1().useKind()),
node.child1().index(),
- predictionToAbbreviatedString(at(node.child1()).prediction()));
+ speculationToAbbreviatedString(at(node.child1()).prediction()));
}
if (!!node.child2()) {
dataLog(", %s@%u%s",
useKindToString(node.child2().useKind()),
node.child2().index(),
- predictionToAbbreviatedString(at(node.child2()).prediction()));
+ speculationToAbbreviatedString(at(node.child2()).prediction()));
}
if (!!node.child3()) {
dataLog(", %s@%u%s",
useKindToString(node.child3().useKind()),
node.child3().index(),
- predictionToAbbreviatedString(at(node.child3()).prediction()));
+ speculationToAbbreviatedString(at(node.child3()).prediction()));
}
hasPrinted = !!node.child1();
}
@@ -202,6 +202,13 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("%svar%u", hasPrinted ? ", " : "", node.varNumber());
hasPrinted = true;
}
+ if (node.hasRegisterPointer()) {
+ dataLog(
+ "%sglobal%u(%p)", hasPrinted ? ", " : "",
+ globalObjectFor(node.codeOrigin)->findRegisterIndex(node.registerPointer()),
+ node.registerPointer());
+ hasPrinted = true;
+ }
if (node.hasIdentifier()) {
dataLog("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), m_codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
hasPrinted = true;
@@ -212,6 +219,10 @@ void Graph::dump(NodeIndex nodeIndex)
hasPrinted = true;
}
}
+ if (node.hasStructure()) {
+ dataLog("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
+ hasPrinted = true;
+ }
if (node.hasStructureTransitionData()) {
dataLog("%sstruct(%p -> %p)", hasPrinted ? ", " : "", node.structureTransitionData().previousStructure, node.structureTransitionData().newStructure);
hasPrinted = true;
@@ -269,9 +280,9 @@ void Graph::dump(NodeIndex nodeIndex)
if (!skipped) {
if (node.hasVariableAccessData())
- dataLog(" predicting %s, double ratio %lf%s", predictionToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
+ dataLog(" predicting %s, double ratio %lf%s", speculationToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
else if (node.hasHeapPrediction())
- dataLog(" predicting %s", predictionToString(node.getHeapPrediction()));
+ dataLog(" predicting %s", speculationToString(node.getHeapPrediction()));
}
dataLog("\n");
@@ -386,7 +397,7 @@ void Graph::predictArgumentTypes()
at(m_arguments[arg]).variableAccessData()->predict(profile->computeUpdatedPrediction());
#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("Argument [%zu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
+ dataLog("Argument [%zu] prediction: %s\n", arg, speculationToString(at(m_arguments[arg]).variableAccessData()->prediction()));
#endif
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 8ca3e2047..acc9ff472 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -187,9 +187,9 @@ public:
BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin);
- PredictedType getJSConstantPrediction(Node& node)
+ SpeculatedType getJSConstantSpeculation(Node& node)
{
- return predictionFromValue(node.valueOfJSConstant(m_codeBlock));
+ return speculationFromValue(node.valueOfJSConstant(m_codeBlock));
}
bool addShouldSpeculateInteger(Node& add)
@@ -258,6 +258,13 @@ public:
{
return at(nodeIndex).isBooleanConstant(m_codeBlock);
}
+ bool isCellConstant(NodeIndex nodeIndex)
+ {
+ if (!isJSConstant(nodeIndex))
+ return false;
+ JSValue value = valueOfJSConstant(nodeIndex);
+ return value.isCell() && !!value;
+ }
bool isFunctionConstant(NodeIndex nodeIndex)
{
if (!isJSConstant(nodeIndex))
@@ -310,6 +317,11 @@ public:
return &m_structureTransitionData.last();
}
+ JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
+ {
+ return m_codeBlock->globalObjectFor(codeOrigin);
+ }
+
ExecutableBase* executableFor(InlineCallFrame* inlineCallFrame)
{
if (!inlineCallFrame)
@@ -424,17 +436,17 @@ public:
bool isPredictedNumerical(Node& node)
{
- PredictedType left = at(node.child1()).prediction();
- PredictedType right = at(node.child2()).prediction();
- return isNumberPrediction(left) && isNumberPrediction(right);
+ SpeculatedType left = at(node.child1()).prediction();
+ SpeculatedType right = at(node.child2()).prediction();
+ return isNumberSpeculation(left) && isNumberSpeculation(right);
}
bool byValIsPure(Node& node)
{
return at(node.child2()).shouldSpeculateInteger()
&& ((node.op() == PutByVal || node.op() == PutByValAlias)
- ? isActionableMutableArrayPrediction(at(node.child1()).prediction())
- : isActionableArrayPrediction(at(node.child1()).prediction()));
+ ? isActionableMutableArraySpeculation(at(node.child1()).prediction())
+ : isActionableArraySpeculation(at(node.child1()).prediction()));
}
bool clobbersWorld(Node& node)
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index 54b5aaee6..561f51615 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -44,7 +44,11 @@ void JITCompiler::linkOSRExits()
{
for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
OSRExit& exit = codeBlock()->osrExit(i);
- exit.m_check.initialJump().link(this);
+ ASSERT(!exit.m_check.isSet() == (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max()));
+ if (exit.m_watchpointIndex == std::numeric_limits<unsigned>::max())
+ exit.m_check.initialJump().link(this);
+ else
+ codeBlock()->watchpoint(exit.m_watchpointIndex).setDestination(label());
jitAssertHasValidCallFrame();
store32(TrustedImm32(i), &globalData()->osrExitIndex);
exit.m_check.switchToLateJump(patchableJump());
@@ -124,16 +128,14 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
for (unsigned i = 0; i < m_calls.size(); ++i)
linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
- if (m_codeBlock->needsCallReturnIndices()) {
- m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
- for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
- unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
- CodeOrigin codeOrigin = m_exceptionChecks[i].m_codeOrigin;
- while (codeOrigin.inlineCallFrame)
- codeOrigin = codeOrigin.inlineCallFrame->caller;
- unsigned exceptionInfo = codeOrigin.bytecodeIndex;
- m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
- }
+ m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+ CodeOrigin codeOrigin = m_exceptionChecks[i].m_codeOrigin;
+ while (codeOrigin.inlineCallFrame)
+ codeOrigin = codeOrigin.inlineCallFrame->caller;
+ unsigned exceptionInfo = codeOrigin.bytecodeIndex;
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
}
Vector<CodeOriginAtCallReturnOffset>& codeOrigins = m_codeBlock->codeOrigins();
@@ -190,6 +192,8 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
OSRExit& exit = codeBlock()->osrExit(i);
linkBuffer.link(exit.m_check.lateJump(), target);
exit.m_check.correctLateJump(linkBuffer);
+ if (exit.m_watchpointIndex != std::numeric_limits<unsigned>::max())
+ codeBlock()->watchpoint(exit.m_watchpointIndex).correctLabels(linkBuffer);
}
codeBlock()->shrinkToFit(CodeBlock::LateShrink);
@@ -216,7 +220,9 @@ bool JITCompiler::compile(JITCode& entry)
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
- entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+ entry = JITCode(
+ FINALIZE_CODE(linkBuffer, ("DFG program/eval CodeBlock %p", m_codeBlock)),
+ JITCode::DFGJIT);
return true;
}
@@ -298,7 +304,9 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
entryWithArityCheck = linkBuffer.locationOf(arityCheck);
- entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+ entry = JITCode(
+ FINALIZE_CODE(linkBuffer, ("DFG function CodeBlock %p", m_codeBlock)),
+ JITCode::DFGJIT);
return true;
}
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index d3ff3be07..9d69ec9f3 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -260,9 +260,9 @@ public:
}
// Helper methods to get predictions
- PredictedType getPrediction(Node& node) { return node.prediction(); }
- PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); }
- PredictedType getPrediction(Edge nodeUse) { return getPrediction(nodeUse.index()); }
+ SpeculatedType getSpeculation(Node& node) { return node.prediction(); }
+ SpeculatedType getSpeculation(NodeIndex nodeIndex) { return getSpeculation(graph()[nodeIndex]); }
+ SpeculatedType getSpeculation(Edge nodeUse) { return getSpeculation(nodeUse.index()); }
#if USE(JSVALUE32_64)
void* addressOfDoubleConstant(NodeIndex nodeIndex)
@@ -288,6 +288,12 @@ public:
m_codeBlock->appendWeakReference(target);
}
+ void addWeakReferences(const StructureSet& structureSet)
+ {
+ for (unsigned i = structureSet.size(); i--;)
+ addWeakReference(structureSet[i]);
+ }
+
void addWeakReferenceTransition(JSCell* codeOrigin, JSCell* from, JSCell* to)
{
m_codeBlock->appendWeakReferenceTransition(codeOrigin, from, to);
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 12ebba823..64e6fe097 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -39,7 +39,7 @@
#include "DFGVariableAccessData.h"
#include "JSValue.h"
#include "Operands.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "ValueProfile.h"
namespace JSC { namespace DFG {
@@ -82,7 +82,7 @@ struct Node {
, children(AdjacencyList::Fixed, child1, child2, child3)
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -95,7 +95,7 @@ struct Node {
, m_virtualRegister(InvalidVirtualRegister)
, m_refCount(0)
, m_opInfo(imm.m_value)
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -109,7 +109,7 @@ struct Node {
, m_refCount(0)
, m_opInfo(imm1.m_value)
, m_opInfo2(safeCast<unsigned>(imm2.m_value))
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
@@ -123,7 +123,7 @@ struct Node {
, m_refCount(0)
, m_opInfo(imm1.m_value)
, m_opInfo2(safeCast<unsigned>(imm2.m_value))
- , m_prediction(PredictNone)
+ , m_prediction(SpecNone)
{
setOpAndDefaultFlags(op);
ASSERT(m_flags & NodeHasVarArgs);
@@ -421,7 +421,7 @@ struct Node {
bool hasVarNumber()
{
- return op() == GetGlobalVar || op() == PutGlobalVar || op() == GetScopedVar || op() == PutScopedVar;
+ return op() == GetScopedVar || op() == PutScopedVar;
}
unsigned varNumber()
@@ -429,6 +429,27 @@ struct Node {
ASSERT(hasVarNumber());
return m_opInfo;
}
+
+ bool hasIdentifierNumberForCheck()
+ {
+ return op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck;
+ }
+
+ unsigned identifierNumberForCheck()
+ {
+ ASSERT(hasIdentifierNumberForCheck());
+ return m_opInfo2;
+ }
+
+ bool hasRegisterPointer()
+ {
+ return op() == GetGlobalVar || op() == PutGlobalVar || op() == GlobalVarWatchpoint || op() == PutGlobalVarCheck;
+ }
+
+ WriteBarrier<Unknown>* registerPointer()
+ {
+ return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
+ }
bool hasScopeChainDepth()
{
@@ -584,17 +605,17 @@ struct Node {
}
}
- PredictedType getHeapPrediction()
+ SpeculatedType getHeapPrediction()
{
ASSERT(hasHeapPrediction());
- return static_cast<PredictedType>(m_opInfo2);
+ return static_cast<SpeculatedType>(m_opInfo2);
}
- bool predictHeap(PredictedType prediction)
+ bool predictHeap(SpeculatedType prediction)
{
ASSERT(hasHeapPrediction());
- return mergePrediction(m_opInfo2, prediction);
+ return mergeSpeculation(m_opInfo2, prediction);
}
bool hasFunctionCheckData()
@@ -630,6 +651,17 @@ struct Node {
return *reinterpret_cast<StructureSet*>(m_opInfo);
}
+ bool hasStructure()
+ {
+ return op() == StructureTransitionWatchpoint;
+ }
+
+ Structure* structure()
+ {
+ ASSERT(hasStructure());
+ return reinterpret_cast<Structure*>(m_opInfo);
+ }
+
bool hasStorageAccessData()
{
return op() == GetByOffset || op() == PutByOffset;
@@ -682,6 +714,17 @@ struct Node {
ASSERT(m_virtualRegister == InvalidVirtualRegister);
m_virtualRegister = virtualRegister;
}
+
+ bool hasArgumentPositionStart()
+ {
+ return op() == InlineStart;
+ }
+
+ unsigned argumentPositionStart()
+ {
+ ASSERT(hasArgumentPositionStart());
+ return m_opInfo;
+ }
bool shouldGenerate()
{
@@ -756,114 +799,114 @@ struct Node {
return children.numChildren();
}
- PredictedType prediction()
+ SpeculatedType prediction()
{
return m_prediction;
}
- bool predict(PredictedType prediction)
+ bool predict(SpeculatedType prediction)
{
- return mergePrediction(m_prediction, prediction);
+ return mergeSpeculation(m_prediction, prediction);
}
bool shouldSpeculateInteger()
{
- return isInt32Prediction(prediction());
+ return isInt32Speculation(prediction());
}
bool shouldSpeculateDouble()
{
- return isDoublePrediction(prediction());
+ return isDoubleSpeculation(prediction());
}
bool shouldSpeculateNumber()
{
- return isNumberPrediction(prediction());
+ return isNumberSpeculation(prediction());
}
bool shouldSpeculateBoolean()
{
- return isBooleanPrediction(prediction());
+ return isBooleanSpeculation(prediction());
}
bool shouldSpeculateFinalObject()
{
- return isFinalObjectPrediction(prediction());
+ return isFinalObjectSpeculation(prediction());
}
bool shouldSpeculateFinalObjectOrOther()
{
- return isFinalObjectOrOtherPrediction(prediction());
+ return isFinalObjectOrOtherSpeculation(prediction());
}
bool shouldSpeculateArray()
{
- return isArrayPrediction(prediction());
+ return isArraySpeculation(prediction());
}
bool shouldSpeculateArguments()
{
- return isArgumentsPrediction(prediction());
+ return isArgumentsSpeculation(prediction());
}
bool shouldSpeculateInt8Array()
{
- return isInt8ArrayPrediction(prediction());
+ return isInt8ArraySpeculation(prediction());
}
bool shouldSpeculateInt16Array()
{
- return isInt16ArrayPrediction(prediction());
+ return isInt16ArraySpeculation(prediction());
}
bool shouldSpeculateInt32Array()
{
- return isInt32ArrayPrediction(prediction());
+ return isInt32ArraySpeculation(prediction());
}
bool shouldSpeculateUint8Array()
{
- return isUint8ArrayPrediction(prediction());
+ return isUint8ArraySpeculation(prediction());
}
bool shouldSpeculateUint8ClampedArray()
{
- return isUint8ClampedArrayPrediction(prediction());
+ return isUint8ClampedArraySpeculation(prediction());
}
bool shouldSpeculateUint16Array()
{
- return isUint16ArrayPrediction(prediction());
+ return isUint16ArraySpeculation(prediction());
}
bool shouldSpeculateUint32Array()
{
- return isUint32ArrayPrediction(prediction());
+ return isUint32ArraySpeculation(prediction());
}
bool shouldSpeculateFloat32Array()
{
- return isFloat32ArrayPrediction(prediction());
+ return isFloat32ArraySpeculation(prediction());
}
bool shouldSpeculateFloat64Array()
{
- return isFloat64ArrayPrediction(prediction());
+ return isFloat64ArraySpeculation(prediction());
}
bool shouldSpeculateArrayOrOther()
{
- return isArrayOrOtherPrediction(prediction());
+ return isArrayOrOtherSpeculation(prediction());
}
bool shouldSpeculateObject()
{
- return isObjectPrediction(prediction());
+ return isObjectSpeculation(prediction());
}
bool shouldSpeculateCell()
{
- return isCellPrediction(prediction());
+ return isCellSpeculation(prediction());
}
static bool shouldSpeculateInteger(Node& op1, Node& op2)
@@ -921,7 +964,7 @@ private:
uintptr_t m_opInfo;
unsigned m_opInfo2;
// The prediction ascribed to this node after propagation.
- PredictedType m_prediction;
+ SpeculatedType m_prediction;
};
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 743f87955..4671f6b6c 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -118,6 +118,18 @@ namespace JSC { namespace DFG {
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
+ /* Transition watchpoints are a contract between the party setting the watchpoint */\
+ /* and the runtime system, where the party promises that the child object once had */\
+ /* the structure being watched, and the runtime system in turn promises that the */\
+ /* watchpoint will be turned into an OSR exit if any object with that structure */\
+ /* ever transitions to a different structure. Hence, the child object must have */\
+ /* previously had a CheckStructure executed on it or we're dealing with an object */\
+ /* constant (WeakJSConstant) and the object was known to have that structure at */\
+ /* compile-time. In the latter case this means that no structure checks have to be */\
+ /* performed for this object by JITted code. In the former case this means that*/\
+ /* the object's structure does not need to be rechecked due to side-effecting */\
+ /* (clobbering) operations. */\
+ macro(StructureTransitionWatchpoint, NodeMustGenerate) \
macro(PutStructure, NodeMustGenerate) \
macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
macro(GetPropertyStorage, NodeResultStorage) \
@@ -141,6 +153,8 @@ namespace JSC { namespace DFG {
macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
macro(PutGlobalVar, NodeMustGenerate) \
+ macro(GlobalVarWatchpoint, NodeMustGenerate) \
+ macro(PutGlobalVarCheck, NodeMustGenerate) \
macro(CheckFunction, NodeMustGenerate) \
\
/* Optimizations for array mutation. */\
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
index bcb98a1ed..d0e0de9da 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
@@ -51,6 +51,7 @@ OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAVal
, m_codeOrigin(jit->m_codeOriginForOSR)
, m_codeOriginForExitProfile(m_codeOrigin)
, m_recoveryIndex(recoveryIndex)
+ , m_watchpointIndex(std::numeric_limits<unsigned>::max())
, m_kind(kind)
, m_count(0)
, m_arguments(jit->m_arguments.size())
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.h b/Source/JavaScriptCore/dfg/DFGOSRExit.h
index 841fdddb3..683f260f1 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExit.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExit.h
@@ -96,6 +96,7 @@ struct OSRExit {
CodeOrigin m_codeOriginForExitProfile;
unsigned m_recoveryIndex;
+ unsigned m_watchpointIndex;
ExitKind m_kind;
uint32_t m_count;
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
index 888a4a2c5..d46d59650 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
@@ -79,11 +79,11 @@ void compileOSRExit(ExecState* exec)
exitCompiler.compileExit(exit, recovery);
LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
- exit.m_code = patchBuffer.finalizeCode();
-
-#if DFG_ENABLE(DEBUG_VERBOSE)
- dataLog("OSR exit code at [%p, %p).\n", patchBuffer.debugAddress(), static_cast<char*>(patchBuffer.debugAddress()) + patchBuffer.debugSize());
-#endif
+ exit.m_code = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG OSR exit #%u (bc#%u, @%u, %s) from CodeBlock %p",
+ exitIndex, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex,
+ exitKindToString(exit.m_kind), codeBlock));
}
{
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
index 86345b0eb..ae29a92d5 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
@@ -78,7 +78,7 @@ private:
};
extern "C" {
-void DFG_OPERATION compileOSRExit(ExecState*);
+void DFG_OPERATION compileOSRExit(ExecState*) WTF_INTERNAL;
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
index d773cb4ac..09912b3e5 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
@@ -533,70 +533,6 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
}
}
- // 11) Create arguments if necessary and place them into the appropriate aliased
- // registers.
-
- if (haveArguments) {
- for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
- const ValueRecovery& recovery = exit.valueRecovery(index);
- if (recovery.technique() != ArgumentsThatWereNotCreated)
- continue;
- int operand = exit.operandForIndex(index);
- // Find the right inline call frame.
- InlineCallFrame* inlineCallFrame = 0;
- for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
- current;
- current = current->caller.inlineCallFrame) {
- if (current->stackOffset <= operand) {
- inlineCallFrame = current;
- break;
- }
- }
- int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
-
- m_jit.load32(AssemblyHelpers::payloadFor(argumentsRegister), GPRInfo::regT0);
- AssemblyHelpers::Jump haveArguments = m_jit.branch32(
- AssemblyHelpers::NotEqual,
- AssemblyHelpers::tagFor(argumentsRegister),
- AssemblyHelpers::TrustedImm32(JSValue::EmptyValueTag));
-
- if (inlineCallFrame) {
- m_jit.setupArgumentsWithExecState(
- AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateInlinedArguments)),
- GPRInfo::nonArgGPR0);
- } else {
- m_jit.setupArgumentsExecState();
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateArguments)),
- GPRInfo::nonArgGPR0);
- }
- m_jit.call(GPRInfo::nonArgGPR0);
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(argumentsRegister));
- m_jit.store32(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::payloadFor(argumentsRegister));
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.store32(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::payloadFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
-
- haveArguments.link(&m_jit);
- m_jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(operand));
- m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));
- }
- }
-
// 12) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
// that all new calls into this code will go to the new JIT, so the execute
// counter only affects call frames that performed OSR exit and call frames
@@ -635,14 +571,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
handleExitCounts(exit);
- // 13) Load the result of the last bytecode operation into regT0.
-
- if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
- m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
- m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
- }
-
- // 14) Fix call frame (s).
+ // 13) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
@@ -678,10 +607,83 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
+ // 14) Create arguments if necessary and place them into the appropriate aliased
+ // registers.
+
+ if (haveArguments) {
+ for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+ const ValueRecovery& recovery = exit.valueRecovery(index);
+ if (recovery.technique() != ArgumentsThatWereNotCreated)
+ continue;
+ int operand = exit.operandForIndex(index);
+ // Find the right inline call frame.
+ InlineCallFrame* inlineCallFrame = 0;
+ for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
+ current;
+ current = current->caller.inlineCallFrame) {
+ if (current->stackOffset <= operand) {
+ inlineCallFrame = current;
+ break;
+ }
+ }
+ int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
+
+ m_jit.load32(AssemblyHelpers::payloadFor(argumentsRegister), GPRInfo::regT0);
+ AssemblyHelpers::Jump haveArguments = m_jit.branch32(
+ AssemblyHelpers::NotEqual,
+ AssemblyHelpers::tagFor(argumentsRegister),
+ AssemblyHelpers::TrustedImm32(JSValue::EmptyValueTag));
+
+ if (inlineCallFrame) {
+ m_jit.setupArgumentsWithExecState(
+ AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateInlinedArguments)),
+ GPRInfo::nonArgGPR0);
+ } else {
+ m_jit.setupArgumentsExecState();
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateArguments)),
+ GPRInfo::nonArgGPR0);
+ }
+ m_jit.call(GPRInfo::nonArgGPR0);
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(argumentsRegister));
+ m_jit.store32(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::payloadFor(argumentsRegister));
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.store32(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::payloadFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
+
+ haveArguments.link(&m_jit);
+ m_jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(operand));
+ m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));
+ }
+ }
+
+ // 15) Load the result of the last bytecode operation into regT0.
+
+ if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
+ m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+ m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
+ }
+
+ // 16) Adjust the call frame pointer.
+
if (exit.m_codeOrigin.inlineCallFrame)
m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
- // 15) Jump into the corresponding baseline JIT code.
+ // 17) Jump into the corresponding baseline JIT code.
CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
index 22b236115..33ba69a35 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
@@ -511,58 +511,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
}
}
- // 13) Create arguments if necessary and place them into the appropriate aliased
- // registers.
-
- if (haveArguments) {
- for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
- const ValueRecovery& recovery = exit.valueRecovery(index);
- if (recovery.technique() != ArgumentsThatWereNotCreated)
- continue;
- int operand = exit.operandForIndex(index);
- // Find the right inline call frame.
- InlineCallFrame* inlineCallFrame = 0;
- for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
- current;
- current = current->caller.inlineCallFrame) {
- if (current->stackOffset <= operand) {
- inlineCallFrame = current;
- break;
- }
- }
- int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
-
- m_jit.loadPtr(AssemblyHelpers::addressFor(argumentsRegister), GPRInfo::regT0);
- AssemblyHelpers::Jump haveArguments = m_jit.branchTestPtr(
- AssemblyHelpers::NonZero, GPRInfo::regT0);
-
- if (inlineCallFrame) {
- m_jit.setupArgumentsWithExecState(
- AssemblyHelpers::TrustedImmPtr(inlineCallFrame));
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateInlinedArguments)),
- GPRInfo::nonArgGPR0);
- } else {
- m_jit.setupArgumentsExecState();
- m_jit.move(
- AssemblyHelpers::TrustedImmPtr(
- bitwise_cast<void*>(operationCreateArguments)),
- GPRInfo::nonArgGPR0);
- }
- m_jit.call(GPRInfo::nonArgGPR0);
- m_jit.storePtr(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(argumentsRegister));
- m_jit.storePtr(
- GPRInfo::returnValueGPR,
- AssemblyHelpers::addressFor(unmodifiedArgumentsRegister(argumentsRegister)));
- m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
-
- haveArguments.link(&m_jit);
- m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
- }
- }
-
- // 14) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
+ // 13) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
// that all new calls into this code will go to the new JIT, so the execute
// counter only affects call frames that performed OSR exit and call frames
// that were still executing the old JIT at the time of another call frame's
@@ -600,12 +549,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
handleExitCounts(exit);
- // 15) Load the result of the last bytecode operation into regT0.
-
- if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
- m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
-
- // 16) Fix call frame(s).
+ // 14) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
@@ -638,10 +582,63 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
+ // 15) Create arguments if necessary and place them into the appropriate aliased
+ // registers.
+
+ if (haveArguments) {
+ for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+ const ValueRecovery& recovery = exit.valueRecovery(index);
+ if (recovery.technique() != ArgumentsThatWereNotCreated)
+ continue;
+ int operand = exit.operandForIndex(index);
+ // Find the right inline call frame.
+ InlineCallFrame* inlineCallFrame = 0;
+ for (InlineCallFrame* current = exit.m_codeOrigin.inlineCallFrame;
+ current;
+ current = current->caller.inlineCallFrame) {
+ if (current->stackOffset <= operand) {
+ inlineCallFrame = current;
+ break;
+ }
+ }
+ int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
+
+ m_jit.loadPtr(AssemblyHelpers::addressFor(argumentsRegister), GPRInfo::regT0);
+ AssemblyHelpers::Jump haveArguments = m_jit.branchTestPtr(
+ AssemblyHelpers::NonZero, GPRInfo::regT0);
+
+ if (inlineCallFrame) {
+ m_jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT0);
+ m_jit.setupArguments(GPRInfo::regT0);
+ } else
+ m_jit.setupArgumentsExecState();
+ m_jit.move(
+ AssemblyHelpers::TrustedImmPtr(
+ bitwise_cast<void*>(operationCreateArguments)),
+ GPRInfo::nonArgGPR0);
+ m_jit.call(GPRInfo::nonArgGPR0);
+ m_jit.storePtr(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(argumentsRegister));
+ m_jit.storePtr(
+ GPRInfo::returnValueGPR,
+ AssemblyHelpers::addressFor(unmodifiedArgumentsRegister(argumentsRegister)));
+ m_jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.
+
+ haveArguments.link(&m_jit);
+ m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
+ }
+ }
+
+ // 16) Load the result of the last bytecode operation into regT0.
+
+ if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
+ m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+
+ // 17) Adjust the call frame pointer.
+
if (exit.m_codeOrigin.inlineCallFrame)
m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
- // 17) Jump into the corresponding baseline JIT code.
+ // 18) Jump into the corresponding baseline JIT code.
CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index b5ac4601a..06a1cf883 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -51,7 +51,7 @@
HIDE_SYMBOL(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov (%rsp), %" STRINGIZE(register) "\n" \
- "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+ "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
@@ -68,7 +68,7 @@
SYMBOL_STRING(function) ":" "\n" \
"mov (%esp), %eax\n" \
"mov %eax, " STRINGIZE(offset) "(%esp)\n" \
- "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+ "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
@@ -87,7 +87,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov a2, lr" "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
@@ -100,7 +100,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov a4, lr" "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
@@ -123,7 +123,7 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
INSTRUCTION_STORE_RETURN_ADDRESS_EJI "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
@@ -136,25 +136,25 @@
".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "\n" \
- "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
);
#endif
#define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
-void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
-EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
-EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
#define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
-void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM; \
+void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
namespace JSC { namespace DFG {
@@ -924,6 +924,11 @@ void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
return virtualFor(execCallee, CodeForConstruct);
}
+void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet)
+{
+ watchpointSet->notifyWrite();
+}
+
EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* propertyName)
{
JSGlobalData* globalData = &exec->globalData();
@@ -1096,6 +1101,8 @@ void DFG_OPERATION operationTearOffInlinedArguments(
EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
{
+ // Here we can assume that the argumernts were created. Because otherwise the JIT code would
+ // have not made this call.
Identifier ident(&exec->globalData(), "length");
JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
PropertySlot slot(baseValue);
@@ -1104,8 +1111,29 @@ EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec, int32_
EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t argumentsRegister, int32_t index)
{
- return JSValue::encode(
- exec->uncheckedR(argumentsRegister).jsValue().get(exec, index));
+ JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
+
+ // If there are no arguments, and we're accessing out of bounds, then we have to create the
+ // arguments in case someone has installed a getter on a numeric property.
+ if (!argumentsValue)
+ exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->globalData(), exec);
+
+ return JSValue::encode(argumentsValue.get(exec, index));
+}
+
+EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(
+ ExecState* exec, int32_t argumentsRegister, InlineCallFrame* inlineCallFrame, int32_t index)
+{
+ JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
+
+ // If there are no arguments, and we're accessing out of bounds, then we have to create the
+ // arguments in case someone has installed a getter on a numeric property.
+ if (!argumentsValue) {
+ exec->uncheckedR(argumentsRegister) = argumentsValue =
+ Arguments::create(exec->globalData(), exec, inlineCallFrame);
+ }
+
+ return JSValue::encode(argumentsValue.get(exec, index));
}
JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
@@ -1241,7 +1269,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%r13), %r13\n"
"mov %r13, %rdi\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#elif CPU(X86)
asm (
@@ -1251,7 +1279,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%edi), %edi\n"
"mov %edi, 4(%esp)\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#elif CPU(ARM_THUMB2)
asm (
@@ -1264,7 +1292,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"ldr r5, [r5, #-40]" "\n"
"mov r0, r5" "\n"
- "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+ "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 03f198e9d..38166a83f 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -77,6 +77,7 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, vo
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZIcfZ)(ExecState*, int32_t, InlineCallFrame*, int32_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZZ)(ExecState*, int32_t, int32_t);
typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*);
typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
@@ -99,78 +100,81 @@ typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JS
typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*);
typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
-JSCell* DFG_OPERATION operationNewObject(ExecState*);
-JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor);
-EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
-EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
-EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty);
-EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*);
-EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*);
-EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*);
-EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*);
-EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*);
-EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*);
-EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue);
-EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t);
-EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t);
-EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t);
-EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*);
-void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
-void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
-EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*);
-EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*);
-EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*);
-void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
-void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+JSCell* DFG_OPERATION operationNewObject(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
+void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
+void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
// These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
-size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*);
-size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
-void* DFG_OPERATION operationVirtualCall(ExecState*);
-void* DFG_OPERATION operationLinkCall(ExecState*);
-void* DFG_OPERATION operationVirtualConstruct(ExecState*);
-void* DFG_OPERATION operationLinkConstruct(ExecState*);
-JSCell* DFG_OPERATION operationCreateActivation(ExecState*);
-JSCell* DFG_OPERATION operationCreateArguments(ExecState*);
-JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*);
-void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister);
-void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*);
-void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*);
-EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t);
-EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int32_t);
-JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*);
-JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*);
-double DFG_OPERATION operationFModOnInts(int32_t, int32_t);
-size_t DFG_OPERATION operationIsObject(EncodedJSValue);
-size_t DFG_OPERATION operationIsFunction(EncodedJSValue);
+size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+void* DFG_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationVirtualConstruct(ExecState*) WTF_INTERNAL;
+void* DFG_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateActivation(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*) WTF_INTERNAL;
+void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(ExecState*, int32_t, InlineCallFrame*, int32_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int32_t) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*) WTF_INTERNAL;
+double DFG_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
+size_t DFG_OPERATION operationIsObject(EncodedJSValue) WTF_INTERNAL;
+size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL;
// This method is used to lookup an exception hander, keyed by faultLocation, which is
// the return location from one of the calls out to one of the helper operations above.
@@ -210,17 +214,17 @@ inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler)
return createDFGHandler(exec, handler).u.encoded;
}
#endif
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t);
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*);
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t) WTF_INTERNAL;
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*) WTF_INTERNAL;
// These operations implement the implicitly called ToInt32, ToNumber, and ToBoolean conversions from ES5.
-double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue);
+double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue) WTF_INTERNAL;
// This conversion returns an int32_t within a size_t such that the value is zero extended to fill the register.
-size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState*, EncodedJSValue);
-size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue);
+size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState*, EncodedJSValue) WTF_INTERNAL;
+size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue) WTF_INTERNAL;
#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
-void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*);
+void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*) WTF_INTERNAL;
#endif
} // extern "C"
diff --git a/Source/JavaScriptCore/dfg/DFGPhase.cpp b/Source/JavaScriptCore/dfg/DFGPhase.cpp
index ecf669704..f97c49e31 100644
--- a/Source/JavaScriptCore/dfg/DFGPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,7 +39,9 @@ void Phase::beginPhase()
dataLog("Graph before %s:\n", m_name);
m_graph.dump();
}
+#endif
+#if DFG_ENABLE(PER_PHASE_VALIDATION)
void Phase::endPhase()
{
validate(m_graph, DumpGraph);
diff --git a/Source/JavaScriptCore/dfg/DFGPhase.h b/Source/JavaScriptCore/dfg/DFGPhase.h
index 6d13bcd25..53055a215 100644
--- a/Source/JavaScriptCore/dfg/DFGPhase.h
+++ b/Source/JavaScriptCore/dfg/DFGPhase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -65,11 +65,14 @@ private:
// Call these hooks when starting and finishing.
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
void beginPhase();
- void endPhase();
-#else // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+#else
void beginPhase() { }
+#endif
+#if DFG_ENABLE(PER_PHASE_VALIDATION)
+ void endPhase();
+#else
void endPhase() { }
-#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+#endif
};
template<typename PhaseType>
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 75f0b7a74..bcb79a96a 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -82,20 +82,20 @@ public:
}
private:
- bool setPrediction(PredictedType prediction)
+ bool setPrediction(SpeculatedType prediction)
{
ASSERT(m_graph[m_compileIndex].hasResult());
// setPrediction() is used when we know that there is no way that we can change
// our minds about what the prediction is going to be. There is no semantic
- // difference between setPrediction() and mergePrediction() other than the
+ // difference between setPrediction() and mergeSpeculation() other than the
// increased checking to validate this property.
- ASSERT(m_graph[m_compileIndex].prediction() == PredictNone || m_graph[m_compileIndex].prediction() == prediction);
+ ASSERT(m_graph[m_compileIndex].prediction() == SpecNone || m_graph[m_compileIndex].prediction() == prediction);
return m_graph[m_compileIndex].predict(prediction);
}
- bool mergePrediction(PredictedType prediction)
+ bool mergePrediction(SpeculatedType prediction)
{
ASSERT(m_graph[m_compileIndex].hasResult());
@@ -134,13 +134,13 @@ private:
switch (op) {
case JSConstant:
case WeakJSConstant: {
- changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
+ changed |= setPrediction(speculationFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
break;
}
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
- PredictedType prediction = variableAccessData->prediction();
+ SpeculatedType prediction = variableAccessData->prediction();
if (prediction)
changed |= mergePrediction(prediction);
@@ -168,7 +168,7 @@ private:
case BitRShift:
case BitLShift:
case BitURShift: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -177,7 +177,7 @@ private:
}
case ValueToInt32: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
flags |= NodeUsedAsInt;
flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -205,22 +205,22 @@ private:
}
case StringCharCodeAt: {
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
}
case ArithMod: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
flags |= NodeUsedAsValue;
@@ -231,29 +231,29 @@ private:
case UInt32ToNumber: {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictNumber);
+ changed |= mergePrediction(SpecNumber);
changed |= m_graph[node.child1()].mergeFlags(flags);
break;
}
case ValueAdd: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isNumberPrediction(left) && isNumberPrediction(right)) {
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
- } else if (!(left & PredictNumber) || !(right & PredictNumber)) {
+ changed |= mergePrediction(SpecDouble);
+ } else if (!(left & SpecNumber) || !(right & SpecNumber)) {
// left or right is definitely something other than a number.
- changed |= mergePrediction(PredictString);
+ changed |= mergePrediction(SpecString);
} else
- changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
+ changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
}
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
@@ -265,14 +265,14 @@ private:
}
case ArithAdd: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
@@ -284,14 +284,14 @@ private:
}
case ArithSub: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.addShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
@@ -305,9 +305,9 @@ private:
case ArithNegate:
if (m_graph[node.child1()].prediction()) {
if (m_graph.negateShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -315,15 +315,15 @@ private:
case ArithMin:
case ArithMax: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
flags |= NodeUsedAsNumber;
@@ -333,14 +333,14 @@ private:
}
case ArithMul: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
if (m_graph.mulShouldSpeculateInteger(node))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
// As soon as a multiply happens, we can easily end up in the part
@@ -355,15 +355,15 @@ private:
}
case ArithDiv: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isInt32Prediction(mergePredictions(left, right))
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(PredictInt32);
+ changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
}
// As soon as a multiply happens, we can easily end up in the part
@@ -378,17 +378,17 @@ private:
}
case ArithSqrt: {
- changed |= setPrediction(PredictDouble);
+ changed |= setPrediction(SpecDouble);
changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue);
break;
}
case ArithAbs: {
- PredictedType child = m_graph[node.child1()].prediction();
+ SpeculatedType child = m_graph[node.child1()].prediction();
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(child);
else
- changed |= setPrediction(PredictDouble);
+ changed |= setPrediction(SpecDouble);
flags &= ~NodeNeedsNegZero;
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -409,7 +409,7 @@ private:
case IsString:
case IsObject:
case IsFunction: {
- changed |= setPrediction(PredictBoolean);
+ changed |= setPrediction(SpecBoolean);
changed |= mergeDefaultFlags(node);
break;
}
@@ -428,7 +428,7 @@ private:
case GetByVal: {
if (m_graph[node.child1()].shouldSpeculateFloat32Array()
|| m_graph[node.child1()].shouldSpeculateFloat64Array())
- changed |= mergePrediction(PredictDouble);
+ changed |= mergePrediction(SpecDouble);
else
changed |= mergePrediction(node.getHeapPrediction());
@@ -444,13 +444,13 @@ private:
}
case GetMyArgumentsLengthSafe: {
- changed |= setPrediction(PredictInt32);
+ changed |= setPrediction(SpecInt32);
break;
}
case GetPropertyStorage:
case GetIndexedPropertyStorage: {
- changed |= setPrediction(PredictOther);
+ changed |= setPrediction(SpecOther);
changed |= mergeDefaultFlags(node);
break;
}
@@ -474,11 +474,11 @@ private:
}
case ConvertThis: {
- PredictedType prediction = m_graph[node.child1()].prediction();
+ SpeculatedType prediction = m_graph[node.child1()].prediction();
if (prediction) {
- if (prediction & ~PredictObjectMask) {
- prediction &= PredictObjectMask;
- prediction = mergePredictions(prediction, PredictObjectOther);
+ if (prediction & ~SpecObjectMask) {
+ prediction &= SpecObjectMask;
+ prediction = mergeSpeculations(prediction, SpecObjectOther);
}
changed |= mergePrediction(prediction);
}
@@ -491,7 +491,8 @@ private:
break;
}
- case PutGlobalVar: {
+ case PutGlobalVar:
+ case PutGlobalVarCheck: {
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
break;
}
@@ -501,30 +502,30 @@ private:
case ResolveBase:
case ResolveBaseStrictPut:
case ResolveGlobal: {
- PredictedType prediction = node.getHeapPrediction();
+ SpeculatedType prediction = node.getHeapPrediction();
changed |= mergePrediction(prediction);
break;
}
case GetScopeChain: {
- changed |= setPrediction(PredictCellOther);
+ changed |= setPrediction(SpecCellOther);
break;
}
case GetCallee: {
- changed |= setPrediction(PredictFunction);
+ changed |= setPrediction(SpecFunction);
break;
}
case CreateThis:
case NewObject: {
- changed |= setPrediction(PredictFinalObject);
+ changed |= setPrediction(SpecFinalObject);
changed |= mergeDefaultFlags(node);
break;
}
case NewArray: {
- changed |= setPrediction(PredictArray);
+ changed |= setPrediction(SpecArray);
for (unsigned childIdx = node.firstChild();
childIdx < node.firstChild() + node.numChildren();
++childIdx) {
@@ -535,24 +536,24 @@ private:
}
case NewArrayBuffer: {
- changed |= setPrediction(PredictArray);
+ changed |= setPrediction(SpecArray);
break;
}
case NewRegexp: {
- changed |= setPrediction(PredictObjectOther);
+ changed |= setPrediction(SpecObjectOther);
break;
}
case StringCharAt: {
- changed |= setPrediction(PredictString);
+ changed |= setPrediction(SpecString);
changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
}
case StrCat: {
- changed |= setPrediction(PredictString);
+ changed |= setPrediction(SpecString);
for (unsigned childIdx = node.firstChild();
childIdx < node.firstChild() + node.numChildren();
++childIdx)
@@ -561,20 +562,20 @@ private:
}
case ToPrimitive: {
- PredictedType child = m_graph[node.child1()].prediction();
+ SpeculatedType child = m_graph[node.child1()].prediction();
if (child) {
- if (isObjectPrediction(child)) {
+ if (isObjectSpeculation(child)) {
// I'd love to fold this case into the case below, but I can't, because
- // removing PredictObjectMask from something that only has an object
- // prediction and nothing else means we have an ill-formed PredictedType
+ // removing SpecObjectMask from something that only has an object
+ // prediction and nothing else means we have an ill-formed SpeculatedType
// (strong predict-none). This should be killed once we remove all traces
// of static (aka weak) predictions.
- changed |= mergePrediction(PredictString);
- } else if (child & PredictObjectMask) {
+ changed |= mergePrediction(SpecString);
+ } else if (child & SpecObjectMask) {
// Objects get turned into strings. So if the input has hints of objectness,
// the output will have hinsts of stringiness.
changed |= mergePrediction(
- mergePredictions(child & ~PredictObjectMask, PredictString));
+ mergeSpeculations(child & ~SpecObjectMask, SpecString));
} else
changed |= mergePrediction(child);
}
@@ -583,21 +584,21 @@ private:
}
case CreateActivation: {
- changed |= setPrediction(PredictObjectOther);
+ changed |= setPrediction(SpecObjectOther);
break;
}
case CreateArguments: {
// At this stage we don't try to predict whether the arguments are ours or
// someone else's. We could, but we don't, yet.
- changed |= setPrediction(PredictArguments);
+ changed |= setPrediction(SpecArguments);
break;
}
case NewFunction:
case NewFunctionNoCheck:
case NewFunctionExpression: {
- changed |= setPrediction(PredictFunction);
+ changed |= setPrediction(SpecFunction);
break;
}
@@ -663,12 +664,14 @@ private:
case ForceOSRExit:
case SetArgument:
case CheckStructure:
+ case StructureTransitionWatchpoint:
case CheckFunction:
case PutStructure:
case TearOffActivation:
case TearOffArguments:
case CheckNumber:
case CheckArgumentsNotCreated:
+ case GlobalVarWatchpoint:
changed |= mergeDefaultFlags(node);
break;
@@ -689,7 +692,7 @@ private:
}
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("%s\n", predictionToString(m_graph[m_compileIndex].prediction()));
+ dataLog("%s\n", speculationToString(m_graph[m_compileIndex].prediction()));
#endif
m_changed |= changed;
@@ -784,12 +787,12 @@ private:
case ValueAdd:
case ArithAdd:
case ArithSub: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !m_graph.addShouldSpeculateInteger(node))
ballot = VariableAccessData::VoteDouble;
else
@@ -801,12 +804,12 @@ private:
}
case ArithMul: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !m_graph.mulShouldSpeculateInteger(node))
ballot = VariableAccessData::VoteDouble;
else
@@ -821,12 +824,12 @@ private:
case ArithMax:
case ArithMod:
case ArithDiv: {
- PredictedType left = m_graph[node.child1()].prediction();
- PredictedType right = m_graph[node.child2()].prediction();
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
VariableAccessData::Ballot ballot;
- if (isNumberPrediction(left) && isNumberPrediction(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()])
&& node.canSpeculateInteger()))
ballot = VariableAccessData::VoteDouble;
@@ -854,10 +857,10 @@ private:
break;
case SetLocal: {
- PredictedType prediction = m_graph[node.child1()].prediction();
- if (isDoublePrediction(prediction))
+ SpeculatedType prediction = m_graph[node.child1()].prediction();
+ if (isDoubleSpeculation(prediction))
node.variableAccessData()->vote(VariableAccessData::VoteDouble);
- else if (!isNumberPrediction(prediction) || isInt32Prediction(prediction))
+ else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
node.variableAccessData()->vote(VariableAccessData::VoteValue);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 794538184..9c3391be5 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -155,7 +155,10 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu
linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG prototype chain access stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), successLabel.executableAddress()));
}
static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
@@ -206,7 +209,11 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
- stubInfo.stubRoutine = patchBuffer.finalizeCode();
+ stubInfo.stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG GetById array length stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
RepatchBuffer repatchBuffer(codeBlock);
repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
@@ -261,7 +268,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdProtoBuildList);
- stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain);
+ stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain, count, true);
return true;
}
@@ -405,7 +412,11 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
}
- MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
+ MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG GetById polymorphic list access for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
@@ -611,7 +622,11 @@ static void emitPutReplaceStub(
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
patchBuffer.link(failure, failureLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG PutById replace stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
}
static void emitPutTransitionStub(
@@ -649,6 +664,8 @@ static void emitPutTransitionStub(
needToRestoreScratch = true;
}
+ ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated());
+
failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(oldStructure)));
testPrototype(stubJit, scratchGPR, oldStructure->storedPrototype(), failureCases);
@@ -705,7 +722,11 @@ static void emitPutTransitionStub(
else
patchBuffer.link(failureCases, failureLabel);
- stubRoutine = patchBuffer.finalizeCode();
+ stubRoutine = FINALIZE_CODE(
+ patchBuffer,
+ ("DFG PutById transition stub for CodeBlock %p, return point %p",
+ exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+ stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
}
static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 9b82121b3..852f74387 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -292,7 +292,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUs
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+ if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchIfNotCell(valueGPR);
}
@@ -354,7 +354,7 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse,
#if ENABLE(GGC)
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+ if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchIfNotCell(valueGPR);
}
@@ -826,7 +826,7 @@ void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNod
jump(notTaken);
}
-void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -847,9 +847,9 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchN
GPRReg op1GPR = op1.gpr();
GPRReg op2GPR = op2.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
branchPtr(condition, op1GPR, op2GPR, taken);
@@ -909,32 +909,32 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa
at(node.child1()), at(node.child2()))) {
compilePeepHoleObjectEquality(
node, branchNodeIndex, &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
} else if (Node::shouldSpeculateArray(
at(node.child1()), at(node.child2()))) {
compilePeepHoleObjectEquality(
node, branchNodeIndex, &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
} else if (at(node.child1()).shouldSpeculateFinalObject()
&& at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child1(), node.child2(), branchNodeIndex,
- &JSFinalObject::s_info, isFinalObjectPrediction);
+ &JSFinalObject::s_info, isFinalObjectSpeculation);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
&& at(node.child2()).shouldSpeculateFinalObject()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child2(), node.child1(), branchNodeIndex,
- &JSFinalObject::s_info, isFinalObjectPrediction);
+ &JSFinalObject::s_info, isFinalObjectSpeculation);
} else if (at(node.child1()).shouldSpeculateArray()
&& at(node.child2()).shouldSpeculateArrayOrOther()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child1(), node.child2(), branchNodeIndex,
- &JSArray::s_info, isArrayPrediction);
+ &JSArray::s_info, isArraySpeculation);
} else if (at(node.child1()).shouldSpeculateArrayOrOther()
&& at(node.child2()).shouldSpeculateArray()) {
compilePeepHoleObjectToObjectOrOtherEquality(
node.child2(), node.child1(), branchNodeIndex,
- &JSArray::s_info, isArrayPrediction);
+ &JSArray::s_info, isArraySpeculation);
} else {
nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
return true;
@@ -991,7 +991,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
if (nodeIndex == NoNode || m_jit.codeBlock()->argumentIsCaptured(i))
m_arguments[i] = ValueSource(ValueInRegisterFile);
else
- m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+ m_arguments[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->prediction());
}
m_state.reset();
@@ -1011,7 +1011,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
m_variables[i] = ValueSource(DoubleInRegisterFile);
else
- m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
+ m_variables[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
}
m_lastSetOperand = std::numeric_limits<int>::max();
@@ -1040,8 +1040,29 @@ void SpeculativeJIT::compile(BasicBlock& block)
case InlineStart: {
InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
int argumentCountIncludingThis = inlineCallFrame->arguments.size();
+ unsigned argumentPositionStart = node.argumentPositionStart();
+ bool argumentsAreCaptured =
+ baselineCodeBlockForInlineCallFrame(inlineCallFrame)->argumentsAreCaptured();
for (int i = 0; i < argumentCountIncludingThis; ++i) {
- ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
+ ValueRecovery recovery;
+ if (argumentsAreCaptured)
+ recovery = ValueRecovery::alreadyInRegisterFile();
+ else {
+ ArgumentPosition& argumentPosition =
+ m_jit.graph().m_argumentPositions[argumentPositionStart + i];
+ ValueSource valueSource;
+ if (argumentPosition.shouldUseDoubleFormat())
+ valueSource = ValueSource(DoubleInRegisterFile);
+ else if (isInt32Speculation(argumentPosition.prediction()))
+ valueSource = ValueSource(Int32InRegisterFile);
+ else if (isArraySpeculation(argumentPosition.prediction()))
+ valueSource = ValueSource(CellInRegisterFile);
+ else if (isBooleanSpeculation(argumentPosition.prediction()))
+ valueSource = ValueSource(BooleanInRegisterFile);
+ else
+ valueSource = ValueSource(ValueInRegisterFile);
+ recovery = computeValueRecoveryFor(valueSource);
+ }
// The recovery should refer either to something that has already been
// stored into the register file at the right place, or to a constant,
// since the Arguments code isn't smart enough to handle anything else.
@@ -1051,12 +1072,15 @@ void SpeculativeJIT::compile(BasicBlock& block)
dataLog("\nRecovery for argument %d: ", i);
recovery.dump(WTF::dataFile());
#endif
- ASSERT(!i || (recovery.isAlreadyInRegisterFile() || recovery.isConstant()));
inlineCallFrame->arguments[i] = recovery;
}
break;
}
+ case WeakJSConstant:
+ m_jit.addWeakReference(node.weakConstant());
+ break;
+
default:
break;
}
@@ -1154,129 +1178,129 @@ void SpeculativeJIT::checkArgumentTypes()
VariableAccessData* variableAccessData = node.variableAccessData();
VirtualRegister virtualRegister = variableAccessData->local();
- PredictedType predictedType = variableAccessData->prediction();
+ SpeculatedType predictedType = variableAccessData->prediction();
JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
#if USE(JSVALUE64)
- if (isInt32Prediction(predictedType))
+ if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
- else if (isArrayPrediction(predictedType)) {
+ else if (isArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanPrediction(predictedType)) {
+ } else if (isBooleanSpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
- } else if (isInt8ArrayPrediction(predictedType)) {
+ } else if (isInt8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
- } else if (isInt16ArrayPrediction(predictedType)) {
+ } else if (isInt16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
- } else if (isInt32ArrayPrediction(predictedType)) {
+ } else if (isInt32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
- } else if (isUint8ArrayPrediction(predictedType)) {
+ } else if (isUint8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
- } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ } else if (isUint8ClampedArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
- } else if (isUint16ArrayPrediction(predictedType)) {
+ } else if (isUint16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
- } else if (isUint32ArrayPrediction(predictedType)) {
+ } else if (isUint32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
- } else if (isFloat32ArrayPrediction(predictedType)) {
+ } else if (isFloat32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
- } else if (isFloat64ArrayPrediction(predictedType)) {
+ } else if (isFloat64ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
}
#else
- if (isInt32Prediction(predictedType))
+ if (isInt32Speculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
- else if (isArrayPrediction(predictedType)) {
+ else if (isArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
- } else if (isBooleanPrediction(predictedType))
+ } else if (isBooleanSpeculation(predictedType))
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
- else if (isInt8ArrayPrediction(predictedType)) {
+ else if (isInt8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
- } else if (isInt16ArrayPrediction(predictedType)) {
+ } else if (isInt16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
- } else if (isInt32ArrayPrediction(predictedType)) {
+ } else if (isInt32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
- } else if (isUint8ArrayPrediction(predictedType)) {
+ } else if (isUint8ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
- } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ } else if (isUint8ClampedArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
- } else if (isUint16ArrayPrediction(predictedType)) {
+ } else if (isUint16ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
- } else if (isUint32ArrayPrediction(predictedType)) {
+ } else if (isUint32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
- } else if (isFloat32ArrayPrediction(predictedType)) {
+ } else if (isFloat32ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
- } else if (isFloat64ArrayPrediction(predictedType)) {
+ } else if (isFloat64ArraySpeculation(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
@@ -1506,8 +1530,8 @@ void SpeculativeJIT::compileGetCharCodeAt(Node& node)
GPRReg indexReg = index.gpr();
GPRReg storageReg = storage.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
- ASSERT(!(at(node.child1()).prediction() & PredictString));
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+ ASSERT(!(at(node.child1()).prediction() & SpecString));
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
return;
@@ -1545,8 +1569,8 @@ void SpeculativeJIT::compileGetByValOnString(Node& node)
GPRReg propertyReg = property.gpr();
GPRReg storageReg = storage.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
- ASSERT(!(at(node.child1()).prediction() & PredictString));
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+ ASSERT(!(at(node.child1()).prediction() & SpecString));
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
return;
@@ -1680,7 +1704,7 @@ void SpeculativeJIT::compileValueToInt32(Node& node)
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
// First, if we get here we have a double encoded as a JSValue
@@ -1717,7 +1741,7 @@ void SpeculativeJIT::compileValueToInt32(Node& node)
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
@@ -1829,7 +1853,7 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
}
#endif
- if (isInt32Prediction(m_state.forNode(node.child1()).m_type)) {
+ if (isInt32Speculation(m_state.forNode(node.child1()).m_type)) {
SpeculateIntegerOperand op1(this, node.child1());
FPRTemporary result(this);
m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
@@ -1850,9 +1874,11 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
JITCompiler::Jump isInteger = m_jit.branchPtr(
MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
- speculationCheck(
- BadType, JSValueRegs(op1GPR), node.child1(),
- m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+ speculationCheck(
+ BadType, JSValueRegs(op1GPR), node.child1(),
+ m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+ }
m_jit.move(op1GPR, tempGPR);
unboxDouble(tempGPR, resultFPR);
@@ -1872,9 +1898,11 @@ void SpeculativeJIT::compileInt32ToDouble(Node& node)
JITCompiler::Jump isInteger = m_jit.branch32(
MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
- speculationCheck(
- BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
- m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+ speculationCheck(
+ BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
+ m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+ }
unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
JITCompiler::Jump done = m_jit.jump();
@@ -2245,8 +2273,8 @@ void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg p
void SpeculativeJIT::compileInstanceOf(Node& node)
{
- if ((!!(at(node.child1()).prediction() & ~PredictCell)
- && !!(m_state.forNode(node.child1()).m_type & ~PredictCell))
+ if ((!!(at(node.child1()).prediction() & ~SpecCell)
+ && !!(m_state.forNode(node.child1()).m_type & ~SpecCell))
|| at(node.child1()).adjustedRefCount() == 1) {
// It might not be a cell. Speculate less aggressively.
// Or: it might only be used once (i.e. by us), so we get zero benefit
@@ -2780,12 +2808,12 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
if (node.op() == CompareEq) {
if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
- compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
return false;
}
if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
- compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
return false;
}
@@ -2793,7 +2821,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
compileObjectToObjectOrOtherEquality(
node.child1(), node.child2(), &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
return false;
}
@@ -2801,7 +2829,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateFinalObject()) {
compileObjectToObjectOrOtherEquality(
node.child2(), node.child1(), &JSFinalObject::s_info,
- isFinalObjectPrediction);
+ isFinalObjectSpeculation);
return false;
}
@@ -2809,7 +2837,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateArrayOrOther()) {
compileObjectToObjectOrOtherEquality(
node.child1(), node.child2(), &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
return false;
}
@@ -2817,7 +2845,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
&& at(node.child2()).shouldSpeculateArray()) {
compileObjectToObjectOrOtherEquality(
node.child2(), node.child1(), &JSArray::s_info,
- isArrayPrediction);
+ isArraySpeculation);
return false;
}
}
@@ -2957,14 +2985,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
unsigned branchIndexInBlock = detectPeepHoleBranch();
if (branchIndexInBlock != UINT_MAX) {
NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
- compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectSpeculation);
use(node.child1());
use(node.child2());
m_indexInBlock = branchIndexInBlock;
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
return false;
}
@@ -2972,14 +3000,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
unsigned branchIndexInBlock = detectPeepHoleBranch();
if (branchIndexInBlock != UINT_MAX) {
NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
- compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArraySpeculation);
use(node.child1());
use(node.child2());
m_indexInBlock = branchIndexInBlock;
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
return false;
}
@@ -2998,8 +3026,8 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- PredictedType basePrediction = at(node.child2()).prediction();
- if (!(basePrediction & PredictInt32) && basePrediction) {
+ SpeculatedType basePrediction = at(node.child2()).prediction();
+ if (!(basePrediction & SpecInt32) && basePrediction) {
ASSERT_NOT_REACHED();
terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
noResult(m_compileIndex);
@@ -3010,8 +3038,8 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
GPRReg storageReg = storage.gpr();
if (at(node.child1()).shouldSpeculateArguments()) {
ASSERT_NOT_REACHED();
- } else if (at(node.child1()).prediction() == PredictString) {
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ } else if (at(node.child1()).prediction() == SpecString) {
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
@@ -3022,51 +3050,51 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
} else if (at(node.child1()).shouldSpeculateInt8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
- if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateInt16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
- if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateInt32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
- if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
- if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
- if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
- if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
- if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateFloat32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
- if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateFloat64Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
- if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else {
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
}
@@ -3094,7 +3122,7 @@ void SpeculativeJIT::compileGetByValOnArguments(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
@@ -3162,7 +3190,7 @@ void SpeculativeJIT::compileGetArgumentsLength(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 56a1a1861..933784685 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -81,13 +81,13 @@ public:
ASSERT(kind() == HaveNode);
}
- static ValueSource forPrediction(PredictedType prediction)
+ static ValueSource forSpeculation(SpeculatedType prediction)
{
- if (isInt32Prediction(prediction))
+ if (isInt32Speculation(prediction))
return ValueSource(Int32InRegisterFile);
- if (isArrayPrediction(prediction))
+ if (isArraySpeculation(prediction))
return ValueSource(CellInRegisterFile);
- if (isBooleanPrediction(prediction))
+ if (isBooleanSpeculation(prediction))
return ValueSource(BooleanInRegisterFile);
return ValueSource(ValueInRegisterFile);
}
@@ -1294,6 +1294,11 @@ public:
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
{
m_jit.setupArgumentsExecState();
@@ -1409,6 +1414,11 @@ public:
m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
return appendCallWithExceptionCheck(operation);
}
+ JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet)
+ {
+ m_jit.setupArguments(TrustedImmPtr(watchpointSet));
+ return appendCall(operation);
+ }
template<typename FunctionType, typename ArgumentType1>
JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
{
@@ -1547,6 +1557,11 @@ public:
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_DFGOperation_EZIcfZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EZZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
@@ -1662,6 +1677,11 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
+ JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet)
+ {
+ m_jit.setupArguments(TrustedImmPtr(watchpointSet));
+ return appendCall(operation);
+ }
template<typename FunctionType, typename ArgumentType1>
JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
{
@@ -1783,6 +1803,11 @@ public:
m_jit.move(GPRInfo::returnValueGPR, result);
return call;
}
+ JITCompiler::Call appendCall(const FunctionPtr& function)
+ {
+ prepareForExternalCall();
+ return m_jit.appendCall(function);
+ }
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
{
JITCompiler::Call call = appendCallWithExceptionCheck(function);
@@ -2034,12 +2059,12 @@ public:
bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
- void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
+ void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
void compilePeepHoleObjectToObjectOrOtherEquality(
- Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
- void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker);
+ Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
+ void compileObjectEquality(Node&, const ClassInfo*, SpeculatedTypeChecker);
void compileObjectToObjectOrOtherEquality(
- Edge leftChild, Edge rightChild, const ClassInfo*, PredictionChecker);
+ Edge leftChild, Edge rightChild, const ClassInfo*, SpeculatedTypeChecker);
void compileValueAdd(Node&);
void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck);
void compileLogicalNot(Node&);
@@ -2183,6 +2208,32 @@ public:
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
}
+ // Use this like you would use speculationCheck(), except that you don't pass it a jump
+ // (because you don't have to execute a branch; that's kind of the whole point), and you
+ // must register the returned Watchpoint with something relevant. In general, this should
+ // be used with extreme care. Use speculationCheck() unless you've got an amazing reason
+ // not to.
+ Watchpoint* speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex)
+ {
+ if (!m_compileOkay)
+ return 0;
+ ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
+ OSRExit& exit = m_jit.codeBlock()->osrExit(
+ m_jit.codeBlock()->appendOSRExit(
+ OSRExit(kind, jsValueSource,
+ m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex),
+ JITCompiler::Jump(), this)));
+ exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint(
+ Watchpoint(m_jit.watchpointLabel()));
+ return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex);
+ }
+ // The default for speculation watchpoints is that they're uncounted, because the
+ // act of firing a watchpoint invalidates it. So, future recompilations will not
+ // attempt to set this watchpoint again.
+ Watchpoint* speculationWatchpoint()
+ {
+ return speculationWatchpoint(UncountableWatchpoint, JSValueSource(), NoNode);
+ }
void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
@@ -2197,7 +2248,7 @@ public:
setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
hadInt32ToDouble = true;
}
- if (setLocal->op() == Flush)
+ if (setLocal->op() == Flush || setLocal->op() == Phantom)
setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
if (hadInt32ToDouble)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 00a83000a..0c33e0748 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -30,6 +30,7 @@
#if ENABLE(DFG_JIT)
#include "DFGSlowPathGenerator.h"
+#include "JSVariableObject.h"
namespace JSC { namespace DFG {
@@ -1051,7 +1052,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
return allocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1073,7 +1074,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
// If we know this was spilled as an integer we can fill without checking.
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
GPRReg gpr = allocate();
@@ -1091,7 +1092,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)));
m_gprs.unlock(tagGPR);
m_gprs.release(tagGPR);
@@ -1147,7 +1148,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
return fprAllocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1185,7 +1186,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
hasUnboxedDouble = m_jit.jump();
@@ -1219,7 +1220,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
if (info.registerFormat() != DataFormatJSInteger) {
FPRTemporary scratch(this);
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
hasUnboxedDouble = m_jit.jump();
@@ -1280,7 +1281,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
return allocate();
}
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1299,7 +1300,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
}
ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
GPRReg gpr = allocate();
m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
@@ -1320,7 +1321,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)));
m_gprs.unlock(tagGPR);
m_gprs.release(tagGPR);
@@ -1349,7 +1350,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecBool@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = m_jit.graph()[nodeIndex];
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1374,7 +1375,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
- if (!isBooleanPrediction(type))
+ if (!isBooleanSpeculation(type))
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
GPRReg gpr = allocate();
@@ -1396,7 +1397,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
GPRReg payloadGPR = info.payloadGPR();
m_gprs.lock(tagGPR);
m_gprs.lock(payloadGPR);
- if (!isBooleanPrediction(type))
+ if (!isBooleanSpeculation(type))
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)));
m_gprs.unlock(tagGPR);
@@ -1439,16 +1440,16 @@ JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg res
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
GPRReg op1GPR = op1.gpr();
GPRReg op2GPR = op2.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
GPRTemporary resultPayload(this, op2);
@@ -1466,7 +1467,7 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, leftChild);
JSValueOperand op2(this, rightChild);
@@ -1477,7 +1478,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
GPRReg op2PayloadGPR = op2.payloadGPR();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1493,9 +1494,9 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
m_jit.branchPtr(
@@ -1514,7 +1515,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+ if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
m_jit.move(op2TagGPR, resultGPR);
m_jit.or32(TrustedImm32(1), resultGPR);
@@ -1537,7 +1538,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -1552,7 +1553,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
GPRReg op2PayloadGPR = op2.payloadGPR();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1568,9 +1569,9 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
m_jit.branchPtr(
@@ -1586,7 +1587,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+ if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
rightNotCell.link(&m_jit);
else {
jump(notTaken, ForceJump);
@@ -1692,11 +1693,11 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
return;
}
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
@@ -1787,9 +1788,9 @@ void SpeculativeJIT::emitBranch(Node& node)
noResult(m_compileIndex);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
@@ -1848,7 +1849,13 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ initConstantInfo(m_compileIndex);
+ break;
+
case PhantomArguments:
+ // This should never be must-generate.
+ ASSERT_NOT_REACHED();
+ // But as a release-mode fall-back make it the empty value.
initConstantInfo(m_compileIndex);
break;
@@ -1858,11 +1865,11 @@ void SpeculativeJIT::compile(Node& node)
break;
case GetLocal: {
- PredictedType prediction = node.variableAccessData()->prediction();
+ SpeculatedType prediction = node.variableAccessData()->prediction();
AbstractValue& value = block()->valuesAtHead.operand(node.local());
// If we have no prediction for this local, then don't attempt to compile.
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
break;
}
@@ -1884,7 +1891,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isInt32Prediction(prediction)) {
+ if (isInt32Speculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1896,7 +1903,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isArrayPrediction(prediction)) {
+ if (isArraySpeculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1908,7 +1915,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isBooleanPrediction(prediction)) {
+ if (isBooleanSpeculation(prediction)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1933,7 +1940,7 @@ void SpeculativeJIT::compile(Node& node)
m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
DataFormat format;
- if (isCellPrediction(value.m_type)
+ if (isCellSpeculation(value.m_type)
&& !node.variableAccessData()->isCaptured())
format = DataFormatJSCell;
else
@@ -1999,7 +2006,7 @@ void SpeculativeJIT::compile(Node& node)
valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) {
DoubleOperand value(this, node.child1());
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
@@ -2007,24 +2014,24 @@ void SpeculativeJIT::compile(Node& node)
valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
break;
}
- if (isInt32Prediction(predictedType)) {
+ if (isInt32Speculation(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
break;
}
- if (isArrayPrediction(predictedType)) {
+ if (isArraySpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
break;
}
- if (isBooleanPrediction(predictedType)) {
+ if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
@@ -2122,7 +2129,7 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckNumber: {
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
JSValueOperand op1(this, node.child1());
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag));
speculationCheck(
@@ -2326,7 +2333,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2349,7 +2356,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (at(node.child1()).prediction() == PredictString) {
+ if (at(node.child1()).prediction() == SpecString) {
compileGetByValOnString(node);
if (!m_compileOkay)
return;
@@ -2357,63 +2364,63 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2434,7 +2441,7 @@ void SpeculativeJIT::compile(Node& node)
{
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
}
@@ -2460,7 +2467,7 @@ void SpeculativeJIT::compile(Node& node)
}
if (!at(node.child2()).shouldSpeculateInteger()
- || !isActionableMutableArrayPrediction(at(node.child1()).prediction())
+ || !isActionableMutableArraySpeculation(at(node.child1()).prediction())
|| at(node.child1()).shouldSpeculateArguments()) {
SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
JSValueOperand property(this, node.child2());
@@ -2481,63 +2488,63 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2562,7 +2569,7 @@ void SpeculativeJIT::compile(Node& node)
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
base.use();
@@ -2608,7 +2615,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+ ASSERT(isActionableMutableArraySpeculation(at(node.child1()).prediction()));
ASSERT(at(node.child2()).shouldSpeculateInteger());
SpeculateCellOperand base(this, node.child1());
@@ -2763,7 +2770,7 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2801,7 +2808,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2947,7 +2954,7 @@ void SpeculativeJIT::compile(Node& node)
op1.use();
- if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean))) {
+ if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean))) {
m_jit.move(op1TagGPR, resultTagGPR);
m_jit.move(op1PayloadGPR, resultPayloadGPR);
} else {
@@ -3053,7 +3060,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ConvertThis: {
- if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isObjectSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
m_jit.move(thisValue.gpr(), result.gpr());
@@ -3061,7 +3068,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isOtherPrediction(at(node.child1()).prediction())) {
+ if (isOtherSpeculation(at(node.child1()).prediction())) {
JSValueOperand thisValue(this, node.child1());
GPRTemporary scratch(this);
@@ -3080,11 +3087,11 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isObjectPrediction(at(node.child1()).prediction())) {
+ if (isObjectSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand thisValue(this, node.child1());
GPRReg thisValueGPR = thisValue.gpr();
- if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
GPRTemporary result(this, thisValue);
@@ -3214,7 +3221,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRTemporary resultTag(this, base);
GPRTemporary resultPayload(this);
@@ -3268,7 +3275,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3317,7 +3324,7 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
GPRTemporary result(this);
@@ -3344,7 +3351,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
@@ -3354,39 +3361,39 @@ void SpeculativeJIT::compile(Node& node)
}
case GetInt8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ClampedArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat64ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
@@ -3400,7 +3407,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
if (value.m_structure.isSubsetOf(node.structureSet())
- && isCellPrediction(value.m_type)) {
+ && isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
}
@@ -3430,7 +3437,23 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case StructureTransitionWatchpoint: {
+ m_jit.addWeakReference(node.structure());
+ node.structure()->addTransitionWatchpoint(speculationWatchpoint());
+
+#if !ASSERT_DISABLED
+ SpeculateCellOperand op1(this, node.child1());
+ JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureOffset()), TrustedImmPtr(node.structure()));
+ m_jit.breakpoint();
+ isOK.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
+
case PhantomPutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
m_jit.addWeakReferenceTransition(
node.codeOrigin.codeOriginOwner(),
node.structureTransitionData().previousStructure,
@@ -3440,6 +3463,8 @@ void SpeculativeJIT::compile(Node& node)
}
case PutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
+
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3558,34 +3583,89 @@ void SpeculativeJIT::compile(Node& node)
}
case GetGlobalVar: {
- GPRTemporary result(this);
- GPRTemporary scratch(this);
+ GPRTemporary resultPayload(this);
+ GPRTemporary resultTag(this);
- JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
- m_jit.loadPtr(const_cast<WriteBarrier<Unknown>**>(globalObject->addressOfRegisters()), result.gpr());
- m_jit.load32(JITCompiler::tagForGlobalVar(result.gpr(), node.varNumber()), scratch.gpr());
- m_jit.load32(JITCompiler::payloadForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+ m_jit.move(TrustedImmPtr(node.registerPointer()), resultPayload.gpr());
+ m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTag.gpr());
+ m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayload.gpr());
- jsValueResult(scratch.gpr(), result.gpr(), m_compileIndex);
+ jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
break;
}
case PutGlobalVar: {
JSValueOperand value(this, node.child1());
- GPRTemporary globalObject(this);
- GPRTemporary scratch(this);
-
- GPRReg globalObjectReg = globalObject.gpr();
- GPRReg scratchReg = scratch.gpr();
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
- m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+ // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have
+ // a spare register - a good optimization would be to put the register pointer into
+ // a register and then do a zero offset store followed by a four-offset store (or
+ // vice-versa depending on endianness).
+ m_jit.store32(value.tagGPR(), node.registerPointer()->tagPointer());
+ m_jit.store32(value.payloadGPR(), node.registerPointer()->payloadPointer());
- writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ noResult(m_compileIndex);
+ break;
+ }
- m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
- m_jit.store32(value.tagGPR(), JITCompiler::tagForGlobalVar(scratchReg, node.varNumber()));
- m_jit.store32(value.payloadGPR(), JITCompiler::payloadForGlobalVar(scratchReg, node.varNumber()));
+ case PutGlobalVarCheck: {
+ JSValueOperand value(this, node.child1());
+
+ WatchpointSet* watchpointSet =
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).watchpointSet();
+ addSlowPathGenerator(
+ slowPathCall(
+ m_jit.branchTest8(
+ JITCompiler::NonZero,
+ JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())),
+ this, operationNotifyGlobalVarWrite, NoResult, watchpointSet));
+
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+ // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have
+ // a spare register - a good optimization would be to put the register pointer into
+ // a register and then do a zero offset store followed by a four-offset store (or
+ // vice-versa depending on endianness).
+ m_jit.store32(value.tagGPR(), node.registerPointer()->tagPointer());
+ m_jit.store32(value.payloadGPR(), node.registerPointer()->payloadPointer());
+
+ noResult(m_compileIndex);
+ break;
+ }
+
+ case GlobalVarWatchpoint: {
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).addWatchpoint(
+ speculationWatchpoint());
+
+#if DFG_ENABLE(JIT_ASSERT)
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+ m_jit.load32(node.registerPointer()->tagPointer(), scratchGPR);
+ JITCompiler::Jump notOK = m_jit.branch32(
+ JITCompiler::NotEqual, scratchGPR,
+ TrustedImm32(node.registerPointer()->get().tag()));
+ m_jit.load32(node.registerPointer()->payloadPointer(), scratchGPR);
+ JITCompiler::Jump ok = m_jit.branch32(
+ JITCompiler::Equal, scratchGPR,
+ TrustedImm32(node.registerPointer()->get().payload()));
+ notOK.link(&m_jit);
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+#endif
+
noResult(m_compileIndex);
break;
}
@@ -3858,16 +3938,15 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckArgumentsNotCreated: {
- if (!isEmptyPrediction(
- m_state.variables().operand(
- m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(
- JITCompiler::NotEqual,
- JITCompiler::tagFor(m_jit.argumentsRegisterFor(node.codeOrigin)),
- TrustedImm32(JSValue::EmptyValueTag)));
- }
+ ASSERT(!isEmptySpeculation(
+ m_state.variables().operand(
+ m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type));
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(
+ JITCompiler::NotEqual,
+ JITCompiler::tagFor(m_jit.argumentsRegisterFor(node.codeOrigin)),
+ TrustedImm32(JSValue::EmptyValueTag)));
noResult(m_compileIndex);
break;
}
@@ -3876,7 +3955,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -3937,7 +4016,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultPayloadGPR = resultPayload.gpr();
GPRReg resultTagGPR = resultTag.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -4033,11 +4112,20 @@ void SpeculativeJIT::compile(Node& node)
baseOffset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
resultPayloadGPR);
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationGetArgumentByVal,
- JSValueRegs(resultTagGPR, resultPayloadGPR),
- m_jit.argumentsRegisterFor(node.codeOrigin), indexGPR));
+ if (node.codeOrigin.inlineCallFrame) {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetInlinedArgumentByVal,
+ JSValueRegs(resultTagGPR, resultPayloadGPR),
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ node.codeOrigin.inlineCallFrame, indexGPR));
+ } else {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetArgumentByVal,
+ JSValueRegs(resultTagGPR, resultPayloadGPR),
+ m_jit.argumentsRegisterFor(node.codeOrigin), indexGPR));
+ }
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index ca57743a6..0b7606b2c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1028,7 +1028,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecInt@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1086,7 +1086,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
// Check the value is an integer.
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isInt32Prediction(type))
+ if (!isInt32Speculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
info.fillJSValue(gpr, DataFormatJSInteger);
// If !strict we're done, return.
@@ -1175,7 +1175,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecDouble@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1260,7 +1260,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
- if (!isNumberPrediction(type))
+ if (!isNumberSpeculation(type))
speculationCheck(BadType, JSValueRegs(jsValueGpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
// First, if we get here we have a double encoded as a JSValue
@@ -1328,7 +1328,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecCell@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1358,7 +1358,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, DataFormatJS);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
info.fillJSValue(gpr, DataFormatJSCell);
return gpr;
@@ -1374,7 +1374,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
case DataFormatJS: {
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isCellPrediction(type))
+ if (!isCellSpeculation(type))
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
info.fillJSValue(gpr, DataFormatJSCell);
return gpr;
@@ -1403,7 +1403,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("SpecBool@%d ", nodeIndex);
#endif
- PredictedType type = m_state.forNode(nodeIndex).m_type;
+ SpeculatedType type = m_state.forNode(nodeIndex).m_type;
Node& node = at(nodeIndex);
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1433,7 +1433,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, DataFormatJS);
- if (!isBooleanPrediction(type)) {
+ if (!isBooleanSpeculation(type)) {
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
@@ -1452,7 +1452,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
case DataFormatJS: {
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
- if (!isBooleanPrediction(type)) {
+ if (!isBooleanSpeculation(type)) {
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
@@ -1499,7 +1499,7 @@ JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, G
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
@@ -1509,9 +1509,9 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
- if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+ if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
@@ -1526,7 +1526,7 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
SpeculateCellOperand op1(this, leftChild);
JSValueOperand op2(this, rightChild);
@@ -1536,7 +1536,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueRegs(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1552,9 +1552,9 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2GPR), rightChild.index(),
m_jit.branchPtr(
@@ -1573,7 +1573,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+ if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
m_jit.move(op2GPR, resultGPR);
m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
@@ -1596,7 +1596,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
- const ClassInfo* classInfo, PredictionChecker predictionCheck)
+ const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
@@ -1610,7 +1610,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
GPRReg op2GPR = op2.gpr();
GPRReg resultGPR = result.gpr();
- if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+ if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) {
speculationCheck(
BadType, JSValueRegs(op1GPR), leftChild.index(),
m_jit.branchPtr(
@@ -1626,9 +1626,9 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
// proof, when filtered on cell, demonstrates that we have an object of the desired type
- // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+ // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the
// speculation.
- if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+ if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) {
speculationCheck(
BadType, JSValueRegs(op2GPR), rightChild.index(),
m_jit.branchPtr(
@@ -1644,7 +1644,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
// We know that within this branch, rightChild must not be a cell. Check if that is enough to
// prove that it is either null or undefined.
- if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+ if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
rightNotCell.link(&m_jit);
else {
jump(notTaken, ForceJump);
@@ -1739,11 +1739,11 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInf
void SpeculativeJIT::compileLogicalNot(Node& node)
{
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
@@ -1766,9 +1766,9 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
return;
}
- PredictedType prediction = m_jit.getPrediction(node.child1());
- if (isBooleanPrediction(prediction)) {
- if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+ SpeculatedType prediction = m_jit.getSpeculation(node.child1());
+ if (isBooleanSpeculation(prediction)) {
+ if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateBooleanOperand value(this, node.child1());
GPRTemporary result(this, value);
@@ -1841,9 +1841,9 @@ void SpeculativeJIT::emitBranch(Node& node)
BlockIndex notTaken = node.notTakenBlockIndex();
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
@@ -1870,10 +1870,10 @@ void SpeculativeJIT::emitBranch(Node& node)
JSValueOperand value(this, node.child1());
GPRReg valueGPR = value.gpr();
- bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
+ bool predictBoolean = isBooleanSpeculation(m_jit.getSpeculation(node.child1()));
if (predictBoolean) {
- if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
if (taken == nextBlock()) {
@@ -1924,7 +1924,13 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ initConstantInfo(m_compileIndex);
+ break;
+
case PhantomArguments:
+ // This should never be must-generate.
+ ASSERT_NOT_REACHED();
+ // But as a release-mode fall-back make it the empty value.
initConstantInfo(m_compileIndex);
break;
@@ -1934,11 +1940,11 @@ void SpeculativeJIT::compile(Node& node)
break;
case GetLocal: {
- PredictedType prediction = node.variableAccessData()->prediction();
+ SpeculatedType prediction = node.variableAccessData()->prediction();
AbstractValue& value = block()->valuesAtHead.operand(node.local());
// If we have no prediction for this local, then don't attempt to compile.
- if (prediction == PredictNone) {
+ if (prediction == SpecNone) {
terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
break;
}
@@ -1960,7 +1966,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isInt32Prediction(value.m_type)) {
+ if (isInt32Speculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1984,9 +1990,9 @@ void SpeculativeJIT::compile(Node& node)
DataFormat format;
if (node.variableAccessData()->isCaptured())
format = DataFormatJS;
- else if (isCellPrediction(value.m_type))
+ else if (isCellSpeculation(value.m_type))
format = DataFormatJSCell;
- else if (isBooleanPrediction(value.m_type))
+ else if (isBooleanSpeculation(value.m_type))
format = DataFormatJSBoolean;
else
format = DataFormatJS;
@@ -2053,25 +2059,25 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
- if (isInt32Prediction(predictedType)) {
+ SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+ if (isInt32Speculation(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
break;
}
- if (isArrayPrediction(predictedType)) {
+ if (isArraySpeculation(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
break;
}
- if (isBooleanPrediction(predictedType)) {
+ if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand boolean(this, node.child1());
m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
@@ -2170,7 +2176,7 @@ void SpeculativeJIT::compile(Node& node)
}
case CheckNumber: {
- if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
JSValueOperand op1(this, node.child1());
JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister);
speculationCheck(
@@ -2370,7 +2376,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
JSValueOperand base(this, node.child1());
JSValueOperand property(this, node.child2());
GPRReg baseGPR = base.gpr();
@@ -2391,7 +2397,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (at(node.child1()).prediction() == PredictString) {
+ if (at(node.child1()).prediction() == SpecString) {
compileGetByValOnString(node);
if (!m_compileOkay)
return;
@@ -2399,63 +2405,63 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint16Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2474,7 +2480,7 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
@@ -2495,7 +2501,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArrayPrediction(at(node.child1()).prediction())) {
+ if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArraySpeculation(at(node.child1()).prediction())) {
JSValueOperand arg1(this, node.child1());
JSValueOperand arg2(this, node.child2());
JSValueOperand arg3(this, node.child3());
@@ -2528,7 +2534,7 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- if (!isArgumentsPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
speculationCheck(
BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
m_jit.branchPtr(
@@ -2572,61 +2578,61 @@ void SpeculativeJIT::compile(Node& node)
}
if (at(node.child1()).shouldSpeculateInt8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateInt32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
break;
}
if (at(node.child1()).shouldSpeculateUint16Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateUint32Array()) {
- compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat32Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
}
if (at(node.child1()).shouldSpeculateFloat64Array()) {
- compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+ compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
if (!m_compileOkay)
return;
break;
@@ -2650,7 +2656,7 @@ void SpeculativeJIT::compile(Node& node)
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
base.use();
@@ -2695,7 +2701,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+ ASSERT(isActionableMutableArraySpeculation(at(node.child1()).prediction()));
ASSERT(at(node.child2()).shouldSpeculateInteger());
SpeculateCellOperand base(this, node.child1());
@@ -2847,7 +2853,7 @@ void SpeculativeJIT::compile(Node& node)
writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -2885,7 +2891,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
@@ -3012,7 +3018,7 @@ void SpeculativeJIT::compile(Node& node)
op1.use();
- if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean)))
+ if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean)))
m_jit.move(op1GPR, resultGPR);
else {
MacroAssembler::Jump alreadyPrimitive = m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
@@ -3106,7 +3112,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ConvertThis: {
- if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (isObjectSpeculation(m_state.forNode(node.child1()).m_type)) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
m_jit.move(thisValue.gpr(), result.gpr());
@@ -3114,13 +3120,13 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isOtherPrediction(at(node.child1()).prediction())) {
+ if (isOtherSpeculation(at(node.child1()).prediction())) {
JSValueOperand thisValue(this, node.child1());
GPRTemporary scratch(this, thisValue);
GPRReg thisValueGPR = thisValue.gpr();
GPRReg scratchGPR = scratch.gpr();
- if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
+ if (!isOtherSpeculation(m_state.forNode(node.child1()).m_type)) {
m_jit.move(thisValueGPR, scratchGPR);
m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
@@ -3131,13 +3137,13 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isObjectPrediction(at(node.child1()).prediction())) {
+ if (isObjectSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand thisValue(this, node.child1());
GPRTemporary result(this, thisValue);
GPRReg thisValueGPR = thisValue.gpr();
GPRReg resultGPR = result.gpr();
- if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
m_jit.move(thisValueGPR, resultGPR);
@@ -3259,7 +3265,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRTemporary result(this, base);
@@ -3309,7 +3315,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isCellPrediction(at(node.child1()).prediction())) {
+ if (isCellSpeculation(at(node.child1()).prediction())) {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3356,7 +3362,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
@@ -3380,7 +3386,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseGPR = base.gpr();
GPRReg resultGPR = result.gpr();
- if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+ if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
@@ -3390,39 +3396,39 @@ void SpeculativeJIT::compile(Node& node)
}
case GetInt8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetInt32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint8ClampedArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint16ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetUint32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat32ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case GetFloat64ArrayLength: {
- compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+ compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type));
break;
}
case CheckFunction: {
@@ -3434,7 +3440,7 @@ void SpeculativeJIT::compile(Node& node)
case CheckStructure: {
AbstractValue& value = m_state.forNode(node.child1());
if (value.m_structure.isSubsetOf(node.structureSet())
- && isCellPrediction(value.m_type)) {
+ && isCellSpeculation(value.m_type)) {
noResult(m_compileIndex);
break;
}
@@ -3464,7 +3470,23 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case StructureTransitionWatchpoint: {
+ m_jit.addWeakReference(node.structure());
+ node.structure()->addTransitionWatchpoint(speculationWatchpoint());
+
+#if !ASSERT_DISABLED
+ SpeculateCellOperand op1(this, node.child1());
+ JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureOffset()), TrustedImmPtr(node.structure()));
+ m_jit.breakpoint();
+ isOK.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
+
case PhantomPutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
m_jit.addWeakReferenceTransition(
node.codeOrigin.codeOriginOwner(),
node.structureTransitionData().previousStructure,
@@ -3474,6 +3496,8 @@ void SpeculativeJIT::compile(Node& node)
}
case PutStructure: {
+ ASSERT(node.structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated());
+
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
@@ -3587,9 +3611,7 @@ void SpeculativeJIT::compile(Node& node)
case GetGlobalVar: {
GPRTemporary result(this);
- JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
- m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
- m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+ m_jit.loadPtr(node.registerPointer(), result.gpr());
jsValueResult(result.gpr(), m_compileIndex);
break;
@@ -3597,22 +3619,65 @@ void SpeculativeJIT::compile(Node& node)
case PutGlobalVar: {
JSValueOperand value(this, node.child1());
- GPRTemporary globalObject(this);
- GPRTemporary scratch(this);
- GPRReg globalObjectReg = globalObject.gpr();
- GPRReg scratchReg = scratch.gpr();
-
- m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+
+ m_jit.storePtr(value.gpr(), node.registerPointer());
- writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ noResult(m_compileIndex);
+ break;
+ }
- m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
- m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+ case PutGlobalVarCheck: {
+ JSValueOperand value(this, node.child1());
+
+ WatchpointSet* watchpointSet =
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).watchpointSet();
+ addSlowPathGenerator(
+ slowPathCall(
+ m_jit.branchTest8(
+ JITCompiler::NonZero,
+ JITCompiler::AbsoluteAddress(watchpointSet->addressOfIsWatched())),
+ this, operationNotifyGlobalVarWrite, NoResult, watchpointSet));
+
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ GPRReg scratchReg = scratch.gpr();
+
+ writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+ }
+
+ m_jit.storePtr(value.gpr(), node.registerPointer());
noResult(m_compileIndex);
break;
}
+
+ case GlobalVarWatchpoint: {
+ m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get(
+ identifier(node.identifierNumberForCheck())->impl()).addWatchpoint(
+ speculationWatchpoint());
+
+#if DFG_ENABLE(JIT_ASSERT)
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+ m_jit.loadPtr(node.registerPointer(), scratchGPR);
+ JITCompiler::Jump ok = m_jit.branchPtr(
+ JITCompiler::Equal, scratchGPR,
+ TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(node.registerPointer()->get()))));
+ m_jit.breakpoint();
+ ok.link(&m_jit);
+#endif
+
+ noResult(m_compileIndex);
+ break;
+ }
case CheckHasInstance: {
SpeculateCellOperand base(this, node.child1());
@@ -3880,7 +3945,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -3939,7 +4004,7 @@ void SpeculativeJIT::compile(Node& node)
GPRReg indexGPR = index.gpr();
GPRReg resultGPR = result.gpr();
- if (!isEmptyPrediction(
+ if (!isEmptySpeculation(
m_state.variables().operand(
m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
speculationCheck(
@@ -4021,27 +4086,35 @@ void SpeculativeJIT::compile(Node& node)
: 0) + CallFrame::argumentOffsetIncludingThis(0)) * sizeof(Register)),
resultGPR);
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationGetArgumentByVal, resultGPR,
- m_jit.argumentsRegisterFor(node.codeOrigin),
- indexGPR));
+ if (node.codeOrigin.inlineCallFrame) {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetInlinedArgumentByVal, resultGPR,
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ node.codeOrigin.inlineCallFrame,
+ indexGPR));
+ } else {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationGetArgumentByVal, resultGPR,
+ m_jit.argumentsRegisterFor(node.codeOrigin),
+ indexGPR));
+ }
jsValueResult(resultGPR, m_compileIndex);
break;
}
case CheckArgumentsNotCreated: {
- if (!isEmptyPrediction(
- m_state.variables().operand(
- m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type)) {
- speculationCheck(
- ArgumentsEscaped, JSValueRegs(), NoNode,
- m_jit.branchTestPtr(
- JITCompiler::NonZero,
- JITCompiler::addressFor(
- m_jit.argumentsRegisterFor(node.codeOrigin))));
- }
+ ASSERT(!isEmptySpeculation(
+ m_state.variables().operand(
+ m_jit.graph().argumentsRegisterFor(node.codeOrigin)).m_type));
+ speculationCheck(
+ ArgumentsEscaped, JSValueRegs(), NoNode,
+ m_jit.branchTestPtr(
+ JITCompiler::NonZero,
+ JITCompiler::addressFor(
+ m_jit.argumentsRegisterFor(node.codeOrigin))));
noResult(m_compileIndex);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index 1ed46c11f..08ca6eaa1 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -79,7 +79,7 @@ MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData)
patchBuffer.link(functionCall, compileOSRExit);
- return patchBuffer.finalizeCode();
+ return FINALIZE_CODE(patchBuffer, ("DFG OSR exit generation thunk"));
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
index 3dfd94d01..382907d27 100644
--- a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
+++ b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
@@ -29,7 +29,7 @@
#include "DFGDoubleFormatState.h"
#include "DFGNodeFlags.h"
#include "Operands.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
#include "VirtualRegister.h"
#include <wtf/Platform.h>
#include <wtf/UnionFind.h>
@@ -43,8 +43,8 @@ public:
VariableAccessData()
: m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
- , m_prediction(PredictNone)
- , m_argumentAwarePrediction(PredictNone)
+ , m_prediction(SpecNone)
+ , m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_doubleFormatState(EmptyDoubleFormatState)
, m_isCaptured(false)
@@ -55,8 +55,8 @@ public:
VariableAccessData(VirtualRegister local, bool isCaptured)
: m_local(local)
- , m_prediction(PredictNone)
- , m_argumentAwarePrediction(PredictNone)
+ , m_prediction(SpecNone)
+ , m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_doubleFormatState(EmptyDoubleFormatState)
, m_isCaptured(isCaptured)
@@ -104,33 +104,33 @@ public:
return m_isArgumentsAlias;
}
- bool predict(PredictedType prediction)
+ bool predict(SpeculatedType prediction)
{
VariableAccessData* self = find();
- bool result = mergePrediction(self->m_prediction, prediction);
+ bool result = mergeSpeculation(self->m_prediction, prediction);
if (result)
- mergePrediction(m_argumentAwarePrediction, m_prediction);
+ mergeSpeculation(m_argumentAwarePrediction, m_prediction);
return result;
}
- PredictedType nonUnifiedPrediction()
+ SpeculatedType nonUnifiedPrediction()
{
return m_prediction;
}
- PredictedType prediction()
+ SpeculatedType prediction()
{
return find()->m_prediction;
}
- PredictedType argumentAwarePrediction()
+ SpeculatedType argumentAwarePrediction()
{
return find()->m_argumentAwarePrediction;
}
- bool mergeArgumentAwarePrediction(PredictedType prediction)
+ bool mergeArgumentAwarePrediction(SpeculatedType prediction)
{
- return mergePrediction(find()->m_argumentAwarePrediction, prediction);
+ return mergeSpeculation(find()->m_argumentAwarePrediction, prediction);
}
void clearVotes()
@@ -161,12 +161,12 @@ public:
// If the variable is not a number prediction, then this doesn't
// make any sense.
- if (!isNumberPrediction(prediction()))
+ if (!isNumberSpeculation(prediction()))
return false;
// If the variable is predicted to hold only doubles, then it's a
// no-brainer: it should be formatted as a double.
- if (isDoublePrediction(prediction()))
+ if (isDoubleSpeculation(prediction()))
return true;
// If the variable is known to be used as an integer, then be safe -
@@ -225,7 +225,7 @@ public:
if (m_doubleFormatState != UsingDoubleFormat)
return false;
- return mergePrediction(m_prediction, PredictDouble);
+ return mergeSpeculation(m_prediction, SpecDouble);
}
NodeFlags flags() const { return m_flags; }
@@ -246,8 +246,8 @@ private:
// usage for variable access nodes do be significant.
VirtualRegister m_local;
- PredictedType m_prediction;
- PredictedType m_argumentAwarePrediction;
+ SpeculatedType m_prediction;
+ SpeculatedType m_argumentAwarePrediction;
NodeFlags m_flags;
float m_votes[2];