Diff
Modified: branches/dfgFourthTier/Source/_javascript_Core/ChangeLog (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ChangeLog 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ChangeLog 2013-06-17 18:17:47 UTC (rev 151649)
@@ -1,3 +1,37 @@
+2013-06-17 Filip Pizlo <[email protected]>
+
+ fourthTier: FTL should support Switch
+ https://bugs.webkit.org/show_bug.cgi?id=117704
+
+ Reviewed by Oliver Hunt.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::clearImmediateSwitchJumpTables):
+ * ftl/FTLAbbreviations.h:
+ (JSC::FTL::buildFPToSI):
+ (JSC::FTL::buildSwitch):
+ (JSC::FTL::addCase):
+ (FTL):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLink.cpp:
+ (JSC::FTL::link):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileSwitch):
+ (LowerDFGToLLVM):
+ * ftl/FTLOutput.h:
+ (JSC::FTL::Output::fpToInt):
+ (JSC::FTL::Output::fpToInt32):
+ (Output):
+ (JSC::FTL::Output::switchInstruction):
+ * ftl/FTLSwitchCase.h: Added.
+ (FTL):
+ (SwitchCase):
+ (JSC::FTL::SwitchCase::SwitchCase):
+ (JSC::FTL::SwitchCase::value):
+ (JSC::FTL::SwitchCase::target):
+
2013-06-15 Filip Pizlo <[email protected]>
fourthTier: Add CFG simplification for Switch
Modified: branches/dfgFourthTier/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-06-17 18:17:47 UTC (rev 151649)
@@ -167,6 +167,7 @@
0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680CF14BBB3D100BFE272 /* LLIntData.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */; };
0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F46E6B9176F89DB00E1F755 /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6B7176F89D900E1F755 /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F493AF816D0CAD10084508B /* SourceProvider.cpp */; };
0F4E1A0E173AEDDC007EE2D3 /* IntendedStructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4E1A0C173AEDDC007EE2D3 /* IntendedStructureChain.cpp */; };
0F4E1A0F173AEDDC007EE2D3 /* IntendedStructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4E1A0D173AEDDC007EE2D3 /* IntendedStructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1167,6 +1168,7 @@
0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = "<group>"; };
0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = "<group>"; };
0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; };
+ 0F46E6B7176F89D900E1F755 /* FTLSwitchCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSwitchCase.h; path = ftl/FTLSwitchCase.h; sourceTree = "<group>"; };
0F493AF816D0CAD10084508B /* SourceProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProvider.cpp; sourceTree = "<group>"; };
0F4E1A0C173AEDDC007EE2D3 /* IntendedStructureChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntendedStructureChain.cpp; sourceTree = "<group>"; };
0F4E1A0D173AEDDC007EE2D3 /* IntendedStructureChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntendedStructureChain.h; sourceTree = "<group>"; };
@@ -2207,6 +2209,7 @@
0FEA0A06170513DB00BB722C /* FTLOutput.h */,
0FEA0A151706BB9000BB722C /* FTLState.cpp */,
0FEA0A07170513DB00BB722C /* FTLState.h */,
+ 0F46E6B7176F89D900E1F755 /* FTLSwitchCase.h */,
0F235BCB17178E1C00690C7F /* FTLThunks.cpp */,
0F235BCC17178E1C00690C7F /* FTLThunks.h */,
0FEA0A1B1708B00700BB722C /* FTLTypedPointer.h */,
@@ -3773,6 +3776,7 @@
0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */,
0F5EE4E9175424AF009AE42D /* JSCTestRunnerUtils.h in Headers */,
+ 0F46E6B9176F89DB00E1F755 /* FTLSwitchCase.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -4206,7 +4210,6 @@
86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
FECE74571745456500FF9300 /* MacroAssemblerX86Common.cpp in Sources */,
86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
- 0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */,
0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */,
Modified: branches/dfgFourthTier/Source/_javascript_Core/bytecode/CodeBlock.h (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/bytecode/CodeBlock.h 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/bytecode/CodeBlock.h 2013-06-17 18:17:47 UTC (rev 151649)
@@ -696,6 +696,12 @@
size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
+ void clearImmediateSwitchJumpTables()
+ {
+ if (!m_rareData)
+ return;
+ m_rareData->m_immediateSwitchJumpTables.clear();
+ }
size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-06-17 18:17:47 UTC (rev 151649)
@@ -31,6 +31,7 @@
#if ENABLE(FTL_JIT)
#include "FTLAbbreviatedTypes.h"
+#include "FTLSwitchCase.h"
#include "FTLValueFromBlock.h"
namespace JSC { namespace FTL {
@@ -189,6 +190,7 @@
static inline LValue buildLoad(LBuilder builder, LValue pointer) { return LLVMBuildLoad(builder, pointer, ""); }
static inline LValue buildStore(LBuilder builder, LValue value, LValue pointer) { return LLVMBuildStore(builder, value, pointer); }
static inline LValue buildZExt(LBuilder builder, LValue value, LType type) { return LLVMBuildZExt(builder, value, type, ""); }
+static inline LValue buildFPToSI(LBuilder builder, LValue value, LType type) { return LLVMBuildFPToSI(builder, value, type, ""); }
static inline LValue buildSIToFP(LBuilder builder, LValue value, LType type) { return LLVMBuildSIToFP(builder, value, type, ""); }
static inline LValue buildUIToFP(LBuilder builder, LValue value, LType type) { return LLVMBuildUIToFP(builder, value, type, ""); }
static inline LValue buildIntCast(LBuilder builder, LValue value, LType type) { return LLVMBuildIntCast(builder, value, type, ""); }
@@ -225,6 +227,16 @@
static inline LValue buildSelect(LBuilder builder, LValue condition, LValue taken, LValue notTaken) { return LLVMBuildSelect(builder, condition, taken, notTaken, ""); }
static inline LValue buildBr(LBuilder builder, LBasicBlock destination) { return LLVMBuildBr(builder, destination); }
static inline LValue buildCondBr(LBuilder builder, LValue condition, LBasicBlock taken, LBasicBlock notTaken) { return LLVMBuildCondBr(builder, condition, taken, notTaken); }
+static inline LValue buildSwitch(LBuilder builder, LValue value, LBasicBlock fallThrough, unsigned numCases) { return LLVMBuildSwitch(builder, value, fallThrough, numCases); }
+static inline void addCase(LValue switchInst, LValue value, LBasicBlock target) { LLVMAddCase(switchInst, value, target); }
+template<typename VectorType>
+static inline LValue buildSwitch(LBuilder builder, LValue value, const VectorType& cases, LBasicBlock fallThrough)
+{
+ LValue result = buildSwitch(builder, value, fallThrough, cases.size());
+ for (unsigned i = 0; i < cases.size(); ++i)
+ addCase(result, cases[i].value(), cases[i].target());
+ return result;
+}
static inline LValue buildRet(LBuilder builder, LValue value) { return LLVMBuildRet(builder, value); }
static inline LValue buildUnreachable(LBuilder builder) { return LLVMBuildUnreachable(builder); }
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCapabilities.cpp (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-06-17 18:17:47 UTC (rev 151649)
@@ -79,6 +79,7 @@
case Jump:
case ForceOSRExit:
case ForwardForceOSRExit:
+ case Switch:
// These are OK.
break;
case GetArrayLength:
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLink.cpp (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLink.cpp 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLink.cpp 2013-06-17 18:17:47 UTC (rev 151649)
@@ -50,10 +50,15 @@
void link(State& state)
{
+ CodeBlock* codeBlock = state.graph.m_codeBlock;
+
+ // LLVM will create its own jump tables as needed.
+ codeBlock->clearImmediateSwitchJumpTables();
+
// Create the entrypoint.
// FIXME: This is a total kludge - LLVM should just use our calling convention.
// https://bugs.webkit.org/show_bug.cgi?id=113621
- CCallHelpers jit(&state.graph.m_vm, state.graph.m_codeBlock);
+ CCallHelpers jit(&state.graph.m_vm, codeBlock);
compileEntry(jit);
@@ -64,7 +69,7 @@
// Plant a check that sufficient space is available in the JSStack.
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
jit.addPtr(
- CCallHelpers::TrustedImm32(state.graph.m_codeBlock->m_numCalleeRegisters * sizeof(Register)),
+ CCallHelpers::TrustedImm32(codeBlock->m_numCalleeRegisters * sizeof(Register)),
GPRInfo::callFrameRegister, GPRInfo::regT1);
CCallHelpers::Jump stackCheck = jit.branchPtr(
CCallHelpers::Below,
@@ -102,7 +107,7 @@
GPRInfo::regT1);
jit.branch32(
CCallHelpers::AboveOrEqual, GPRInfo::regT1,
- CCallHelpers::TrustedImm32(state.graph.m_codeBlock->numParameters()))
+ CCallHelpers::TrustedImm32(codeBlock->numParameters()))
.linkTo(fromArityCheck, &jit);
jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
jit.poke(
@@ -118,9 +123,9 @@
jit.move(GPRInfo::regT0, GPRInfo::callFrameRegister);
jit.jump(fromArityCheck);
- OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(state.graph.m_vm, &jit, state.graph.m_codeBlock, JITCompilationMustSucceed));
+ OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(state.graph.m_vm, &jit, codeBlock, JITCompilationMustSucceed));
linkBuffer->link(callStackCheck, cti_stack_check);
- linkBuffer->link(callArityCheck, state.graph.m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
+ linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
state.finalizer->initializeEntrypointLinkBuffer(linkBuffer.release());
state.finalizer->initializeFunction(state.generatedFunction);
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-06-17 18:17:47 UTC (rev 151649)
@@ -414,6 +414,9 @@
case Branch:
compileBranch();
break;
+ case Switch:
+ compileSwitch();
+ break;
case Return:
compileReturn();
break;
@@ -1428,6 +1431,76 @@
m_blocks.get(m_graph.m_blocks[m_node->notTakenBlockIndex()].get()));
}
+ void compileSwitch()
+ {
+ SwitchData* data = ""
+ switch (data->kind) {
+ case SwitchImm: {
+ Vector<ValueFromBlock, 2> intValues;
+ LBasicBlock switchOnInts = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm int case"));
+
+ LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
+
+ switch (m_node->child1().useKind()) {
+ case Int32Use: {
+ intValues.append(m_out.anchor(lowInt32(m_node->child1())));
+ m_out.jump(switchOnInts);
+ break;
+ }
+
+ case UntypedUse: {
+ LBasicBlock isInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is int"));
+ LBasicBlock isNotInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is not int"));
+ LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is double"));
+
+ LValue boxedValue = lowJSValue(m_node->child1());
+ m_out.branch(isNotInt32(boxedValue), isNotInt, isInt);
+
+ LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
+
+ intValues.append(m_out.anchor(unboxInt32(boxedValue)));
+ m_out.jump(switchOnInts);
+
+ m_out.appendTo(isNotInt, isDouble);
+ m_out.branch(
+ isCellOrMisc(boxedValue),
+ m_blocks.get(m_graph.m_blocks[data->fallThrough].get()),
+ isDouble);
+
+ m_out.appendTo(isDouble, innerLastNext);
+ LValue doubleValue = unboxDouble(boxedValue);
+ LValue intInDouble = m_out.fpToInt32(doubleValue);
+ intValues.append(m_out.anchor(intInDouble));
+ m_out.branch(
+ m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
+ switchOnInts,
+ m_blocks.get(m_graph.m_blocks[data->fallThrough].get()));
+ break;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+
+ m_out.appendTo(switchOnInts, lastNext);
+ LValue intValue = m_out.phi(m_out.int32, intValues);
+
+ Vector<SwitchCase> cases;
+ for (unsigned i = 0; i < data->cases.size(); ++i) {
+ cases.append(SwitchCase(
+ m_out.constInt32(data->cases[i].value.asInt32()),
+ m_blocks.get(m_graph.m_blocks[data->cases[i].target].get())));
+ }
+
+ m_out.switchInstruction(
+ intValue, cases,
+ m_blocks.get(m_graph.m_blocks[data->fallThrough].get()));
+ return;
+ } }
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
void compileReturn()
{
// FIXME: have a real epilogue when we switch to using our calling convention.
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h (151648 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h 2013-06-17 18:06:27 UTC (rev 151648)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h 2013-06-17 18:17:47 UTC (rev 151649)
@@ -170,6 +170,8 @@
}
LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
+ LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
+ LValue fpToInt32(LValue value) { return fpToInt(value, int32); }
LValue intToFP(LValue value, LType type) { return buildSIToFP(m_builder, value, type); }
LValue intToDouble(LValue value) { return intToFP(value, doubleType); }
LValue unsignedToFP(LValue value, LType type) { return buildUIToFP(m_builder, value, type); }
@@ -325,6 +327,8 @@
void jump(LBasicBlock destination) { buildBr(m_builder, destination); }
void branch(LValue condition, LBasicBlock taken, LBasicBlock notTaken) { buildCondBr(m_builder, condition, taken, notTaken); }
+ template<typename VectorType>
+ void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough) { buildSwitch(m_builder, value, cases, fallThrough); }
void ret(LValue value) { buildRet(m_builder, value); }
void unreachable() { buildUnreachable(m_builder); }
Added: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLSwitchCase.h (0 => 151649)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLSwitchCase.h (rev 0)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLSwitchCase.h 2013-06-17 18:17:47 UTC (rev 151649)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FTLSwitchCase_h
+#define FTLSwitchCase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(FTL_JIT)
+
+#include "FTLAbbreviatedTypes.h"
+
+namespace JSC { namespace FTL {
+
+class SwitchCase {
+public:
+ SwitchCase(LValue value, LBasicBlock target)
+ : m_value(value)
+ , m_target(target)
+ {
+ }
+
+ LValue value() const { return m_value; }
+ LBasicBlock target() const { return m_target; }
+
+private:
+ LValue m_value;
+ LBasicBlock m_target;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLSwitchCase_h
+