Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (159426 => 159427)
--- trunk/Source/_javascript_Core/ChangeLog 2013-11-18 17:06:49 UTC (rev 159426)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-11-18 17:56:27 UTC (rev 159427)
@@ -1,3 +1,34 @@
+2013-11-18 Michael Saboff <[email protected]>
+
+ Crash in virtualForThunkGenerator generated code on ARM64
+ https://bugs.webkit.org/show_bug.cgi?id=124447
+
+ Reviewed by Geoffrey Garen.
+
+ The baseline JIT generates slow path call code with the caller in regT0. The DFG
+ generates call code with the caller in nonArgGPR0. The virtualForThunkGenerator
+ generates code with the caller in nonArgGPR0. For X86 and X86_64, regT0 and nonArgGPR0
+ are the same CPU register, eax. For other platforms this isn't the case. The same
+ issue exists for JSVALUE32_64 ports as well, where there also is an issue with the callee
+ tag registers being regT1 and nonArgGPR1 in the various locations.
+
+ Changed nonArgGPR0, nonArgGPR1 and nonArgGPR2 for X86 and X86_64 to not match up with
+ regT0-2. Changing these registers will cause a crash on all ports should we have a
+ similar problem in the future. Changed the DFG call generating code to use regT0 and
+ regT1. Now all slow path call code is generated using regT0 and for JSVALUE32_64 regT1.
+ Added r12 to X86_64 as a new temp register (regT9) and moved r13 down to regT10.
+ The new temp register decreases the likelihood of inadvertant register overlap.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * jit/GPRInfo.h:
+ (JSC::GPRInfo::toRegister):
+ (JSC::GPRInfo::toIndex):
+ * jit/ThunkGenerators.cpp:
+ (JSC::virtualForThunkGenerator):
+
2013-11-18 Balazs Kilvady <[email protected]>
Add missing load8/branch8 with AbsoluteAddress parameter to MIPS port.
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (159426 => 159427)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2013-11-18 17:06:49 UTC (rev 159426)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2013-11-18 17:56:27 UTC (rev 159427)
@@ -701,16 +701,17 @@
slowPath.link(&m_jit);
- if (calleeTagGPR == GPRInfo::nonArgGPR0) {
- if (calleePayloadGPR == GPRInfo::nonArgGPR1)
- m_jit.swap(GPRInfo::nonArgGPR1, GPRInfo::nonArgGPR0);
+ // Callee payload needs to be in regT0, tag in regT1
+ if (calleeTagGPR == GPRInfo::regT0) {
+ if (calleePayloadGPR == GPRInfo::regT1)
+ m_jit.swap(GPRInfo::regT1, GPRInfo::regT0);
else {
- m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
- m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
+ m_jit.move(calleeTagGPR, GPRInfo::regT1);
+ m_jit.move(calleePayloadGPR, GPRInfo::regT0);
}
} else {
- m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
- m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
+ m_jit.move(calleePayloadGPR, GPRInfo::regT0);
+ m_jit.move(calleeTagGPR, GPRInfo::regT1);
}
JITCompiler::Call slowCall = m_jit.nearCall();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (159426 => 159427)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2013-11-18 17:06:49 UTC (rev 159426)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2013-11-18 17:56:27 UTC (rev 159427)
@@ -723,7 +723,7 @@
slowPath.link(&m_jit);
- m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
+ m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
JITCompiler::Call slowCall = m_jit.nearCall();
done.link(&m_jit);
Modified: trunk/Source/_javascript_Core/jit/GPRInfo.h (159426 => 159427)
--- trunk/Source/_javascript_Core/jit/GPRInfo.h 2013-11-18 17:06:49 UTC (rev 159426)
+++ trunk/Source/_javascript_Core/jit/GPRInfo.h 2013-11-18 17:56:27 UTC (rev 159427)
@@ -305,9 +305,9 @@
// These constants provide the names for the general purpose argument & return value registers.
static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
- static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
- static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
- static const GPRReg nonArgGPR2 = X86Registers::esi; // regT4
+ static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
+ static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
+ static const GPRReg nonArgGPR2 = X86Registers::ebx; // regT3
static const GPRReg returnValueGPR = X86Registers::eax; // regT0
static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
@@ -355,7 +355,7 @@
class GPRInfo {
public:
typedef GPRReg RegisterType;
- static const unsigned numberOfRegisters = 10;
+ static const unsigned numberOfRegisters = 11;
static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
// Note: regT3 is required to be callee-preserved.
@@ -375,7 +375,8 @@
static const GPRReg regT6 = X86Registers::r8;
static const GPRReg regT7 = X86Registers::r9;
static const GPRReg regT8 = X86Registers::r10;
- static const GPRReg regT9 = X86Registers::r13;
+ static const GPRReg regT9 = X86Registers::r12;
+ static const GPRReg regT10 = X86Registers::r13;
// These constants provide the names for the general purpose argument & return value registers.
#if !OS(WINDOWS)
static const GPRReg argumentGPR0 = X86Registers::edi; // regT4
@@ -390,9 +391,9 @@
static const GPRReg argumentGPR2 = X86Registers::r8; // regT6
static const GPRReg argumentGPR3 = X86Registers::r9; // regT7
#endif
- static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0
+ static const GPRReg nonArgGPR0 = X86Registers::r10; // regT8
static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
- static const GPRReg nonArgGPR2 = X86Registers::r10; // regT8
+ static const GPRReg nonArgGPR2 = X86Registers::r12; // regT9
static const GPRReg returnValueGPR = X86Registers::eax; // regT0
static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
@@ -400,7 +401,7 @@
static GPRReg toRegister(unsigned index)
{
ASSERT(index < numberOfRegisters);
- static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9 };
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9, regT10 };
return registerForIndex[index];
}
@@ -419,7 +420,7 @@
{
ASSERT(reg != InvalidGPRReg);
ASSERT(static_cast<int>(reg) < 16);
- static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, 9, InvalidIndex, InvalidIndex };
+ static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
return indexForRegister[reg];
}
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (159426 => 159427)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2013-11-18 17:06:49 UTC (rev 159426)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2013-11-18 17:56:27 UTC (rev 159427)
@@ -147,6 +147,7 @@
static MacroAssemblerCodeRef virtualForThunkGenerator(
VM* vm, CodeSpecializationKind kind)
{
+ // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
// The return address is on the stack, or in the link register. We will hence
// jump to the callee, or save the return address to the call frame while we
// make a C++ function call to the appropriate JIT operation.
@@ -161,14 +162,14 @@
#if USE(JSVALUE64)
slowCase.append(
jit.branchTest64(
- CCallHelpers::NonZero, GPRInfo::nonArgGPR0, GPRInfo::tagMaskRegister));
+ CCallHelpers::NonZero, GPRInfo::regT0, GPRInfo::tagMaskRegister));
#else
slowCase.append(
jit.branch32(
- CCallHelpers::NotEqual, GPRInfo::nonArgGPR1,
+ CCallHelpers::NotEqual, GPRInfo::regT1,
CCallHelpers::TrustedImm32(JSValue::CellTag)));
#endif
- jit.loadPtr(CCallHelpers::Address(GPRInfo::nonArgGPR0, JSCell::structureOffset()), GPRInfo::nonArgGPR2);
+ jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSCell::structureOffset()), GPRInfo::nonArgGPR2);
slowCase.append(
jit.branchPtr(
CCallHelpers::NotEqual,
@@ -178,7 +179,7 @@
// Now we know we have a JSFunction.
jit.loadPtr(
- CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfExecutable()),
+ CCallHelpers::Address(GPRInfo::regT0, JSFunction::offsetOfExecutable()),
GPRInfo::nonArgGPR2);
slowCase.append(
jit.branch32(
@@ -191,17 +192,17 @@
// call.
jit.loadPtr(
- CCallHelpers::Address(GPRInfo::nonArgGPR0, JSFunction::offsetOfScopeChain()),
- GPRInfo::nonArgGPR1);
+ CCallHelpers::Address(GPRInfo::regT0, JSFunction::offsetOfScopeChain()),
+ GPRInfo::regT1);
#if USE(JSVALUE64)
jit.store64(
- GPRInfo::nonArgGPR1,
+ GPRInfo::regT1,
CCallHelpers::Address(
GPRInfo::callFrameRegister,
static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
#else
jit.storePtr(
- GPRInfo::nonArgGPR1,
+ GPRInfo::regT1,
CCallHelpers::Address(
GPRInfo::callFrameRegister,
static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain +