Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (167645 => 167646)
--- trunk/Source/_javascript_Core/ChangeLog 2014-04-22 02:16:53 UTC (rev 167645)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-04-22 02:58:00 UTC (rev 167646)
@@ -1,3 +1,25 @@
+2014-04-21 Filip Pizlo <[email protected]>
+
+ Switch statements that skip the baseline JIT should work
+ https://bugs.webkit.org/show_bug.cgi?id=131965
+
+ Reviewed by Mark Hahnenberg.
+
+ * bytecode/JumpTable.h:
+ (JSC::SimpleJumpTable::ensureCTITable):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::emitSwitchIntJump):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_switch_imm):
+ (JSC::JIT::emit_op_switch_char):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_switch_imm):
+ (JSC::JIT::emit_op_switch_char):
+ * tests/stress/inline-llint-with-switch.js: Added.
+ (foo):
+ (bar):
+ (test):
+
2014-04-21 Mark Hahnenberg <[email protected]>
Arguments objects shouldn't need a destructor
Modified: trunk/Source/_javascript_Core/bytecode/JumpTable.h (167645 => 167646)
--- trunk/Source/_javascript_Core/bytecode/JumpTable.h 2014-04-22 02:16:53 UTC (rev 167645)
+++ trunk/Source/_javascript_Core/bytecode/JumpTable.h 2014-04-22 02:58:00 UTC (rev 167646)
@@ -94,6 +94,12 @@
}
#if ENABLE(JIT)
+ void ensureCTITable()
+ {
+ ASSERT(ctiOffsets.isEmpty() || ctiOffsets.size() == branchOffsets.size());
+ ctiOffsets.grow(branchOffsets.size());
+ }
+
inline CodeLocationLabel ctiForValue(int32_t value)
{
if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (167645 => 167646)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2014-04-22 02:16:53 UTC (rev 167645)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2014-04-22 02:58:00 UTC (rev 167646)
@@ -4947,6 +4947,7 @@
SwitchData* data, GPRReg value, GPRReg scratch)
{
SimpleJumpTable& table = m_jit.codeBlock()->switchJumpTable(data->switchTableIndex);
+ table.ensureCTITable();
m_jit.sub32(Imm32(table.min), value);
addBranch(
m_jit.branch32(JITCompiler::AboveOrEqual, value, Imm32(table.ctiOffsets.size())),
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (167645 => 167646)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2014-04-22 02:16:53 UTC (rev 167645)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2014-04-22 02:58:00 UTC (rev 167646)
@@ -646,7 +646,7 @@
// create jump table for switch destinations, track this switch statement.
SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Immediate));
- jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+ jumpTable->ensureCTITable();
emitGetVirtualRegister(scrutinee, regT0);
callOperation(operationSwitchImmWithUnknownKeyType, regT0, tableIndex);
@@ -662,7 +662,7 @@
// create jump table for switch destinations, track this switch statement.
SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Character));
- jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+ jumpTable->ensureCTITable();
emitGetVirtualRegister(scrutinee, regT0);
callOperation(operationSwitchCharWithUnknownKeyType, regT0, tableIndex);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (167645 => 167646)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2014-04-22 02:16:53 UTC (rev 167645)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2014-04-22 02:58:00 UTC (rev 167646)
@@ -933,7 +933,7 @@
// create jump table for switch destinations, track this switch statement.
SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Immediate));
- jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+ jumpTable->ensureCTITable();
emitLoad(scrutinee, regT1, regT0);
callOperation(operationSwitchImmWithUnknownKeyType, regT1, regT0, tableIndex);
@@ -949,7 +949,7 @@
// create jump table for switch destinations, track this switch statement.
SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Character));
- jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+ jumpTable->ensureCTITable();
emitLoad(scrutinee, regT1, regT0);
callOperation(operationSwitchCharWithUnknownKeyType, regT1, regT0, tableIndex);
Added: trunk/Source/_javascript_Core/tests/stress/inline-llint-with-switch.js (0 => 167646)
--- trunk/Source/_javascript_Core/tests/stress/inline-llint-with-switch.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/inline-llint-with-switch.js 2014-04-22 02:58:00 UTC (rev 167646)
@@ -0,0 +1,43 @@
+function foo(i) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ return 42;
+ default:
+ return "error";
+ }
+}
+
+function bar(p) {
+ if (p)
+ return foo(effectful42() - 42);
+ else
+ return 42;
+}
+
+noInline(bar);
+
+function test(p) {
+ var result = bar(p);
+ if (result != 42)
+ throw "Error: bad result: " + result;
+}
+
+// Make sure that the call to foo() looks like it has happened.
+for (var i = 0; i < 2; ++i)
+ test(true);
+
+// Warm up bar and cause inlining, but make sure that foo() doesn't get DFG'd.
+for (var i = 0; i < 10000; ++i)
+ test(false);
+
+// And finally test the switch statement.
+test(true);