Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (96414 => 96415)
--- trunk/Source/_javascript_Core/ChangeLog 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-09-30 20:01:38 UTC (rev 96415)
@@ -1,3 +1,28 @@
+2011-09-30 Gavin Barraclough <[email protected]>
+
+ Merge some more of DFGSpeculativeJIT 32_64/64
+ https://bugs.webkit.org/show_bug.cgi?id=69164
+
+ Reviewed by Oliver Hunt.
+
+ * dfg/DFGJITCodeGenerator.h:
+ * dfg/DFGJITCodeGenerator32_64.cpp:
+ * dfg/DFGJITCodeGenerator64.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+ (JSC::DFG::SpeculativeJIT::compare):
+ (JSC::DFG::SpeculativeJIT::compileValueAdd):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compare):
+ (JSC::DFG::SpeculativeJIT::compileValueAdd):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::compile):
+
2011-09-30 Mark Hahnenberg <[email protected]>
Add getCallData to MethodTable in ClassInfo
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-09-30 20:01:38 UTC (rev 96415)
@@ -779,8 +779,6 @@
void emitBranch(Node&);
- void nonSpeculativeLogicalNot(Node&);
-
MacroAssembler::Address addressOfCallData(int idx)
{
return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)));
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-09-30 20:01:38 UTC (rev 96415)
@@ -1554,38 +1554,6 @@
noResult(m_compileIndex, UseChildrenCalledExplicitly);
}
-void JITCodeGenerator::nonSpeculativeLogicalNot(Node& node)
-{
- JSValueOperand arg1(this, node.child1());
- GPRTemporary resultTag(this, arg1);
- GPRTemporary resultPayload(this, arg1, false);
- GPRReg arg1TagGPR = arg1.tagGPR();
- GPRReg arg1PayloadGPR = arg1.payloadGPR();
- GPRReg resultTagGPR = resultTag.gpr();
- GPRReg resultPayloadGPR = resultPayload.gpr();
-
- arg1.use();
-
- JITCompiler::Jump fastCase = m_jit.branch32(JITCompiler::Equal, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
-
- silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
- m_jit.push(arg1TagGPR);
- m_jit.push(arg1PayloadGPR);
- m_jit.push(GPRInfo::callFrameRegister);
- appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
- m_jit.move(GPRInfo::returnValueGPR, resultPayloadGPR);
- silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
- JITCompiler::Jump doNot = m_jit.jump();
-
- fastCase.link(&m_jit);
- m_jit.move(arg1PayloadGPR, resultPayloadGPR);
-
- doNot.link(&m_jit);
- m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
- m_jit.move(TrustedImm32(JSValue::BooleanTag), resultTagGPR);
- jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
-}
-
void JITCodeGenerator::emitCall(Node& node)
{
P_DFGOperation_E slowCallFunction;
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-09-30 20:01:38 UTC (rev 96415)
@@ -1525,33 +1525,6 @@
}
}
-void JITCodeGenerator::nonSpeculativeLogicalNot(Node& node)
-{
- JSValueOperand arg1(this, node.child1());
- GPRTemporary result(this);
-
- GPRReg arg1GPR = arg1.gpr();
- GPRReg resultGPR = result.gpr();
-
- arg1.use();
-
- m_jit.move(arg1GPR, resultGPR);
- m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
- JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
-
- silentSpillAllRegisters(resultGPR);
- m_jit.move(arg1GPR, GPRInfo::argumentGPR1);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
- m_jit.move(GPRInfo::returnValueGPR, resultGPR);
- silentFillAllRegisters(resultGPR);
-
- fastCase.link(&m_jit);
-
- m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
- jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
-}
-
void JITCodeGenerator::emitCall(Node& node)
{
P_DFGOperation_E slowCallFunction;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-09-30 20:01:38 UTC (rev 96415)
@@ -194,6 +194,41 @@
addBranch(m_jit.jump(), notTaken);
}
+// Returns true if the compare is fused with a subsequent branch.
+bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
+{
+ // Fused compare & branch.
+ NodeIndex branchNodeIndex = detectPeepHoleBranch();
+ if (branchNodeIndex != NoNode) {
+ // detectPeepHoleBranch currently only permits the branch to be the very next node,
+ // so can be no intervening nodes to also reference the compare.
+ ASSERT(node.adjustedRefCount() == 1);
+
+ if (shouldSpeculateInteger(node.child1(), node.child2())) {
+ compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
+ use(node.child1());
+ use(node.child2());
+ } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
+ compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
+ use(node.child1());
+ use(node.child2());
+ } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2())) {
+ compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
+ use(node.child1());
+ use(node.child2());
+ } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
+ compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
+ use(node.child1());
+ use(node.child2());
+ } else
+ nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
+
+ m_compileIndex = branchNodeIndex;
+ return true;
+ }
+ return false;
+}
+
void SpeculativeJIT::compileMovHint(Node& node)
{
ASSERT(node.op == SetLocal);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-09-30 20:01:38 UTC (rev 96415)
@@ -570,10 +570,13 @@
}
bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, Z_DFGOperation_EJJ);
+ bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, Z_DFGOperation_EJJ);
void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr);
void compileObjectEquality(Node&, void* vptr);
+ void compileValueAdd(Node&);
+ void compileLogicalNot(Node&);
// It is acceptable to have structure be equal to scratch, so long as you're fine
// with the structure GPR being clobbered.
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-09-30 20:01:38 UTC (rev 96415)
@@ -101,7 +101,7 @@
case DataFormatCell:
case DataFormatBoolean:
case DataFormatJSDouble:
- case DataFormatJSCell:
+ case DataFormatJSCell:
case DataFormatJSBoolean: {
terminateSpeculativeExecution();
returnFormat = DataFormatInteger;
@@ -373,35 +373,8 @@
// Returns true if the compare is fused with a subsequent branch.
bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
{
- // Fused compare & branch.
- NodeIndex branchNodeIndex = detectPeepHoleBranch();
- if (branchNodeIndex != NoNode) {
- // detectPeepHoleBranch currently only permits the branch to be the very next node,
- // so can be no intervening nodes to also reference the compare.
- ASSERT(node.adjustedRefCount() == 1);
-
- if (shouldSpeculateInteger(node.child1(), node.child2())) {
- compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
- use(node.child1());
- use(node.child2());
- } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
- compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
- use(node.child1());
- use(node.child2());
- } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2())) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
- use(node.child1());
- use(node.child2());
- } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
- use(node.child1());
- use(node.child2());
- } else
- nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
-
- m_compileIndex = branchNodeIndex;
+ if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
return true;
- }
if (shouldSpeculateFinalObject(node.child1(), node.child2()))
compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
@@ -440,6 +413,75 @@
return false;
}
+void SpeculativeJIT::compileValueAdd(Node& node)
+{
+ JSValueOperand op1(this, node.child1());
+ JSValueOperand op2(this, node.child2());
+
+ GPRReg op1TagGPR = op1.tagGPR();
+ GPRReg op1PayloadGPR = op1.payloadGPR();
+ GPRReg op2TagGPR = op2.tagGPR();
+ GPRReg op2PayloadGPR = op2.payloadGPR();
+
+ flushRegisters();
+
+ GPRResult2 resultTag(this);
+ GPRResult resultPayload(this);
+ if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
+ callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
+ else
+ callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
+
+ jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileLogicalNot(Node& node)
+{
+ // FIXME: Need to add fast paths for known booleans.
+ JSValueOperand value(this, node.child1());
+ GPRTemporary resultTag(this, value);
+ GPRTemporary resultPayload(this, value, false);
+ speculationCheck(m_jit.branch32(JITCompiler::NotEqual, value.tagGPR(), TrustedImm32(JSValue::BooleanTag)));
+ m_jit.move(value.payloadGPR(), resultPayload.gpr());
+ m_jit.xor32(TrustedImm32(1), resultPayload.gpr());
+ m_jit.move(TrustedImm32(JSValue::BooleanTag), resultTag.gpr());
+
+ // If we add a DataFormatBool, we should use it here.
+ jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex, DataFormatJSBoolean);
+
+ // This code is moved from nonSpeculativeLogicalNot, currently unused!
+#if 0
+ JSValueOperand arg1(this, node.child1());
+ GPRTemporary resultTag(this, arg1);
+ GPRTemporary resultPayload(this, arg1, false);
+ GPRReg arg1TagGPR = arg1.tagGPR();
+ GPRReg arg1PayloadGPR = arg1.payloadGPR();
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
+
+ arg1.use();
+
+ JITCompiler::Jump fastCase = m_jit.branch32(JITCompiler::Equal, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
+
+ silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+ m_jit.push(arg1TagGPR);
+ m_jit.push(arg1PayloadGPR);
+ m_jit.push(GPRInfo::callFrameRegister);
+ appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
+ m_jit.move(GPRInfo::returnValueGPR, resultPayloadGPR);
+ silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+ JITCompiler::Jump doNot = m_jit.jump();
+
+ fastCase.link(&m_jit);
+ m_jit.move(arg1PayloadGPR, resultPayloadGPR);
+
+ doNot.link(&m_jit);
+ m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
+ m_jit.move(TrustedImm32(JSValue::BooleanTag), resultTagGPR);
+ jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+#endif
+}
+
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op;
@@ -459,31 +501,36 @@
}
GPRTemporary result(this);
- VirtualRegister virtualRegister = node.virtualRegister();
- m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
if (isInt32Prediction(prediction)) {
+ m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+
// Like integerResult, but don't useChildren - our children are phi nodes,
// and don't represent values within this dataflow with virtual registers.
+ VirtualRegister virtualRegister = node.virtualRegister();
m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
- } else {
- // Like jsValueResult, but don't useChildren - our children are phi nodes,
- // and don't represent values within this dataflow with virtual registers.
- GPRTemporary tag(this);
- m_jit.load32(JITCompiler::tagFor(node.local()), tag.gpr());
- m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
- m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
+ break;
+ }
- DataFormat format;
- if (isArrayPrediction(prediction))
- format = DataFormatJSCell;
- else if (isBooleanPrediction(prediction))
- format = DataFormatJSBoolean;
- else
- format = DataFormatJS;
+ GPRTemporary tag(this);
+ m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+ m_jit.load32(JITCompiler::tagFor(node.local()), tag.gpr());
- m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format);
- }
+ // Like jsValueResult, but don't useChildren - our children are phi nodes,
+ // and don't represent values within this dataflow with virtual registers.
+ VirtualRegister virtualRegister = node.virtualRegister();
+ m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
+ m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
+
+ DataFormat format;
+ if (isArrayPrediction(prediction))
+ format = DataFormatJSCell;
+ else if (isBooleanPrediction(prediction))
+ format = DataFormatJSBoolean;
+ else
+ format = DataFormatJS;
+
+ m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format);
break;
}
@@ -616,17 +663,14 @@
IntegerOperand op1(this, node.child1());
FPRTemporary result(this);
- GPRTemporary address(this, op1);
GPRReg inputGPR = op1.gpr();
FPRReg outputFPR = result.fpr();
- GPRReg addressGPR = address.gpr();
m_jit.convertInt32ToDouble(inputGPR, outputFPR);
JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
- m_jit.move(JITCompiler::TrustedImmPtr(&twoToThe32), addressGPR);
- m_jit.addDouble(JITCompiler::Address(addressGPR, 0), outputFPR);
+ m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);
positive.link(&m_jit);
doubleResult(outputFPR, m_compileIndex);
@@ -764,25 +808,7 @@
}
ASSERT(op == ValueAdd);
-
- JSValueOperand op1(this, node.child1());
- JSValueOperand op2(this, node.child2());
-
- GPRReg op1TagGPR = op1.tagGPR();
- GPRReg op1PayloadGPR = op1.payloadGPR();
- GPRReg op2TagGPR = op2.tagGPR();
- GPRReg op2PayloadGPR = op2.payloadGPR();
-
- flushRegisters();
-
- GPRResult2 resultTag(this);
- GPRResult resultPayload(this);
- if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
- callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
- else
- callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
-
- jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+ compileValueAdd(node);
break;
}
@@ -1062,20 +1088,9 @@
break;
}
- case LogicalNot: {
- // FIXME: Need to add fast paths for known booleans.
- JSValueOperand value(this, node.child1());
- GPRTemporary resultTag(this, value);
- GPRTemporary resultPayload(this, value, false);
- speculationCheck(m_jit.branch32(JITCompiler::NotEqual, value.tagGPR(), TrustedImm32(JSValue::BooleanTag)));
- m_jit.move(value.payloadGPR(), resultPayload.gpr());
- m_jit.xor32(TrustedImm32(1), resultPayload.gpr());
- m_jit.move(TrustedImm32(JSValue::BooleanTag), resultTag.gpr());
-
- // If we add a DataFormatBool, we should use it here.
- jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex, DataFormatJSBoolean);
+ case LogicalNot:
+ compileLogicalNot(node);
break;
- }
case CompareLess:
if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
@@ -1156,7 +1171,7 @@
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
JSValueOperand value(this, node.child3());
- GPRTemporary scratch(this, base);
+ GPRTemporary scratch(this);
// Map base, property & value into registers, allocate a scratch register.
GPRReg baseReg = base.gpr();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (96414 => 96415)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-09-30 19:34:33 UTC (rev 96414)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2011-09-30 20:01:38 UTC (rev 96415)
@@ -476,35 +476,8 @@
// Returns true if the compare is fused with a subsequent branch.
bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
{
- // Fused compare & branch.
- NodeIndex branchNodeIndex = detectPeepHoleBranch();
- if (branchNodeIndex != NoNode) {
- // detectPeepHoleBranch currently only permits the branch to be the very next node,
- // so can be no intervening nodes to also reference the compare.
- ASSERT(node.adjustedRefCount() == 1);
-
- if (shouldSpeculateInteger(node.child1(), node.child2())) {
- compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
- use(node.child1());
- use(node.child2());
- } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
- compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
- use(node.child1());
- use(node.child2());
- } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2())) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
- use(node.child1());
- use(node.child2());
- } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
- use(node.child1());
- use(node.child2());
- } else
- nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
-
- m_compileIndex = branchNodeIndex;
+ if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
return true;
- }
if (shouldSpeculateInteger(node.child1(), node.child2())) {
SpeculateIntegerOperand op1(this, node.child1());
@@ -537,6 +510,78 @@
return false;
}
+void SpeculativeJIT::compileValueAdd(Node& node)
+{
+ JSValueOperand op1(this, node.child1());
+ JSValueOperand op2(this, node.child2());
+
+ GPRReg op1GPR = op1.gpr();
+ GPRReg op2GPR = op2.gpr();
+
+ flushRegisters();
+
+ GPRResult result(this);
+ if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
+ callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
+ else
+ callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
+
+ jsValueResult(result.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileLogicalNot(Node& node)
+{
+ if (isKnownBoolean(node.child1())) {
+ SpeculateBooleanOperand value(this, node.child1());
+ GPRTemporary result(this, value);
+
+ m_jit.move(value.gpr(), result.gpr());
+ m_jit.xorPtr(TrustedImm32(true), result.gpr());
+
+ jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+ return;
+ }
+
+ PredictedType prediction = m_jit.getPrediction(node.child1());
+ if (isBooleanPrediction(prediction) || !prediction) {
+ JSValueOperand value(this, node.child1());
+ GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
+
+ m_jit.move(value.gpr(), result.gpr());
+ m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
+ speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+ m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
+
+ // If we add a DataFormatBool, we should use it here.
+ jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+ return;
+ }
+
+ JSValueOperand arg1(this, node.child1());
+ GPRTemporary result(this);
+
+ GPRReg arg1GPR = arg1.gpr();
+ GPRReg resultGPR = result.gpr();
+
+ arg1.use();
+
+ m_jit.move(arg1GPR, resultGPR);
+ m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
+ JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
+
+ silentSpillAllRegisters(resultGPR);
+ m_jit.move(arg1GPR, GPRInfo::argumentGPR1);
+ m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
+ m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+ silentFillAllRegisters(resultGPR);
+
+ fastCase.link(&m_jit);
+
+ m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
+ jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+}
+
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op;
@@ -564,24 +609,25 @@
VirtualRegister virtualRegister = node.virtualRegister();
m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
- } else {
- m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
+ break;
+ }
- // Like jsValueResult, but don't useChildren - our children are phi nodes,
- // and don't represent values within this dataflow with virtual registers.
- VirtualRegister virtualRegister = node.virtualRegister();
- m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
-
- DataFormat format;
- if (isArrayPrediction(prediction))
- format = DataFormatJSCell;
- else if (isBooleanPrediction(prediction))
- format = DataFormatJSBoolean;
- else
- format = DataFormatJS;
+ m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
- m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
- }
+ // Like jsValueResult, but don't useChildren - our children are phi nodes,
+ // and don't represent values within this dataflow with virtual registers.
+ VirtualRegister virtualRegister = node.virtualRegister();
+ m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
+
+ DataFormat format;
+ if (isArrayPrediction(prediction))
+ format = DataFormatJSCell;
+ else if (isBooleanPrediction(prediction))
+ format = DataFormatJSBoolean;
+ else
+ format = DataFormatJS;
+
+ m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
break;
}
@@ -862,22 +908,7 @@
}
ASSERT(op == ValueAdd);
-
- JSValueOperand op1(this, node.child1());
- JSValueOperand op2(this, node.child2());
-
- GPRReg op1GPR = op1.gpr();
- GPRReg op2GPR = op2.gpr();
-
- flushRegisters();
-
- GPRResult result(this);
- if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
- callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
- else
- callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
-
- jsValueResult(result.gpr(), m_compileIndex);
+ compileValueAdd(node);
break;
}
@@ -1157,37 +1188,9 @@
break;
}
- case LogicalNot: {
- if (isKnownBoolean(node.child1())) {
- SpeculateBooleanOperand value(this, node.child1());
- GPRTemporary result(this, value);
-
- m_jit.move(value.gpr(), result.gpr());
- m_jit.xorPtr(TrustedImm32(true), result.gpr());
-
- jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
- break;
- }
-
- PredictedType prediction = m_jit.getPrediction(node.child1());
- if (isBooleanPrediction(prediction) || !prediction) {
- JSValueOperand value(this, node.child1());
- GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
-
- m_jit.move(value.gpr(), result.gpr());
- m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
- speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
- m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
-
- // If we add a DataFormatBool, we should use it here.
- jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
- break;
- }
-
- nonSpeculativeLogicalNot(node);
-
+ case LogicalNot:
+ compileLogicalNot(node);
break;
- }
case CompareLess:
if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))