Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (98404 => 98405)
--- trunk/Source/_javascript_Core/ChangeLog 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-10-25 23:06:13 UTC (rev 98405)
@@ -1,3 +1,34 @@
+2011-10-25 Gavin Barraclough <[email protected]>
+
+ Separate out function linking & exception check data structures.
+ https://bugs.webkit.org/show_bug.cgi?id=70858
+
+ Reviewed by Oliver Hunt.
+
+ This will make it easier to refactor the callOperation methods to spilt the value
+ representation specific handling from the cpu/calling-convention implementation.
+
+ * dfg/DFGJITCodeGenerator.h:
+ (JSC::DFG::appendCallWithExceptionCheck):
+ * dfg/DFGJITCodeGenerator32_64.cpp:
+ (JSC::DFG::JITCodeGenerator::emitCall):
+ * dfg/DFGJITCodeGenerator64.cpp:
+ (JSC::DFG::JITCodeGenerator::emitCall):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::compileBody):
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::CallLinkRecord::CallLinkRecord):
+ (JSC::DFG::CallExceptionRecord::CallExceptionRecord):
+ (JSC::DFG::JITCompiler::JITCompiler):
+ (JSC::DFG::JITCompiler::notifyCall):
+ (JSC::DFG::JITCompiler::appendCall):
+ (JSC::DFG::JITCompiler::addExceptionCheck):
+ (JSC::DFG::JITCompiler::addFastExceptionCheck):
+ * dfg/DFGJITCompiler32_64.cpp:
+ (JSC::DFG::JITCompiler::compileBody):
+ (JSC::DFG::JITCompiler::link):
+
2011-10-25 Filip Pizlo <[email protected]>
Tiered compilation may introduce dangling pointers in constant buffers
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-10-25 23:06:13 UTC (rev 98405)
@@ -1550,7 +1550,7 @@
JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
{
- return m_jit.appendCallWithExceptionCheck(function, at(m_compileIndex).codeOrigin);
+ return m_jit.addExceptionCheck(m_jit.appendCall(function), at(m_compileIndex).codeOrigin);
}
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
{
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-10-25 23:06:13 UTC (rev 98405)
@@ -1365,7 +1365,7 @@
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
m_jit.poke(GPRInfo::argumentGPR0);
- JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, at(m_compileIndex).codeOrigin);
+ JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
m_jit.move(Imm32(numPassedArgs), GPRInfo::regT1);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-10-25 23:06:13 UTC (rev 98405)
@@ -1311,7 +1311,7 @@
slowPath.link(&m_jit);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, at(m_compileIndex).codeOrigin);
+ JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
m_jit.move(Imm32(numPassedArgs), GPRInfo::regT1);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-10-25 23:06:13 UTC (rev 98405)
@@ -610,17 +610,18 @@
linkOSRExits(speculative);
- // Iterate over the m_calls vector, checking for exception checks,
- // and linking them to here.
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- Jump& exceptionCheck = m_calls[i].m_exceptionCheck;
+ // Iterate over the m_calls vector, checking for jumps to link.
+ bool didLinkExceptionCheck = false;
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ Jump& exceptionCheck = m_exceptionChecks[i].m_exceptionCheck;
if (exceptionCheck.isSet()) {
exceptionCheck.link(this);
- ++m_exceptionCheckCount;
+ didLinkExceptionCheck = true;
}
}
+
// If any exception checks were linked, generate code to lookup a handler.
- if (m_exceptionCheckCount) {
+ if (didLinkExceptionCheck) {
// lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
// an identifier for the operation that threw the exception, which we can use
// to look up handler information. The identifier we use is the return address
@@ -628,7 +629,7 @@
// available on the stack, just below the stack pointer!
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
peek(GPRInfo::argumentGPR1, -1);
- m_calls.append(CallRecord(call(), lookupExceptionHandler));
+ m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
// lookupExceptionHandler leaves the handler CallFrame* in the returnValueGPR,
// and the address of the handler in returnValueGPR2.
jump(GPRInfo::returnValueGPR2);
@@ -643,19 +644,15 @@
#endif
// Link all calls out from the JIT code to their respective functions.
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- if (m_calls[i].m_function.value())
- linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
- }
+ for (unsigned i = 0; i < m_calls.size(); ++i)
+ linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
if (m_codeBlock->needsCallReturnIndices()) {
- m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionCheckCount);
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- if (m_calls[i].m_handlesExceptions) {
- unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call);
- unsigned exceptionInfo = m_calls[i].m_codeOrigin.bytecodeIndex;
- m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
- }
+ m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+ unsigned exceptionInfo = m_exceptionChecks[i].m_codeOrigin.bytecodeIndex;
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h 2011-10-25 23:06:13 UTC (rev 98405)
@@ -63,47 +63,44 @@
};
#endif
-// === CallRecord ===
+// === CallLinkRecord ===
//
-// A record of a call out from JIT code to a helper function.
-// Every CallRecord contains a reference to the call instruction & the function
-// that it needs to be linked to. Calls that might throw an exception also record
-// the Jump taken on exception (unset if not present), and ExceptionInfo (presently
-// an unsigned, bytecode index) used to recover handler/source info.
-struct CallRecord {
- // Constructor for a call with no exception handler.
- CallRecord(MacroAssembler::Call call, FunctionPtr function)
+// A record of a call out from JIT code that needs linking to a helper function.
+// Every CallLinkRecord contains a reference to the call instruction & the function
+// that it needs to be linked to.
+struct CallLinkRecord {
+ CallLinkRecord(MacroAssembler::Call call, FunctionPtr function)
: m_call(call)
, m_function(function)
- , m_handlesExceptions(false)
{
}
- // Constructor for a call with an exception handler.
- CallRecord(MacroAssembler::Call call, FunctionPtr function, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
+ MacroAssembler::Call m_call;
+ FunctionPtr m_function;
+};
+
+// === CallExceptionRecord ===
+//
+// A record of a call out from JIT code that might throw an exception.
+// Calls that might throw an exception also record the Jump taken on exception
+// (unset if not present) and code origin used to recover handler/source info.
+struct CallExceptionRecord {
+ CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin)
: m_call(call)
- , m_function(function)
- , m_exceptionCheck(exceptionCheck)
, m_codeOrigin(codeOrigin)
- , m_handlesExceptions(true)
{
}
- // Constructor for a call that may cause exceptions, but which are handled
- // through some mechanism other than the in-line exception handler.
- CallRecord(MacroAssembler::Call call, FunctionPtr function, CodeOrigin codeOrigin)
+ CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
: m_call(call)
- , m_function(function)
+ , m_exceptionCheck(exceptionCheck)
, m_codeOrigin(codeOrigin)
- , m_handlesExceptions(true)
{
}
MacroAssembler::Call m_call;
- FunctionPtr m_function;
MacroAssembler::Jump m_exceptionCheck;
CodeOrigin m_codeOrigin;
- bool m_handlesExceptions;
};
// === JITCompiler ===
@@ -120,7 +117,6 @@
: m_globalData(globalData)
, m_graph(dfg)
, m_codeBlock(codeBlock)
- , m_exceptionCheckCount(0)
{
}
@@ -209,39 +205,36 @@
}
// Notify the JIT of a call that does not require linking.
- void notifyCall(Call call, CodeOrigin codeOrigin)
+ void notifyCall(Call functionCall, CodeOrigin codeOrigin)
{
- m_calls.append(CallRecord(call, FunctionPtr(), codeOrigin));
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin));
}
// Add a call out from JIT code, without an exception check.
Call appendCall(const FunctionPtr& function)
{
Call functionCall = call();
- m_calls.append(CallRecord(functionCall, function));
- // FIXME: should be able to JIT_ASSERT here that globalData->exception is null on return back to JIT code.
+ m_calls.append(CallLinkRecord(functionCall, function));
return functionCall;
}
// Add a call out from JIT code, with an exception check.
- Call appendCallWithExceptionCheck(const FunctionPtr& function, CodeOrigin codeOrigin)
+ Call addExceptionCheck(Call functionCall, CodeOrigin codeOrigin)
{
- Call functionCall = call();
#if USE(JSVALUE64)
Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
#elif USE(JSVALUE32_64)
Jump exceptionCheck = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
#endif
- m_calls.append(CallRecord(functionCall, function, exceptionCheck, codeOrigin));
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
return functionCall;
}
// Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
- Call appendCallWithFastExceptionCheck(const FunctionPtr& function, CodeOrigin codeOrigin)
+ Call addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin)
{
- Call functionCall = call();
Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
- m_calls.append(CallRecord(functionCall, function, exceptionCheck, codeOrigin));
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
return functionCall;
}
@@ -466,8 +459,8 @@
// Vector of calls out from JIT code, including exception handler information.
// Count of the number of CallRecords with exception handlers.
- Vector<CallRecord> m_calls;
- unsigned m_exceptionCheckCount;
+ Vector<CallLinkRecord> m_calls;
+ Vector<CallExceptionRecord> m_exceptionChecks;
// JIT code map for OSR entrypoints.
Label m_startOfCode;
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler32_64.cpp (98404 => 98405)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler32_64.cpp 2011-10-25 23:02:53 UTC (rev 98404)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler32_64.cpp 2011-10-25 23:06:13 UTC (rev 98405)
@@ -568,26 +568,26 @@
linkOSRExits(speculative);
- // Iterate over the m_calls vector, checking for exception checks,
- // and linking them to here.
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- Jump& exceptionCheck = m_calls[i].m_exceptionCheck;
+ // Iterate over the m_calls vector, checking for jumps to link.
+ bool didLinkExceptionCheck = false;
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ Jump& exceptionCheck = m_exceptionChecks[i].m_exceptionCheck;
if (exceptionCheck.isSet()) {
exceptionCheck.link(this);
- ++m_exceptionCheckCount;
+ didLinkExceptionCheck = true;
}
}
+
// If any exception checks were linked, generate code to lookup a handler.
- if (m_exceptionCheckCount) {
+ if (didLinkExceptionCheck) {
// lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
// an identifier for the operation that threw the exception, which we can use
// to look up handler information. The identifier we use is the return address
// of the call out from JIT code that threw the exception; this is still
// available on the stack, just below the stack pointer!
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
peek(GPRInfo::argumentGPR1, -1);
- poke(GPRInfo::callFrameRegister);
- poke(GPRInfo::argumentGPR1, 1);
- m_calls.append(CallRecord(call(), lookupExceptionHandler));
+ m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
// lookupExceptionHandler leaves the handler CallFrame* in the returnValueGPR,
// and the address of the handler in returnValueGPR2.
jump(GPRInfo::returnValueGPR2);
@@ -602,19 +602,15 @@
#endif
// Link all calls out from the JIT code to their respective functions.
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- if (m_calls[i].m_function.value())
- linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
- }
+ for (unsigned i = 0; i < m_calls.size(); ++i)
+ linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
if (m_codeBlock->needsCallReturnIndices()) {
- m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionCheckCount);
- for (unsigned i = 0; i < m_calls.size(); ++i) {
- if (m_calls[i].m_handlesExceptions) {
- unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call);
- unsigned exceptionInfo = m_calls[i].m_codeOrigin.bytecodeIndex;
- m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
- }
+ m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
+ for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+ unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+ unsigned exceptionInfo = m_exceptionChecks[i].m_codeOrigin.bytecodeIndex;
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
}
}