Commit 0d018be1 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: FTL should support Jump and ForceOSRExit

https://bugs.webkit.org/show_bug.cgi?id=115942

Reviewed by Oliver Hunt.

Added two obvious nodes: Jump and ForceOSRExit. We already had everything we needed
to support them.

Adding these increases our coverage a fair bit, and revealed a bug: LLVM's full
instruction selector currently appears to mishandle doubles in constant pools (or
just constant pools in general) with the small code model in the MCJIT. But switching
to FastISel "fixes" it. That's what this patch does, for now. This will probably
actually be permanent; the FastISel does pretty much everything we would ever want,
at least in the foreseeable future.

* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
(FTL):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileBlock):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileJSConstant):
(LowerDFGToLLVM):
(JSC::FTL::LowerDFGToLLVM::compileJump):
(JSC::FTL::LowerDFGToLLVM::compileReturn):
(JSC::FTL::LowerDFGToLLVM::compileForceOSRExit):
* runtime/Options.h:
(JSC):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153156 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9a58da10
2013-05-11 Filip Pizlo <fpizlo@apple.com>
fourthTier: FTL should support Jump and ForceOSRExit
https://bugs.webkit.org/show_bug.cgi?id=115942
Reviewed by Oliver Hunt.
Added two obvious nodes: Jump and ForceOSRExit. We already had everything we needed
to support them.
Adding these increases our coverage a fair bit, and revealed a bug: LLVM's full
instruction selector currently appears to mishandle doubles in constant pools (or
just constant pools in general) with the small code model in the MCJIT. But switching
to FastISel "fixes" it. That's what this patch does, for now. This will probably
actually be permanent; the FastISel does pretty much everything we would ever want,
at least in the foreseeable future.
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
(FTL):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileBlock):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileJSConstant):
(LowerDFGToLLVM):
(JSC::FTL::LowerDFGToLLVM::compileJump):
(JSC::FTL::LowerDFGToLLVM::compileReturn):
(JSC::FTL::LowerDFGToLLVM::compileForceOSRExit):
* runtime/Options.h:
(JSC):
2013-05-10 Filip Pizlo <fpizlo@apple.com>
fourthTier: FTL should support CompareStrictEqConstant
......
......@@ -2033,9 +2033,9 @@
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
932F5BD90822A1C700736975 /* JavaScriptCore.framework */,
932F5BE10822A1C700736975 /* jsc */,
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
141211200A48793C00480255 /* minidom */,
14BD59BF0A3E8F9000BAF59C /* testapi */,
6511230514046A4C002B101D /* testRegExp */,
......@@ -3379,6 +3379,7 @@
0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
0FB105861675481200F8AB6E /* ExitKind.h in Headers */,
0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */,
0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */,
0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */,
0FEA0A1F1708B00700BB722C /* FTLAbstractHeapRepository.h in Headers */,
......@@ -3405,6 +3406,7 @@
0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
0F235BE417178E1C00690C7F /* FTLValueFormat.h in Headers */,
0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
0F235BE617178E1C00690C7F /* FTLValueSource.h in Headers */,
BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */,
0FF0F1A016B72A1A005DF95B /* FunctionExecutableDump.h in Headers */,
......@@ -3507,7 +3509,6 @@
0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */,
BC18C42A0E16F5CD00B34460 /* JSType.h in Headers */,
6507D29E0E871E5E00D7D896 /* JSTypeInfo.h in Headers */,
0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
86E3C612167BABD7006D760A /* JSValue.h in Headers */,
86E3C61B167BABEE006D760A /* JSValueInternal.h in Headers */,
BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */,
......@@ -3614,7 +3615,6 @@
0FF729BE166AD360000F5BA3 /* ProfilerExecutionCounter.h in Headers */,
0FF729BF166AD360000F5BA3 /* ProfilerOrigin.h in Headers */,
0FF729C0166AD360000F5BA3 /* ProfilerOriginStack.h in Headers */,
0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */,
0FB1058C1675483300F8AB6E /* ProfilerOSRExit.h in Headers */,
0FB1058E1675483A00F8AB6E /* ProfilerOSRExitSite.h in Headers */,
0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
......
......@@ -32,6 +32,108 @@ namespace JSC { namespace FTL {
using namespace DFG;
inline bool canCompile(Node* node)
{
switch (node->op()) {
case JSConstant:
case WeakJSConstant:
case GetLocal:
case SetLocal:
case MovHintAndCheck:
case MovHint:
case ZombieHint:
case Phantom:
case Flush:
case PhantomLocal:
case SetArgument:
case Return:
case BitAnd:
case BitOr:
case BitXor:
case BitRShift:
case BitLShift:
case BitURShift:
case CheckStructure:
case StructureTransitionWatchpoint:
case PutStructure:
case PhantomPutStructure:
case GetButterfly:
case GetByOffset:
case PutByOffset:
case GetGlobalVar:
case PutGlobalVar:
case ValueAdd:
case ArithAdd:
case ArithSub:
case ArithMul:
case ArithNegate:
case UInt32ToNumber:
case Int32ToDouble:
case CompareEqConstant:
case CompareStrictEqConstant:
case Jump:
case ForceOSRExit:
// These are OK.
break;
case GetArrayLength:
switch (node->arrayMode().type()) {
case Array::Int32:
case Array::Double:
case Array::Contiguous:
break;
default:
return false;
}
break;
case GetByVal:
switch (node->arrayMode().type()) {
case Array::ForceExit:
return true;
case Array::Int32:
case Array::Double:
case Array::Contiguous:
break;
default:
return false;
}
switch (node->arrayMode().speculation()) {
case Array::SaneChain:
case Array::InBounds:
break;
default:
return false;
}
break;
case CompareEq:
case CompareStrictEq:
if (node->isBinaryUseKind(Int32Use))
break;
if (node->isBinaryUseKind(NumberUse))
break;
if (node->isBinaryUseKind(ObjectUse))
break;
return false;
case CompareLess:
case CompareLessEq:
case CompareGreater:
case CompareGreaterEq:
if (node->isBinaryUseKind(Int32Use))
break;
if (node->isBinaryUseKind(NumberUse))
break;
return false;
case Branch:
case LogicalNot:
if (node->child1().useKind() == BooleanUse)
break;
return false;
default:
// Don't know how to handle anything else.
return false;
}
return true;
}
bool canCompile(Graph& graph)
{
for (BlockIndex blockIndex = graph.m_blocks.size(); blockIndex--;) {
......@@ -65,99 +167,8 @@ bool canCompile(Graph& graph)
}
}
switch (node->op()) {
case JSConstant:
case WeakJSConstant:
case GetLocal:
case SetLocal:
case MovHintAndCheck:
case MovHint:
case ZombieHint:
case Phantom:
case Flush:
case PhantomLocal:
case SetArgument:
case Return:
case BitAnd:
case BitOr:
case BitXor:
case BitRShift:
case BitLShift:
case BitURShift:
case CheckStructure:
case StructureTransitionWatchpoint:
case PutStructure:
case PhantomPutStructure:
case GetButterfly:
case GetByOffset:
case PutByOffset:
case GetGlobalVar:
case PutGlobalVar:
case ValueAdd:
case ArithAdd:
case ArithSub:
case ArithMul:
case ArithNegate:
case UInt32ToNumber:
case Int32ToDouble:
case CompareEqConstant:
case CompareStrictEqConstant:
// These are OK.
break;
case GetArrayLength:
switch (node->arrayMode().type()) {
case Array::Int32:
case Array::Double:
case Array::Contiguous:
break;
default:
return false;
}
break;
case GetByVal:
switch (node->arrayMode().type()) {
case Array::Int32:
case Array::Double:
case Array::Contiguous:
break;
default:
return false;
}
switch (node->arrayMode().speculation()) {
case Array::SaneChain:
case Array::InBounds:
break;
default:
return false;
}
break;
case CompareEq:
case CompareStrictEq:
if (node->isBinaryUseKind(Int32Use))
break;
if (node->isBinaryUseKind(NumberUse))
break;
if (node->isBinaryUseKind(ObjectUse))
break;
if (!canCompile(node))
return false;
case CompareLess:
case CompareLessEq:
case CompareGreater:
case CompareGreaterEq:
if (node->isBinaryUseKind(Int32Use))
break;
if (node->isBinaryUseKind(NumberUse))
break;
return false;
case Branch:
case LogicalNot:
if (node->child1().useKind() == BooleanUse)
break;
return false;
default:
// Don't know how to handle anything else.
return false;
}
}
}
......
......@@ -48,6 +48,7 @@ void compile(State& state)
options.OptLevel = Options::llvmOptimizationLevel();
options.NoFramePointerElim = true;
options.CodeModel = LLVMCodeModelSmall;
options.EnableFastISel = Options::enableLLVMFastISel();
if (LLVMCreateMCJITCompilerForModule(&state.engine, state.module, &options, sizeof(options), &error)) {
dataLog("FATAL: Could not create LLVM execution engine: ", error, "\n");
......
......@@ -243,12 +243,19 @@ private:
m_state.reset();
m_state.beginBasicBlock(m_highBlock);
for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex)
compileNode(m_nodeIndex);
for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
if (!compileNode(m_nodeIndex))
break;
}
}
void compileNode(unsigned nodeIndex)
bool compileNode(unsigned nodeIndex)
{
if (!m_state.isValid()) {
m_out.unreachable();
return false;
}
m_node = m_highBlock->at(nodeIndex);
m_codeOrigin = m_node->codeOrigin;
......@@ -288,9 +295,6 @@ private:
case PhantomLocal:
case SetArgument:
break;
case Return:
compileReturn();
break;
case ArithAdd:
case ValueAdd:
compileAdd();
......@@ -388,9 +392,18 @@ private:
case LogicalNot:
compileLogicalNot();
break;
case Jump:
compileJump();
break;
case Branch:
compileBranch();
break;
case Return:
compileReturn();
break;
case ForceOSRExit:
compileForceOSRExit();
break;
default:
RELEASE_ASSERT_NOT_REACHED();
break;
......@@ -404,11 +417,17 @@ private:
if (shouldExecuteEffects)
m_state.executeEffects(nodeIndex);
return true;
}
void compileJSConstant()
{
m_jsValueValues.add(m_node, m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(m_node))));
JSValue value = m_graph.valueOfJSConstant(m_node);
if (value.isDouble())
m_doubleValues.add(m_node, m_out.constDouble(value.asDouble()));
else
m_jsValueValues.add(m_node, m_out.constInt64(JSValue::encode(value)));
}
void compileWeakJSConstant()
......@@ -555,13 +574,6 @@ private:
DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
}
void compileReturn()
{
// FIXME: have a real epilogue when we switch to using our calling convention.
// https://bugs.webkit.org/show_bug.cgi?id=113621
m_out.ret(lowJSValue(m_node->child1()));
}
void compileAdd()
{
switch (m_node->binaryUseKind()) {
......@@ -1123,6 +1135,11 @@ private:
}
}
void compileJump()
{
m_out.jump(m_blocks.get(m_graph.m_blocks[m_node->takenBlockIndex()].get()));
}
void compileBranch()
{
switch (m_node->child1().useKind()) {
......@@ -1140,6 +1157,18 @@ private:
}
}
void compileReturn()
{
// FIXME: have a real epilogue when we switch to using our calling convention.
// https://bugs.webkit.org/show_bug.cgi?id=113621
m_out.ret(lowJSValue(m_node->child1()));
}
void compileForceOSRExit()
{
terminate(InadequateCoverage);
}
enum EqualNullOrUndefinedMode { EqualNull, EqualUndefined, EqualNullOrUndefined };
void equalNullOrUndefined(Edge edge, EqualNullOrUndefinedMode mode)
{
......
......@@ -113,6 +113,7 @@ typedef OptionRange optionRange;
v(bool, useExperimentalFTL, false) \
v(bool, useFTLTBAA, true) \
v(bool, enableLLVMLICM, true) \
v(bool, enableLLVMFastISel, true) \
v(unsigned, llvmOptimizationLevel, 2) \
\
v(bool, enableProfiler, false) \
......
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