Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (153229 => 153230)
--- trunk/Source/_javascript_Core/ChangeLog 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-07-25 04:03:05 UTC (rev 153230)
@@ -1,3 +1,37 @@
+2013-06-17 Filip Pizlo <fpi...@apple.com>
+
+ 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 <fpi...@apple.com>
fourthTier: Add CFG simplification for Switch
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (153229 => 153230)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-07-25 04:03:05 UTC (rev 153230)
@@ -809,6 +809,7 @@
A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; };
A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */; };
A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
@@ -1847,6 +1848,7 @@
A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSONObject.cpp; sourceTree = "<group>"; };
A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyDescriptor.h; sourceTree = "<group>"; };
A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyDescriptor.cpp; sourceTree = "<group>"; };
+ A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSwitchCase.h; path = ftl/FTLSwitchCase.h; sourceTree = "<group>"; };
A8A4748D151A8306004123FF /* libWTF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
@@ -2197,6 +2199,7 @@
0FEA09FC1705137F00BB722C /* ftl */ = {
isa = PBXGroup;
children = (
+ A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */,
0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */,
0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */,
0FEA0A171708B00700BB722C /* FTLAbstractHeap.cpp */,
@@ -3558,6 +3561,7 @@
86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */,
0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */,
0FAF7EFE165BA91F000C8455 /* JITDisassembler.h in Headers */,
+ A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
86CC85A10EE79A4700288682 /* JITInlines.h in Headers */,
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (153229 => 153230)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2013-07-25 04:03:05 UTC (rev 153230)
@@ -702,6 +702,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: trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h (153229 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-07-25 04:03:05 UTC (rev 153230)
@@ -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: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (153229 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-07-25 04:03:05 UTC (rev 153230)
@@ -79,6 +79,7 @@
case Jump:
case ForceOSRExit:
case ForwardForceOSRExit:
+ case Switch:
// These are OK.
break;
case GetArrayLength:
Modified: trunk/Source/_javascript_Core/ftl/FTLLink.cpp (153229 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLLink.cpp 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ftl/FTLLink.cpp 2013-07-25 04:03:05 UTC (rev 153230)
@@ -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: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (153229 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-07-25 04:03:05 UTC (rev 153230)
@@ -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: trunk/Source/_javascript_Core/ftl/FTLOutput.h (153229 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLOutput.h 2013-07-25 04:03:03 UTC (rev 153229)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h 2013-07-25 04:03:05 UTC (rev 153230)
@@ -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: trunk/Source/_javascript_Core/ftl/FTLSwitchCase.h (0 => 153230)
--- trunk/Source/_javascript_Core/ftl/FTLSwitchCase.h (rev 0)
+++ trunk/Source/_javascript_Core/ftl/FTLSwitchCase.h 2013-07-25 04:03:05 UTC (rev 153230)
@@ -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
+