Commit ee099cb3 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JITCodeGenerator should no longer have code that tries too hard

to be both speculative and non-speculative
https://bugs.webkit.org/show_bug.cgi?id=69321

Reviewed by Gavin Barraclough.
        
Removed m_isSpeculative and speculationCheck() from JITCodeGenerator.
This required moving emitBranch() to SpeculativeJIT, since it was
the main user of that field and method. Other than trvial clean-ups
in emitBranch(), the code is unchanged (and still has some disparity
between 64 and 32_64, and still lacks some obvious optimizations).

* dfg/DFGJITCodeGenerator.cpp:
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::JITCodeGenerator):
* dfg/DFGJITCodeGenerator32_64.cpp:
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
* dfg/DFGJITCodeGenerator64.cpp:
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitBranch):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitBranch):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96661 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c7fca6eb
2011-10-03 Filip Pizlo <fpizlo@apple.com>
JITCodeGenerator should no longer have code that tries too hard
to be both speculative and non-speculative
https://bugs.webkit.org/show_bug.cgi?id=69321
Reviewed by Gavin Barraclough.
Removed m_isSpeculative and speculationCheck() from JITCodeGenerator.
This required moving emitBranch() to SpeculativeJIT, since it was
the main user of that field and method. Other than trvial clean-ups
in emitBranch(), the code is unchanged (and still has some disparity
between 64 and 32_64, and still lacks some obvious optimizations).
* dfg/DFGJITCodeGenerator.cpp:
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::JITCodeGenerator):
* dfg/DFGJITCodeGenerator32_64.cpp:
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
* dfg/DFGJITCodeGenerator64.cpp:
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitBranch):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitBranch):
2011-10-04 David Hyatt <hyatt@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=69372
......@@ -377,12 +377,6 @@ bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)
return false;
}
void JITCodeGenerator::speculationCheck(MacroAssembler::Jump jumpToFail)
{
ASSERT(m_isSpeculative);
static_cast<SpeculativeJIT*>(this)->speculationCheck(jumpToFail);
}
#ifndef NDEBUG
static const char* dataFormatString(DataFormat format)
{
......
......@@ -232,9 +232,8 @@ public:
}
protected:
JITCodeGenerator(JITCompiler& jit, bool isSpeculative)
JITCodeGenerator(JITCompiler& jit)
: m_jit(jit)
, m_isSpeculative(isSpeculative)
, m_compileIndex(0)
, m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
, m_blockHeads(jit.graph().m_blocks.size())
......@@ -778,8 +777,6 @@ protected:
void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
bool nonSpeculativeStrictEq(Node&, bool invert = false);
void emitBranch(Node&);
MacroAssembler::Address addressOfCallData(int idx)
{
return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)));
......@@ -799,8 +796,6 @@ protected:
void emitCall(Node&);
void speculationCheck(MacroAssembler::Jump jumpToFail);
// Called once a node has completed code generation but prior to setting
// its result, to free up its children. (This must happen prior to setting
// the nodes result, since the node may have the same VirtualRegister as
......@@ -1383,17 +1378,6 @@ protected:
// The JIT, while also provides MacroAssembler functionality.
JITCompiler& m_jit;
// This flag is used to distinguish speculative and non-speculative
// code generation. This is significant when filling spilled values
// from the RegisterFile. When spilling we attempt to store information
// as to the type of boxed value being stored (int32, double, cell), and
// when filling on the speculative path we will retrieve this type info
// where available. On the non-speculative path, however, we cannot rely
// on the spill format info, since the a value being loaded might have
// been spilled by either the speculative or non-speculative paths (where
// we entered the non-speculative path on an intervening bail-out), and
// the value may have been boxed differently on the two paths.
bool m_isSpeculative;
// The current node being generated.
BlockIndex m_block;
NodeIndex m_compileIndex;
......
......@@ -136,7 +136,7 @@ FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
m_jit.emitLoad(nodeIndex, tag, payload);
m_gprs.retain(tag, virtualRegister, SpillOrderSpilled);
m_gprs.retain(payload, virtualRegister, SpillOrderSpilled);
info.fillJSValue(tag, payload, m_isSpeculative ? spillFormat : DataFormatJS);
info.fillJSValue(tag, payload, spillFormat);
unlock(tag);
unlock(payload);
}
......@@ -242,7 +242,7 @@ bool JITCodeGenerator::fillJSValue(NodeIndex nodeIndex, GPRReg& tagGPR, GPRReg&
m_jit.emitLoad(nodeIndex, tagGPR, payloadGPR);
m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
info.fillJSValue(tagGPR, payloadGPR, m_isSpeculative ? spillFormat : DataFormatJS);
info.fillJSValue(tagGPR, payloadGPR, spillFormat);
}
return true;
......@@ -1517,45 +1517,6 @@ void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
}
void JITCodeGenerator::emitBranch(Node& node)
{
// FIXME: Add fast cases for known Boolean!
JSValueOperand value(this, node.child1());
value.fill();
GPRReg valueTagGPR = value.tagGPR();
GPRReg valuePayloadGPR = value.payloadGPR();
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
use(node.child1());
BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
fastPath.link(&m_jit);
addBranch(m_jit.branchTest32(JITCompiler::Zero, valuePayloadGPR), notTaken);
addBranch(m_jit.jump(), taken);
slowPath.link(&m_jit);
silentSpillAllRegisters(resultGPR);
m_jit.push(valueTagGPR);
m_jit.push(valuePayloadGPR);
m_jit.push(GPRInfo::callFrameRegister);
appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
m_jit.move(GPRInfo::returnValueGPR, resultGPR);
silentFillAllRegisters(resultGPR);
addBranch(m_jit.branchTest8(JITCompiler::NonZero, resultGPR), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
}
void JITCodeGenerator::emitCall(Node& node)
{
P_DFGOperation_E slowCallFunction;
......
......@@ -148,7 +148,7 @@ FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
ASSERT(spillFormat & DataFormatJS);
m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
info.fillJSValue(gpr, spillFormat);
unlock(gpr);
}
}
......@@ -266,7 +266,7 @@ GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
ASSERT(spillFormat & DataFormatJS);
m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
info.fillJSValue(gpr, spillFormat);
}
return gpr;
}
......@@ -1461,70 +1461,6 @@ void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert
jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
}
void JITCodeGenerator::emitBranch(Node& node)
{
JSValueOperand value(this, node.child1());
GPRReg valueGPR = value.gpr();
BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
if (isKnownBoolean(node.child1())) {
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
if (taken == (m_block + 1)) {
condition = MacroAssembler::Zero;
BlockIndex tmp = taken;
taken = notTaken;
notTaken = tmp;
}
addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
noResult(m_compileIndex);
} else {
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
if (predictBoolean) {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
}
if (m_isSpeculative && predictBoolean) {
speculationCheck(m_jit.jump());
value.use();
} else {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken);
if (!predictBoolean) {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
}
value.use();
silentSpillAllRegisters(resultGPR);
m_jit.move(valueGPR, GPRInfo::argumentGPR1);
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
m_jit.move(GPRInfo::returnValueGPR, resultGPR);
silentFillAllRegisters(resultGPR);
addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
}
noResult(m_compileIndex, UseChildrenCalledExplicitly);
}
}
void JITCodeGenerator::emitCall(Node& node)
{
P_DFGOperation_E slowCallFunction;
......
......@@ -600,6 +600,7 @@ private:
void compileObjectEquality(Node&, void* vptr);
void compileValueAdd(Node&);
void compileLogicalNot(Node&);
void emitBranch(Node&);
// It is acceptable to have structure be equal to scratch, so long as you're fine
// with the structure GPR being clobbered.
......@@ -943,7 +944,7 @@ private:
};
inline SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
: JITCodeGenerator(jit, true)
: JITCodeGenerator(jit)
, m_compileOkay(true)
, m_arguments(jit.codeBlock()->m_numParameters)
, m_variables(jit.graph().m_localVars)
......
......@@ -482,6 +482,45 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
#endif
}
void SpeculativeJIT::emitBranch(Node& node)
{
// FIXME: Add fast cases for known Boolean!
JSValueOperand value(this, node.child1());
value.fill();
GPRReg valueTagGPR = value.tagGPR();
GPRReg valuePayloadGPR = value.payloadGPR();
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
use(node.child1());
BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
fastPath.link(&m_jit);
addBranch(m_jit.branchTest32(JITCompiler::Zero, valuePayloadGPR), notTaken);
addBranch(m_jit.jump(), taken);
slowPath.link(&m_jit);
silentSpillAllRegisters(resultGPR);
m_jit.push(valueTagGPR);
m_jit.push(valuePayloadGPR);
m_jit.push(GPRInfo::callFrameRegister);
appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
m_jit.move(GPRInfo::returnValueGPR, resultGPR);
silentFillAllRegisters(resultGPR);
addBranch(m_jit.branchTest8(JITCompiler::NonZero, resultGPR), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
}
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op;
......
......@@ -582,6 +582,66 @@ void SpeculativeJIT::compileLogicalNot(Node& node)
jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
}
void SpeculativeJIT::emitBranch(Node& node)
{
JSValueOperand value(this, node.child1());
GPRReg valueGPR = value.gpr();
BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
if (isKnownBoolean(node.child1())) {
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
if (taken == (m_block + 1)) {
condition = MacroAssembler::Zero;
BlockIndex tmp = taken;
taken = notTaken;
notTaken = tmp;
}
addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
noResult(m_compileIndex);
} else {
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
if (predictBoolean) {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
speculationCheck(m_jit.jump());
value.use();
} else {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken);
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
value.use();
silentSpillAllRegisters(resultGPR);
m_jit.move(valueGPR, GPRInfo::argumentGPR1);
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
m_jit.move(GPRInfo::returnValueGPR, resultGPR);
silentFillAllRegisters(resultGPR);
addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken);
if (notTaken != (m_block + 1))
addBranch(m_jit.jump(), notTaken);
}
noResult(m_compileIndex, UseChildrenCalledExplicitly);
}
}
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment