Commit 48a7bc89 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Never use ReturnPC for exception handling and quit using exception check...

Never use ReturnPC for exception handling and quit using exception check indices as a lame replica of the CodeOrigin index
https://bugs.webkit.org/show_bug.cgi?id=121734

Reviewed by Mark Hahnenberg.
        
Exception handling can deduce where the exception was thrown from by looking at the
code origin that was stored into the call frame header. There is no need to pass any
additional meta-data into the exception throwing logic. But the DFG was still doing it
anyway.
        
This removes all of the logic to pass extra meta-data into lookupExceptionHandler()
and friends. It simplifies a lot of code.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::codeOrigins):
(JSC::CodeBlock::hasCodeOrigins):
(JSC::CodeBlock::canGetCodeOrigin):
(JSC::CodeBlock::codeOrigin):
* bytecode/CodeOrigin.h:
(JSC::InlineCallFrame::InlineCallFrame):
* bytecode/InlineCallFrameSet.cpp: Added.
(JSC::InlineCallFrameSet::InlineCallFrameSet):
(JSC::InlineCallFrameSet::~InlineCallFrameSet):
(JSC::InlineCallFrameSet::add):
(JSC::InlineCallFrameSet::shrinkToFit):
* bytecode/InlineCallFrameSet.h: Added.
(JSC::InlineCallFrameSet::isEmpty):
(JSC::InlineCallFrameSet::size):
(JSC::InlineCallFrameSet::at):
* dfg/DFGArgumentsSimplificationPhase.cpp:
(JSC::DFG::ArgumentsSimplificationPhase::run):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::addCodeOrigin):
(JSC::DFG::CommonData::shrinkToFit):
* dfg/DFGCommonData.h:
* dfg/DFGDesiredWriteBarriers.cpp:
(JSC::DFG::DesiredWriteBarrier::DesiredWriteBarrier):
(JSC::DFG::DesiredWriteBarrier::trigger):
* dfg/DFGDesiredWriteBarriers.h:
(JSC::DFG::DesiredWriteBarriers::add):
(JSC::DFG::initializeLazyWriteBarrierForInlineCallFrameExecutable):
(JSC::DFG::initializeLazyWriteBarrierForInlineCallFrameCallee):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(JSC::DFG::JITCompiler::compileExceptionHandlers):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::emitStoreCodeOrigin):
(JSC::DFG::JITCompiler::exceptionCheck):
(JSC::DFG::JITCompiler::fastExceptionCheck):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGRepatch.cpp:
(JSC::DFG::tryBuildGetByIDList):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):
(JSC::DFG::SpeculativeJIT::appendCallSetResult):
(JSC::DFG::SpeculativeJIT::appendCall):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGVirtualRegisterAllocationPhase.cpp:
(JSC::DFG::VirtualRegisterAllocationPhase::run):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::callPreflight):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitExceptionCheck):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156300 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d99af846
......@@ -57,6 +57,7 @@ set(JavaScriptCore_SOURCES
bytecode/ExecutionCounter.cpp
bytecode/ExitKind.cpp
bytecode/GetByIdStatus.cpp
bytecode/InlineCallFrameSet.cpp
bytecode/JumpTable.cpp
bytecode/LazyOperandValueProfile.cpp
bytecode/MethodOfGettingAValueProfile.cpp
......
2013-09-23 Filip Pizlo <fpizlo@apple.com>
Never use ReturnPC for exception handling and quit using exception check indices as a lame replica of the CodeOrigin index
https://bugs.webkit.org/show_bug.cgi?id=121734
Reviewed by Mark Hahnenberg.
Exception handling can deduce where the exception was thrown from by looking at the
code origin that was stored into the call frame header. There is no need to pass any
additional meta-data into the exception throwing logic. But the DFG was still doing it
anyway.
This removes all of the logic to pass extra meta-data into lookupExceptionHandler()
and friends. It simplifies a lot of code.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::codeOrigins):
(JSC::CodeBlock::hasCodeOrigins):
(JSC::CodeBlock::canGetCodeOrigin):
(JSC::CodeBlock::codeOrigin):
* bytecode/CodeOrigin.h:
(JSC::InlineCallFrame::InlineCallFrame):
* bytecode/InlineCallFrameSet.cpp: Added.
(JSC::InlineCallFrameSet::InlineCallFrameSet):
(JSC::InlineCallFrameSet::~InlineCallFrameSet):
(JSC::InlineCallFrameSet::add):
(JSC::InlineCallFrameSet::shrinkToFit):
* bytecode/InlineCallFrameSet.h: Added.
(JSC::InlineCallFrameSet::isEmpty):
(JSC::InlineCallFrameSet::size):
(JSC::InlineCallFrameSet::at):
* dfg/DFGArgumentsSimplificationPhase.cpp:
(JSC::DFG::ArgumentsSimplificationPhase::run):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::addCodeOrigin):
(JSC::DFG::CommonData::shrinkToFit):
* dfg/DFGCommonData.h:
* dfg/DFGDesiredWriteBarriers.cpp:
(JSC::DFG::DesiredWriteBarrier::DesiredWriteBarrier):
(JSC::DFG::DesiredWriteBarrier::trigger):
* dfg/DFGDesiredWriteBarriers.h:
(JSC::DFG::DesiredWriteBarriers::add):
(JSC::DFG::initializeLazyWriteBarrierForInlineCallFrameExecutable):
(JSC::DFG::initializeLazyWriteBarrierForInlineCallFrameCallee):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(JSC::DFG::JITCompiler::compileExceptionHandlers):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::emitStoreCodeOrigin):
(JSC::DFG::JITCompiler::exceptionCheck):
(JSC::DFG::JITCompiler::fastExceptionCheck):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGRepatch.cpp:
(JSC::DFG::tryBuildGetByIDList):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):
(JSC::DFG::SpeculativeJIT::appendCallSetResult):
(JSC::DFG::SpeculativeJIT::appendCall):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGVirtualRegisterAllocationPhase.cpp:
(JSC::DFG::VirtualRegisterAllocationPhase::run):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::callPreflight):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitExceptionCheck):
2013-09-23 Oliver Hunt <oliver@apple.com>
CodeLoad performance regression
......@@ -127,6 +127,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
Source/JavaScriptCore/bytecode/GetByIdStatus.h \
Source/JavaScriptCore/bytecode/HandlerInfo.h \
Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp \
Source/JavaScriptCore/bytecode/InlineCallFrameSet.h \
Source/JavaScriptCore/bytecode/Instruction.h \
Source/JavaScriptCore/bytecode/JumpTable.cpp \
Source/JavaScriptCore/bytecode/JumpTable.h \
......
......@@ -306,6 +306,7 @@
<ClCompile Include="..\bytecode\ExecutionCounter.cpp" />
<ClCompile Include="..\bytecode\ExitKind.cpp" />
<ClCompile Include="..\bytecode\GetByIdStatus.cpp" />
<ClCompile Include="..\bytecode\InlineCallFrameSet.cpp" />
<ClCompile Include="..\bytecode\JumpTable.cpp" />
<ClCompile Include="..\bytecode\LazyOperandValueProfile.cpp" />
<ClCompile Include="..\bytecode\MethodOfGettingAValueProfile.cpp" />
......@@ -648,6 +649,7 @@
<ClInclude Include="..\bytecode\ExpressionRangeInfo.h" />
<ClInclude Include="..\bytecode\GetByIdStatus.h" />
<ClInclude Include="..\bytecode\HandlerInfo.h" />
<ClInclude Include="..\bytecode\InlineCallFrameSet.h" />
<ClInclude Include="..\bytecode\Instruction.h" />
<ClInclude Include="..\bytecode\JumpTable.h" />
<ClInclude Include="..\bytecode\LazyOperandValueProfile.h" />
......
......@@ -118,6 +118,8 @@
0F24E54217EA9F5900ABB217 /* CCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53E17EA9F5900ABB217 /* FPRInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E54417EA9F5900ABB217 /* GPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E53F17EA9F5900ABB217 /* GPRInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */; };
0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F256C361627B0AD007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2B66AC17B6B53F00A7AE3F /* GCIncomingRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2B66AD17B6B54500A7AE3F /* GCIncomingRefCountedInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1318,6 +1320,8 @@
0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCallHelpers.h; sourceTree = "<group>"; };
0F24E53E17EA9F5900ABB217 /* FPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FPRInfo.h; sourceTree = "<group>"; };
0F24E53F17EA9F5900ABB217 /* GPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPRInfo.h; sourceTree = "<group>"; };
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineCallFrameSet.cpp; sourceTree = "<group>"; };
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineCallFrameSet.h; sourceTree = "<group>"; };
0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCallArrayAllocatorSlowPathGenerator.h; path = dfg/DFGCallArrayAllocatorSlowPathGenerator.h; sourceTree = "<group>"; };
0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCounted.h; sourceTree = "<group>"; };
0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCIncomingRefCountedInlines.h; sourceTree = "<group>"; };
......@@ -3754,6 +3758,8 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */,
0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */,
0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */,
0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */,
0F63945115D07051006A597C /* ArrayProfile.cpp */,
......@@ -4240,6 +4246,7 @@
7C3BA29717C039560072DDC9 /* JSPromiseResolverConstructor.h in Headers */,
7C3BA29917C039560072DDC9 /* JSPromiseResolverPrototype.h in Headers */,
862553D216136E1A009F17D0 /* JSProxy.h in Headers */,
0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */,
BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */,
14874AE615EBDE4A002E3587 /* JSScope.h in Headers */,
A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
......@@ -4984,6 +4991,7 @@
0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */,
0F9D3370165DBB90005AD387 /* Disassembler.cpp in Sources */,
A70447ED17A0BD7000F5898E /* DumpContext.cpp in Sources */,
0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */,
147F39C7107EC37600427A48 /* Error.cpp in Sources */,
147F39C8107EC37600427A48 /* ErrorConstructor.cpp in Sources */,
147F39C9107EC37600427A48 /* ErrorInstance.cpp in Sources */,
......
......@@ -65,6 +65,7 @@ SOURCES += \
bytecode/ExecutionCounter.cpp \
bytecode/ExitKind.cpp \
bytecode/GetByIdStatus.cpp \
bytecode/InlineCallFrameSet.cpp \
bytecode/JumpTable.cpp \
bytecode/LazyOperandValueProfile.cpp \
bytecode/MethodOfGettingAValueProfile.cpp \
......
......@@ -2545,13 +2545,8 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
}
} // else don't shrink these, because we would have already pointed pointers into these tables.
if (m_rareData) {
if (m_rareData)
m_rareData->m_exceptionHandlers.shrinkToFit();
#if ENABLE(DFG_JIT)
m_rareData->m_inlineCallFrames.shrinkToFit();
m_rareData->m_codeOrigins.shrinkToFit();
#endif
}
}
void CodeBlock::createActivation(CallFrame* callFrame)
......
......@@ -566,43 +566,27 @@ public:
bool hasExpressionInfo() { return m_unlinkedCode->hasExpressionInfo(); }
#if ENABLE(DFG_JIT)
SegmentedVector<InlineCallFrame, 4>& inlineCallFrames()
{
createRareDataIfNecessary();
return m_rareData->m_inlineCallFrames;
}
Vector<CodeOrigin, 0, UnsafeVectorOverflow>& codeOrigins()
{
createRareDataIfNecessary();
return m_rareData->m_codeOrigins;
return m_jitCode->dfgCommon()->codeOrigins;
}
unsigned addCodeOrigin(CodeOrigin codeOrigin)
{
createRareDataIfNecessary();
unsigned result = m_rareData->m_codeOrigins.size();
m_rareData->m_codeOrigins.append(codeOrigin);
return result;
}
// Having code origins implies that there has been some inlining.
bool hasCodeOrigins()
{
return m_rareData && !!m_rareData->m_codeOrigins.size();
return JITCode::isOptimizingJIT(jitType());
}
bool canGetCodeOrigin(unsigned index)
{
if (!m_rareData)
if (!hasCodeOrigins())
return false;
return m_rareData->m_codeOrigins.size() > index;
return index < codeOrigins().size();
}
CodeOrigin codeOrigin(unsigned index)
{
RELEASE_ASSERT(m_rareData);
return m_rareData->m_codeOrigins[index];
return codeOrigins()[index];
}
bool addFrequentExitSite(const DFG::FrequentExitSite& site)
......@@ -1120,11 +1104,6 @@ private:
Vector<StringJumpTable> m_stringSwitchJumpTables;
EvalCodeCache m_evalCodeCache;
#if ENABLE(DFG_JIT)
SegmentedVector<InlineCallFrame, 4> m_inlineCallFrames;
Vector<CodeOrigin, 0, UnsafeVectorOverflow> m_codeOrigins;
#endif
};
#if COMPILER(MSVC)
friend void WTF::deleteOwnedPtr<RareData>(RareData*);
......
......@@ -100,6 +100,15 @@ struct InlineCallFrame {
signed stackOffset : 31;
bool isCall : 1;
// There is really no good notion of a "default" set of values for
// InlineCallFrame's fields. This constructor is here just to reduce confusion if
// we forgot to initialize explicitly.
InlineCallFrame()
: stackOffset(0)
, isCall(false)
{
}
CodeSpecializationKind specializationKind() const { return specializationFromIsCall(isCall); }
bool isClosureCall() const { return !callee; }
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "InlineCallFrameSet.h"
namespace JSC {
InlineCallFrameSet::InlineCallFrameSet() { }
InlineCallFrameSet::~InlineCallFrameSet() { }
InlineCallFrame* InlineCallFrameSet::add()
{
m_frames.append(InlineCallFrame());
return &m_frames.last();
}
void InlineCallFrameSet::shrinkToFit()
{
m_frames.shrinkToFit();
}
} // namespace JSC
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef InlineCallFrameSet_h
#define InlineCallFrameSet_h
#include "CodeOrigin.h"
#include <wtf/Noncopyable.h>
#include <wtf/SegmentedVector.h>
namespace JSC {
class InlineCallFrameSet {
WTF_MAKE_NONCOPYABLE(InlineCallFrameSet);
public:
InlineCallFrameSet();
~InlineCallFrameSet();
bool isEmpty() const { return m_frames.isEmpty(); }
InlineCallFrame* add();
// The only users of these methods just want to iterate all inline call frames.
// There is no requirement for random access.
unsigned size() const { return m_frames.size(); }
InlineCallFrame* at(unsigned i) { return &m_frames[i]; }
void shrinkToFit();
private:
SegmentedVector<InlineCallFrame, 4> m_frames;
};
} // namespace JSC
#endif // InlineCallFrameSet_h
......@@ -122,8 +122,8 @@ public:
bool changed = false;
// Record which arguments are known to escape no matter what.
for (unsigned i = codeBlock()->inlineCallFrames().size(); i--;)
pruneObviousArgumentCreations(&codeBlock()->inlineCallFrames()[i]);
for (unsigned i = m_graph.m_inlineCallFrames->size(); i--;)
pruneObviousArgumentCreations(m_graph.m_inlineCallFrames->at(i));
pruneObviousArgumentCreations(0); // the machine call frame.
// Create data for variable access datas that we will want to analyze.
......
......@@ -3374,56 +3374,53 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
ASSERT(inlineCallFrameStart != InvalidVirtualRegister);
ASSERT(callsiteBlockHead);
InlineCallFrame inlineCallFrame;
m_inlineCallFrame = byteCodeParser->m_graph.m_inlineCallFrames->add();
initializeLazyWriteBarrierForInlineCallFrameExecutable(
byteCodeParser->m_graph.m_plan.writeBarriers,
inlineCallFrame.executable,
m_inlineCallFrame->executable,
byteCodeParser->m_codeBlock,
byteCodeParser->m_codeBlock->inlineCallFrames().size(),
m_inlineCallFrame,
byteCodeParser->m_codeBlock->ownerExecutable(),
codeBlock->ownerExecutable());
inlineCallFrame.stackOffset = inlineCallFrameStart - JSStack::CallFrameHeaderSize;
m_inlineCallFrame->stackOffset = inlineCallFrameStart - JSStack::CallFrameHeaderSize;
if (callee) {
initializeLazyWriteBarrierForInlineCallFrameCallee(
byteCodeParser->m_graph.m_plan.writeBarriers,
inlineCallFrame.callee,
m_inlineCallFrame->callee,
byteCodeParser->m_codeBlock,
byteCodeParser->m_codeBlock->inlineCallFrames().size(),
m_inlineCallFrame,
byteCodeParser->m_codeBlock->ownerExecutable(),
callee);
}
inlineCallFrame.caller = byteCodeParser->currentCodeOrigin();
inlineCallFrame.arguments.resize(argumentCountIncludingThis); // Set the number of arguments including this, but don't configure the value recoveries, yet.
inlineCallFrame.isCall = isCall(kind);
m_inlineCallFrame->caller = byteCodeParser->currentCodeOrigin();
m_inlineCallFrame->arguments.resize(argumentCountIncludingThis); // Set the number of arguments including this, but don't configure the value recoveries, yet.
m_inlineCallFrame->isCall = isCall(kind);
if (inlineCallFrame.caller.inlineCallFrame)
inlineCallFrame.capturedVars = inlineCallFrame.caller.inlineCallFrame->capturedVars;
if (m_inlineCallFrame->caller.inlineCallFrame)
m_inlineCallFrame->capturedVars = m_inlineCallFrame->caller.inlineCallFrame->capturedVars;
else {
for (int i = byteCodeParser->m_codeBlock->m_numVars; i--;) {
if (byteCodeParser->m_codeBlock->isCaptured(localToOperand(i)))
inlineCallFrame.capturedVars.set(i);
m_inlineCallFrame->capturedVars.set(i);
}
}
for (int i = argumentCountIncludingThis; i--;) {
if (codeBlock->isCaptured(argumentToOperand(i)))
inlineCallFrame.capturedVars.set(operandToLocal(argumentToOperand(i) + inlineCallFrame.stackOffset));
m_inlineCallFrame->capturedVars.set(operandToLocal(argumentToOperand(i) + m_inlineCallFrame->stackOffset));
}
for (size_t i = codeBlock->m_numVars; i--;) {
int localOperand = localToOperand(i);
if (codeBlock->isCaptured(localOperand))
inlineCallFrame.capturedVars.set(operandToLocal(localOperand + inlineCallFrame.stackOffset));
m_inlineCallFrame->capturedVars.set(operandToLocal(localOperand + m_inlineCallFrame->stackOffset));
}
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLogF("Current captured variables: ");
inlineCallFrame.capturedVars.dump(WTF::dataFile());
m_inlineCallFrame->capturedVars.dump(WTF::dataFile());
dataLogF("\n");
#endif
byteCodeParser->m_codeBlock->inlineCallFrames().append(inlineCallFrame);
m_inlineCallFrame = &byteCodeParser->m_codeBlock->inlineCallFrames().last();
byteCodeParser->buildOperandMapsIfNecessary();
m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
......
......@@ -45,8 +45,19 @@ void CommonData::notifyCompilingStructureTransition(Plan& plan, CodeBlock* codeB
node->structureTransitionData().newStructure);
}
unsigned CommonData::addCodeOrigin(CodeOrigin codeOrigin)
{
if (codeOrigins.isEmpty()
|| codeOrigins.last() != codeOrigin)
codeOrigins.append(codeOrigin);
unsigned index = codeOrigins.size() - 1;
ASSERT(codeOrigins[index] == codeOrigin);
return index;
}
void CommonData::shrinkToFit()
{
codeOrigins.shrinkToFit();
weakReferences.shrinkToFit();
transitions.shrinkToFit();
}
......
......@@ -30,6 +30,7 @@
#if ENABLE(DFG_JIT)
#include "InlineCallFrameSet.h"
#include "JSCell.h"
#include "ProfilerCompilation.h"
#include <wtf/Noncopyable.h>
......@@ -69,9 +70,13 @@ public:
CommonData() { }
void notifyCompilingStructureTransition(Plan&, CodeBlock*, Node*);
unsigned addCodeOrigin(CodeOrigin codeOrigin);
void shrinkToFit();
OwnPtr<InlineCallFrameSet> inlineCallFrames;
Vector<CodeOrigin, 0, UnsafeVectorOverflow> codeOrigins;
Vector<Identifier> dfgIdentifiers;
Vector<WeakReferenceTransition> transitions;
Vector<WriteBarrier<JSCell> > weakReferences;
......
......@@ -38,35 +38,42 @@ DesiredWriteBarrier::DesiredWriteBarrier(Type type, CodeBlock* codeBlock, unsign
: m_owner(owner)
, m_type(type)
, m_codeBlock(codeBlock)
, m_index(index)
{
m_which.index = index;
}
DesiredWriteBarrier::DesiredWriteBarrier(Type type, CodeBlock* codeBlock, InlineCallFrame* inlineCallFrame, JSCell* owner)
: m_owner(owner)
, m_type(type)
, m_codeBlock(codeBlock)
{
m_which.inlineCallFrame = inlineCallFrame;
}
void DesiredWriteBarrier::trigger(VM& vm)
{
switch (m_type) {
case ConstantType: {
WriteBarrier<Unknown>& barrier = m_codeBlock->constants()[m_index];
WriteBarrier<Unknown>& barrier = m_codeBlock->constants()[m_which.index];
barrier.set(vm, m_owner, barrier.get());
break;
return;
}
case InlineCallFrameExecutableType: {
InlineCallFrame& inlineCallFrame = m_codeBlock->inlineCallFrames()[m_index];
WriteBarrier<ScriptExecutable>& executable = inlineCallFrame.executable;
InlineCallFrame* inlineCallFrame = m_which.inlineCallFrame;
WriteBarrier<ScriptExecutable>& executable = inlineCallFrame->executable;
executable.set(vm, m_owner, executable.get());
break;
return;
}
case InlineCallFrameCalleeType: {
InlineCallFrame& inlineCallFrame = m_codeBlock->inlineCallFrames()[m_index];
ASSERT(!!inlineCallFrame.callee);
WriteBarrier<JSFunction>& callee = inlineCallFrame.callee;
InlineCallFrame* inlineCallFrame = m_which.inlineCallFrame;
ASSERT(!!inlineCallFrame->callee);
WriteBarrier<JSFunction>& callee = inlineCallFrame->callee;
callee.set(vm, m_owner, callee.get());
break;
}
}
return;
} }
RELEASE_ASSERT_NOT_REACHED();
}
DesiredWriteBarriers::DesiredWriteBarriers()
......
......@@ -36,6 +36,7 @@ namespace JSC {
class JSFunction;
class ScriptExecutable;
class VM;
struct InlineCallFrame;
namespace DFG {
......@@ -43,6 +44,7 @@ class DesiredWriteBarrier {
public:
enum Type { ConstantType, InlineCallFrameExecutableType, InlineCallFrameCalleeType };
DesiredWriteBarrier(Type, CodeBlock*, unsigned index, JSCell* owner);
DesiredWriteBarrier(Type, CodeBlock*, InlineCallFrame*, JSCell* owner);
void trigger(VM&);
......@@ -50,7 +52,10 @@ private:
JSCell* m_owner;
Type m_type;
CodeBlock* m_codeBlock;
unsigned m_index;
union {
unsigned index;
InlineCallFrame* inlineCallFrame;
} m_which;
};
class DesiredWriteBarriers {
......@@ -63,6 +68,11 @@ public:
m_barriers.append(DesiredWriteBarrier(type, codeBlock, index, owner));
return m_barriers.last();
}
DesiredWriteBarrier& add(DesiredWriteBarrier::Type type, CodeBlock* codeBlock, InlineCallFrame* inlineCallFrame, JSCell* owner)
{
m_barriers.append(DesiredWriteBarrier(type, codeBlock, inlineCallFrame, owner));
return m_barriers.last();
}
void trigger(VM&);
......@@ -70,15 +80,15 @@ private:
Vector<DesiredWriteBarrier> m_barriers;
};
inline void initializeLazyWriteBarrierForInlineCallFrameExecutable(DesiredWriteBarriers& barriers, WriteBarrier<ScriptExecutable>& barrier, CodeBlock* codeBlock, unsigned index, JSCell* owner, ScriptExecutable* value)
inline void initializeLazyWriteBarrierForInlineCallFrameExecutable(DesiredWriteBarriers& barriers, WriteBarrier<ScriptExecutable>& barrier, CodeBlock* codeBlock, InlineCallFrame* inlineCallFrame, JSCell* owner, ScriptExecutable* value)
{
DesiredWriteBarrier& desiredBarrier = barriers.add(DesiredWriteBarrier::InlineCallFrameExecutableType, codeBlock, index, owner);
DesiredWriteBarrier& desiredBarrier = barriers.add(DesiredWriteBarrier::InlineCallFrameExecutableType, codeBlock, inlineCallFrame, owner);
barrier = WriteBarrier<ScriptExecutable>(desiredBarrier, value);
}
inline void initializeLazyWriteBarrierForInlineCallFrameCallee(DesiredWriteBarriers& barriers, WriteBarrier<JSFunction>& barrier, CodeBlock* codeBlock, unsigned index, JSCell* owner, JSFunction* value)
inline void initializeLazyWriteBarrierForInlineCallFrameCallee(DesiredWriteBarriers& barriers, WriteBarrier<JSFunction>& barrier, CodeBlock* codeBlock, InlineCallFrame* inlineCallFrame, JSCell* owner, JSFunction* value)
{
DesiredWriteBarrier& desiredBarrier = barriers.add(DesiredWriteBarrier::InlineCallFrameCalleeType, codeBlock, index, owner);
DesiredWriteBarrier& desiredBarrier = barriers.add(DesiredWriteBarrier::InlineCallFrameCalleeType, codeBlock, inlineCallFrame, owner);
barrier = WriteBarrier<JSFunction>(desiredBarrier, value);
}
......
......@@ -54,6 +54,7 @@ Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
, m_codeBlock(m_plan.codeBlock.get())
, m_profiledBlock(m_codeBlock->alternative())
, m_allocator(longLivedState.m_allocator)
, m_inlineCallFrames(adoptPtr(new InlineCallFrameSet()))
, m_hasArguments(false)
, m_fixpointState(BeforeFixpoint)
, m_form(LoadStore)
......
......@@ -41,6 +41,7 @@
#include "DFGNodeAllocator.h"
#include "DFGPlan.h"
#include "DFGVariadicFunction.h"
#include "InlineCallFrameSet.h"
#include "JSStack.h"
#include "MethodOfGettingAValueProfile.h"
#include <wtf/BitVector.h>
......@@ -747,6 +748,7 @@ public:
SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
SegmentedVector<SwitchData, 4> m_switchData;
OwnPtr<InlineCallFrameSet> m_inlineCallFrames;
bool m_hasArguments;
HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped;
BitVector m_preservedVars;
......