Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (191393 => 191394)
--- trunk/Source/_javascript_Core/ChangeLog 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-10-21 18:44:44 UTC (rev 191394)
@@ -1,3 +1,48 @@
+2015-10-21 Saam barati <[email protected]>
+
+ The FTL should place the CallSiteIndex on the call frame for JS calls when it fills in the patchpoint
+ https://bugs.webkit.org/show_bug.cgi?id=150104
+
+ Reviewed by Filip Pizlo.
+
+ We lower JS Calls to patchpoints in LLVM. LLVM may decide to duplicate
+ these patchpoints (or remove them). We eagerly store the CallSiteIndex on the
+ call frame when lowering DFG to LLVM. But, because the patchpoint we lower to may
+ be duplicated, we really don't know the unique CallSiteIndex until we've
+ actually seen the resulting patchpoints after LLVM has completed its transformations.
+ To solve this, we now store the unique CallSiteIndex on the call frame header
+ when generating code to fill into the patchpoint.
+
+ * ftl/FTLCompile.cpp:
+ (JSC::FTL::mmAllocateDataSection):
+ * ftl/FTLJSCall.cpp:
+ (JSC::FTL::JSCall::JSCall):
+ (JSC::FTL::JSCall::emit):
+ * ftl/FTLJSCall.h:
+ (JSC::FTL::JSCall::stackmapID):
+ * ftl/FTLJSCallBase.cpp:
+ (JSC::FTL::JSCallBase::JSCallBase):
+ (JSC::FTL::JSCallBase::emit):
+ (JSC::FTL::JSCallBase::link):
+ * ftl/FTLJSCallBase.h:
+ * ftl/FTLJSCallVarargs.cpp:
+ (JSC::FTL::JSCallVarargs::JSCallVarargs):
+ (JSC::FTL::JSCallVarargs::numSpillSlotsNeeded):
+ (JSC::FTL::JSCallVarargs::emit):
+ * ftl/FTLJSCallVarargs.h:
+ (JSC::FTL::JSCallVarargs::node):
+ (JSC::FTL::JSCallVarargs::stackmapID):
+ * ftl/FTLJSTailCall.cpp:
+ (JSC::FTL::JSTailCall::JSTailCall):
+ (JSC::FTL::m_instructionOffset):
+ (JSC::FTL::JSTailCall::emit):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstructVarargs):
+ (JSC::FTL::DFG::LowerDFGToLLVM::callPreflight):
+ (JSC::FTL::DFG::LowerDFGToLLVM::codeOriginDescriptionOfCallSite):
+ (JSC::FTL::DFG::LowerDFGToLLVM::callCheck):
+
2015-10-21 Geoffrey Garen <[email protected]>
Date creation should share a little code
Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -657,7 +657,7 @@
JSCall& call = state.jsCalls[i];
CCallHelpers fastPathJIT(&vm, codeBlock);
- call.emit(fastPathJIT, state.jitCode->stackmaps.stackSizeForLocals());
+ call.emit(fastPathJIT, state);
char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset;
@@ -672,7 +672,7 @@
JSCallVarargs& call = state.jsCallVarargses[i];
CCallHelpers fastPathJIT(&vm, codeBlock);
- call.emit(fastPathJIT, varargsSpillSlotsOffset);
+ call.emit(fastPathJIT, state, varargsSpillSlotsOffset);
char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset;
size_t sizeOfIC = sizeOfICFor(call.node());
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -29,6 +29,7 @@
#if ENABLE(FTL_JIT)
#include "DFGNode.h"
+#include "FTLState.h"
#include "LinkBuffer.h"
namespace JSC { namespace FTL {
@@ -41,21 +42,19 @@
{
}
-JSCall::JSCall(unsigned stackmapID, Node* node)
- : JSCallBase(
- node->op() == Construct ? CallLinkInfo::Construct : CallLinkInfo::Call,
- node->origin.semantic)
+JSCall::JSCall(unsigned stackmapID, Node* node, CodeOrigin callSiteDescriptionOrigin)
+ : JSCallBase(node->op() == Construct ? CallLinkInfo::Construct : CallLinkInfo::Call, node->origin.semantic, callSiteDescriptionOrigin)
, m_stackmapID(stackmapID)
, m_instructionOffset(0)
{
ASSERT(node->op() == Call || node->op() == Construct || node->op() == TailCallInlinedCaller);
}
-void JSCall::emit(CCallHelpers& jit, unsigned stackSizeForLocals)
+void JSCall::emit(CCallHelpers& jit, State& state)
{
- JSCallBase::emit(jit);
+ JSCallBase::emit(jit, state);
- jit.addPtr(CCallHelpers::TrustedImm32(- static_cast<int64_t>(stackSizeForLocals)), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+ jit.addPtr(CCallHelpers::TrustedImm32(- static_cast<int64_t>(state.jitCode->stackmaps.stackSizeForLocals())), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
}
} } // namespace JSC::FTL
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCall.h (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCall.h 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCall.h 2015-10-21 18:44:44 UTC (rev 191394)
@@ -41,9 +41,9 @@
class JSCall : public JSCallBase {
public:
JSCall();
- JSCall(unsigned stackmapID, DFG::Node*);
+ JSCall(unsigned stackmapID, DFG::Node*, CodeOrigin callSiteDescriptionOrigin);
- void emit(CCallHelpers&, unsigned stackSizeForLocals);
+ void emit(CCallHelpers&, State&);
unsigned stackmapID() const { return m_stackmapID; }
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -29,6 +29,7 @@
#if ENABLE(FTL_JIT)
#include "DFGNode.h"
+#include "FTLState.h"
#include "LinkBuffer.h"
namespace JSC { namespace FTL {
@@ -41,15 +42,19 @@
{
}
-JSCallBase::JSCallBase(CallLinkInfo::CallType type, CodeOrigin origin)
+JSCallBase::JSCallBase(CallLinkInfo::CallType type, CodeOrigin semantic, CodeOrigin callSiteDescription)
: m_type(type)
- , m_origin(origin)
+ , m_semanticeOrigin(semantic)
+ , m_callSiteDescriptionOrigin(callSiteDescription)
, m_callLinkInfo(nullptr)
{
}
-void JSCallBase::emit(CCallHelpers& jit)
+void JSCallBase::emit(CCallHelpers& jit, State& state)
{
+ CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(m_callSiteDescriptionOrigin);
+ jit.store32(CCallHelpers::TrustedImm32(callSiteIndex.bits()), CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
+
m_callLinkInfo = jit.codeBlock()->addCallLinkInfo();
if (CallLinkInfo::callModeFor(m_type) == CallMode::Tail)
@@ -79,7 +84,7 @@
else
done.link(&jit);
- m_callLinkInfo->setUpCall(m_type, m_origin, GPRInfo::regT0);
+ m_callLinkInfo->setUpCall(m_type, m_semanticeOrigin, GPRInfo::regT0);
}
void JSCallBase::link(VM& vm, LinkBuffer& linkBuffer)
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallBase.h (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCallBase.h 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallBase.h 2015-10-21 18:44:44 UTC (rev 191394)
@@ -42,17 +42,20 @@
namespace FTL {
+class State;
+
class JSCallBase {
public:
JSCallBase();
- JSCallBase(CallLinkInfo::CallType, CodeOrigin);
+ JSCallBase(CallLinkInfo::CallType, CodeOrigin semantic, CodeOrigin callSiteDescription);
- void emit(CCallHelpers&);
+ void emit(CCallHelpers&, State&);
void link(VM&, LinkBuffer&);
protected:
CallLinkInfo::CallType m_type;
- CodeOrigin m_origin;
+ CodeOrigin m_semanticeOrigin;
+ CodeOrigin m_callSiteDescriptionOrigin; // These two code origins may be different with tail calls under some circumstances of inlining. See relevant comment in LowerDFGToLLVM.
CCallHelpers::DataLabelPtr m_targetToCheck;
CCallHelpers::Call m_fastCall;
CCallHelpers::Call m_slowCall;
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -30,6 +30,7 @@
#include "DFGNode.h"
#include "DFGOperations.h"
+#include "FTLState.h"
#include "JSCInlines.h"
#include "LinkBuffer.h"
#include "ScratchRegisterAllocator.h"
@@ -46,14 +47,14 @@
{
}
-JSCallVarargs::JSCallVarargs(unsigned stackmapID, Node* node)
+JSCallVarargs::JSCallVarargs(unsigned stackmapID, Node* node, CodeOrigin callSiteDescriptionOrigin)
: m_stackmapID(stackmapID)
, m_node(node)
, m_callBase(
(node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs)
? CallLinkInfo::ConstructVarargs : (node->op() == TailCallVarargs || node->op() == TailCallForwardVarargs)
? CallLinkInfo::TailCallVarargs : CallLinkInfo::CallVarargs,
- node->origin.semantic)
+ node->origin.semantic, callSiteDescriptionOrigin)
, m_instructionOffset(0)
{
ASSERT(
@@ -68,7 +69,7 @@
return 4;
}
-void JSCallVarargs::emit(CCallHelpers& jit, int32_t spillSlotsOffset)
+void JSCallVarargs::emit(CCallHelpers& jit, State& state, int32_t spillSlotsOffset)
{
// We are passed three pieces of information:
// - The callee.
@@ -204,7 +205,7 @@
// stack frame to already be set up, which it is.
jit.store64(GPRInfo::regT0, CCallHelpers::calleeFrameSlot(JSStack::Callee));
- m_callBase.emit(jit);
+ m_callBase.emit(jit, state);
// Undo the damage we've done.
if (isARM64()) {
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.h (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.h 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallVarargs.h 2015-10-21 18:44:44 UTC (rev 191394)
@@ -43,13 +43,13 @@
class JSCallVarargs {
public:
JSCallVarargs();
- JSCallVarargs(unsigned stackmapID, DFG::Node*);
+ JSCallVarargs(unsigned stackmapID, DFG::Node*, CodeOrigin callSiteDescriptionOrigin);
DFG::Node* node() const { return m_node; }
static unsigned numSpillSlotsNeeded();
- void emit(CCallHelpers&, int32_t spillSlotsOffset);
+ void emit(CCallHelpers&, State&, int32_t spillSlotsOffset);
void link(VM&, LinkBuffer&, CodeLocationLabel exceptionHandler);
unsigned stackmapID() const { return m_stackmapID; }
Modified: trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -179,7 +179,7 @@
} // anonymous namespace
JSTailCall::JSTailCall(unsigned stackmapID, Node* node, Vector<ExitValue> arguments)
- : JSCallBase(CallLinkInfo::TailCall, node->origin.semantic)
+ : JSCallBase(CallLinkInfo::TailCall, node->origin.semantic, node->origin.semantic)
, m_stackmapID(stackmapID)
, m_arguments { WTF::move(arguments) }
, m_instructionOffset(0)
@@ -318,7 +318,7 @@
jit.abortWithReason(JITDidReturnFromTailCall);
- m_callLinkInfo->setUpCall(m_type, m_origin, calleeGPR);
+ m_callLinkInfo->setUpCall(m_type, m_semanticeOrigin, calleeGPR);
}
} } // namespace JSC::FTL
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (191393 => 191394)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-10-21 18:42:06 UTC (rev 191393)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-10-21 18:44:44 UTC (rev 191394)
@@ -4462,12 +4462,10 @@
for (unsigned i = 0; i < padding; ++i)
arguments.append(getUndef(m_out.int64));
- callPreflight();
-
LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments);
setInstructionCallingConvention(call, LLVMWebKitJSCallConv);
- m_ftlState.jsCalls.append(JSCall(stackmapID, m_node));
+ m_ftlState.jsCalls.append(JSCall(stackmapID, m_node, codeOriginDescriptionOfCallSite()));
setJSValue(call);
}
@@ -4544,12 +4542,10 @@
ASSERT(thisArg);
arguments.append(thisArg);
- callPreflight();
-
LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments);
setInstructionCallingConvention(call, LLVMCCallConv);
- m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, m_node));
+ m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, m_node, codeOriginDescriptionOfCallSite()));
switch (m_node->op()) {
case TailCallVarargs:
@@ -8665,16 +8661,27 @@
m_ftlState.jitCode->common.addCodeOrigin(codeOrigin).bits()),
tagFor(JSStack::ArgumentCount));
}
+
void callPreflight()
{
+ callPreflight(codeOriginDescriptionOfCallSite());
+ }
+
+ CodeOrigin codeOriginDescriptionOfCallSite() const
+ {
CodeOrigin codeOrigin = m_node->origin.semantic;
-
if (m_node->op() == TailCallInlinedCaller
|| m_node->op() == TailCallVarargsInlinedCaller
- || m_node->op() == TailCallForwardVarargsInlinedCaller)
+ || m_node->op() == TailCallForwardVarargsInlinedCaller) {
+ // This case arises when you have a situation like this:
+ // foo makes a call to bar, bar is inlined in foo. bar makes a call
+ // to baz and baz is inlined in bar. And then baz makes a tail-call to jaz,
+ // and jaz is inlined in baz. We want the callframe for jaz to appear to
+ // have caller be bar.
codeOrigin = *codeOrigin.inlineCallFrame->getCallerSkippingDeadFrames();
+ }
- callPreflight(codeOrigin);
+ return codeOrigin;
}
void callCheck()