Commit a61ec35b authored by mark.lam@apple.com's avatar mark.lam@apple.com

Change baseline JIT watchdog timer check to use the proper fast slow path

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

Reviewed by Oliver Hunt.

SH4 parts contributed by Julien Brianceau.

* assembler/ARMAssembler.h:
* assembler/MacroAssemblerARM.h:
* assembler/MacroAssemblerARMv7.h:
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::branchAdd32):
* assembler/MacroAssemblerSH4.h:
(JSC::MacroAssemblerSH4::branchAdd32):
* assembler/MacroAssemblerX86Common.h:
* assembler/SH4Assembler.h:
* jit/JIT.cpp:
(JSC::JIT::emitEnterOptimizationCheck):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
(JSC::JIT::emitEnterOptimizationCheck):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_loop_hint):
(JSC::JIT::emitSlow_op_loop_hint):
(JSC::JIT::emit_op_enter):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enter):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@148893 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b3fa3406
2013-04-22 Mark Lam <mark.lam@apple.com>
Change baseline JIT watchdog timer check to use the proper fast slow path
infrastructure.
https://bugs.webkit.org/show_bug.cgi?id=114963.
Reviewed by Oliver Hunt.
SH4 parts contributed by Julien Brianceau.
* assembler/ARMAssembler.h:
* assembler/MacroAssemblerARM.h:
* assembler/MacroAssemblerARMv7.h:
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::branchAdd32):
* assembler/MacroAssemblerSH4.h:
(JSC::MacroAssemblerSH4::branchAdd32):
* assembler/MacroAssemblerX86Common.h:
* assembler/SH4Assembler.h:
* jit/JIT.cpp:
(JSC::JIT::emitEnterOptimizationCheck):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
(JSC::JIT::emitEnterOptimizationCheck):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_loop_hint):
(JSC::JIT::emitSlow_op_loop_hint):
(JSC::JIT::emit_op_enter):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enter):
2013-04-22 Andreas Kling <akling@apple.com>
Shrink baseline size of WTF::Vector on 64-bit by switching to unsigned capacity and size.
......@@ -107,21 +107,21 @@ namespace JSC {
// ARM conditional constants
typedef enum {
EQ = 0x00000000, // Zero
NE = 0x10000000, // Non-zero
CS = 0x20000000,
CC = 0x30000000,
MI = 0x40000000,
PL = 0x50000000,
VS = 0x60000000,
VC = 0x70000000,
HI = 0x80000000,
LS = 0x90000000,
GE = 0xa0000000,
LT = 0xb0000000,
GT = 0xc0000000,
LE = 0xd0000000,
AL = 0xe0000000
EQ = 0x00000000, // Zero / Equal.
NE = 0x10000000, // Non-zero / Not equal.
CS = 0x20000000, // Unsigned higher or same.
CC = 0x30000000, // Unsigned lower.
MI = 0x40000000, // Negative.
PL = 0x50000000, // Positive or zero.
VS = 0x60000000, // Overflowed.
VC = 0x70000000, // Not overflowed.
HI = 0x80000000, // Unsigned higher.
LS = 0x90000000, // Unsigned lower or same.
GE = 0xa0000000, // Signed greater than or equal.
LT = 0xb0000000, // Signed less than.
GT = 0xc0000000, // Signed greater than.
LE = 0xd0000000, // Signed less than or euqal.
AL = 0xe0000000 // Unconditional / Always execute.
} Condition;
// ARM instruction constants
......
......@@ -58,6 +58,7 @@ public:
enum ResultCondition {
Overflow = ARMAssembler::VS,
Signed = ARMAssembler::MI,
PositiveOrZero = ARMAssembler::PL,
Zero = ARMAssembler::EQ,
NonZero = ARMAssembler::NE
};
......
......@@ -119,6 +119,7 @@ public:
enum ResultCondition {
Overflow = ARMv7Assembler::ConditionVS,
Signed = ARMv7Assembler::ConditionMI,
PositiveOrZero = ARMAssembler::PL,
Zero = ARMv7Assembler::ConditionEQ,
NonZero = ARMv7Assembler::ConditionNE
};
......
......@@ -80,6 +80,7 @@ public:
enum ResultCondition {
Overflow,
Signed,
PositiveOrZero,
Zero,
NonZero
};
......@@ -1509,7 +1510,7 @@ public:
Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
if (cond == Overflow) {
/*
move dest, dataTemp
......@@ -1542,6 +1543,12 @@ public:
m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
}
if (cond == PositiveOrZero) {
add32(src, dest);
// Check if dest is negative.
m_assembler.slt(cmpTempRegister, MIPSRegisters::zero, dest);
return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
}
if (cond == Zero) {
add32(src, dest);
return branchEqual(dest, MIPSRegisters::zero);
......
......@@ -68,6 +68,7 @@ public:
enum ResultCondition {
Overflow = SH4Assembler::OF,
Signed = SH4Assembler::SI,
PositiveOrZero = SH4Assembler::NS,
Zero = SH4Assembler::EQ,
NonZero = SH4Assembler::NE
};
......@@ -1920,6 +1921,12 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
return branchFalse();
}
if (cond == PositiveOrZero) {
m_assembler.addlRegReg(src, dest);
m_assembler.cmppz(dest);
return branchTrue();
}
m_assembler.addlRegReg(src, dest);
compare32(0, dest, Equal);
......@@ -1956,6 +1963,11 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
return branchFalse();
}
if (cond == PositiveOrZero) {
m_assembler.cmppz(dest);
return branchTrue();
}
compare32(0, dest, Equal);
if (cond == NonZero) // NotEqual
......
......@@ -68,6 +68,7 @@ public:
enum ResultCondition {
Overflow = X86Assembler::ConditionO,
Signed = X86Assembler::ConditionS,
PositiveOrZero = X86Assembler::ConditionNS,
Zero = X86Assembler::ConditionE,
NonZero = X86Assembler::ConditionNE
};
......
......@@ -341,22 +341,23 @@ public:
typedef enum {
EQ = 0x0, // Equal
NE = 0x1, // Not Equal
HS = 0x2, // Unsigend Greater Than equal
HI = 0x3, // Unsigend Greater Than
LS = 0x4, // Unsigend Lower or Same
LI = 0x5, // Unsigend Lower
HS = 0x2, // Unsigned Greater Than equal
HI = 0x3, // Unsigned Greater Than
LS = 0x4, // Unsigned Lower or Same
LI = 0x5, // Unsigned Lower
GE = 0x6, // Greater or Equal
LT = 0x7, // Less Than
GT = 0x8, // Greater Than
LE = 0x9, // Less or Equal
OF = 0xa, // OverFlow
SI = 0xb, // Signed
EQU= 0xc, // Equal or unordered(NaN)
NEU= 0xd,
GTU= 0xe,
GEU= 0xf,
LTU= 0x10,
LEU= 0x11,
NS = 0xc, // Not Signed
EQU= 0xd, // Equal or unordered(NaN)
NEU= 0xe,
GTU= 0xf,
GEU= 0x10,
LTU= 0x11,
LEU= 0x12,
} Condition;
// Opaque label types
......
......@@ -103,32 +103,20 @@ JIT::JIT(VM* vm, CodeBlock* codeBlock)
}
#if ENABLE(DFG_JIT)
void JIT::emitOptimizationCheck(OptimizationCheckKind kind)
void JIT::emitEnterOptimizationCheck()
{
if (!canBeOptimized())
return;
Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop() : Options::executionCounterIncrementForReturn()), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
Jump skipOptimize = branchAdd32(Signed, TrustedImm32(Options::executionCounterIncrementForReturn()), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
JITStubCall stubCall(this, cti_optimize);
stubCall.addArgument(TrustedImm32(m_bytecodeOffset));
if (kind == EnterOptimizationCheck)
ASSERT(!m_bytecodeOffset);
ASSERT(!m_bytecodeOffset);
stubCall.call();
skipOptimize.link(this);
}
#endif
void JIT::emitWatchdogTimerCheck()
{
if (!m_vm->watchdog.isEnabled())
return;
Jump skipCheck = branchTest8(Zero, AbsoluteAddress(m_vm->watchdog.timerDidFireAddress()));
JITStubCall stubCall(this, cti_handle_watchdog_timer);
stubCall.call();
skipCheck.link(this);
}
#define NEXT_OPCODE(name) \
m_bytecodeOffset += OPCODE_LENGTH(name); \
break;
......@@ -473,6 +461,7 @@ void JIT::privateCompileSlowCases()
DEFINE_SLOWCASE_OP(op_jngreater)
DEFINE_SLOWCASE_OP(op_jngreatereq)
DEFINE_SLOWCASE_OP(op_jtrue)
DEFINE_SLOWCASE_OP(op_loop_hint)
DEFINE_SLOWCASE_OP(op_lshift)
DEFINE_SLOWCASE_OP(op_mod)
DEFINE_SLOWCASE_OP(op_mul)
......
......@@ -780,6 +780,7 @@ namespace JSC {
void emitSlow_op_jngreater(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_jngreatereq(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_loop_hint(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
......@@ -852,13 +853,11 @@ namespace JSC {
// Loads the character value of a single character string into dst.
void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures);
enum OptimizationCheckKind { LoopOptimizationCheck, EnterOptimizationCheck };
#if ENABLE(DFG_JIT)
void emitOptimizationCheck(OptimizationCheckKind);
void emitEnterOptimizationCheck();
#else
void emitOptimizationCheck(OptimizationCheckKind) { }
void emitEnterOptimizationCheck() { }
#endif
void emitWatchdogTimerCheck();
#ifndef NDEBUG
void printBytecodeOperandTypes(unsigned src1, unsigned src2);
......@@ -944,12 +943,6 @@ namespace JSC {
#endif
} JIT_CLASS_ALIGNMENT;
inline void JIT::emit_op_loop_hint(Instruction*)
{
emitWatchdogTimerCheck();
emitOptimizationCheck(LoopOptimizationCheck);
}
} // namespace JSC
#endif // ENABLE(JIT)
......
......@@ -481,6 +481,52 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
isZero.link(this);
}
void JIT::emit_op_loop_hint(Instruction*)
{
// Emit the watchdog timer check:
if (m_vm->watchdog.isEnabled())
addSlowCase(branchTest8(NonZero, AbsoluteAddress(m_vm->watchdog.timerDidFireAddress())));
// Emit the JIT optimization check:
if (canBeOptimized())
addSlowCase(branchAdd32(PositiveOrZero, TrustedImm32(Options::executionCounterIncrementForLoop()),
AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter())));
}
void JIT::emitSlow_op_loop_hint(Instruction*, Vector<SlowCaseEntry>::iterator& iter)
{
// Emit the slow path of the watchdog timer check:
if (m_vm->watchdog.isEnabled()) {
linkSlowCase(iter);
JITStubCall stubCall(this, cti_handle_watchdog_timer);
stubCall.call();
#if ENABLE(DFG_JIT)
if (canBeOptimized()) {
Jump doOptimize = branchAdd32(PositiveOrZero, TrustedImm32(Options::executionCounterIncrementForLoop()),
AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_loop_hint));
doOptimize.link(this);
} else
#endif
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_loop_hint));
}
#if ENABLE(DFG_JIT)
// Emit the slow path for the JIT optimization check:
if (canBeOptimized()) {
linkSlowCase(iter);
JITStubCall stubCall(this, cti_optimize);
stubCall.addArgument(TrustedImm32(m_bytecodeOffset));
stubCall.call();
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_loop_hint));
}
#endif
}
void JIT::emit_op_neq(Instruction* currentInstruction)
{
emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
......@@ -863,7 +909,7 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)
void JIT::emit_op_enter(Instruction*)
{
emitOptimizationCheck(EnterOptimizationCheck);
emitEnterOptimizationCheck();
// Even though CTI doesn't use them, we initialize our constant
// registers to zap stale pointers, to avoid unnecessarily prolonging
......
......@@ -1113,7 +1113,7 @@ void JIT::emit_op_debug(Instruction* currentInstruction)
void JIT::emit_op_enter(Instruction*)
{
emitOptimizationCheck(EnterOptimizationCheck);
emitEnterOptimizationCheck();
// Even though JIT code doesn't use them, we initialize our constant
// registers to zap stale pointers, to avoid unnecessarily prolonging
......
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