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
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 3236470..e83f0cb 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -57,6 +57,7 @@
bytecode/ExecutionCounter.cpp
bytecode/ExitKind.cpp
bytecode/GetByIdStatus.cpp
+ bytecode/InlineCallFrameSet.cpp
bytecode/JumpTable.cpp
bytecode/LazyOperandValueProfile.cpp
bytecode/MethodOfGettingAValueProfile.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 3c7c6f6..fbd7c29 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,87 @@
+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
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index d1422f4..25b99b3 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -127,6 +127,8 @@
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 \
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
index 5daf481..7683e1d 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
@@ -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" />
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index dff658d..97d4504 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -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 */,
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index a458732..23002e0 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -65,6 +65,7 @@
bytecode/ExecutionCounter.cpp \
bytecode/ExitKind.cpp \
bytecode/GetByIdStatus.cpp \
+ bytecode/InlineCallFrameSet.cpp \
bytecode/JumpTable.cpp \
bytecode/LazyOperandValueProfile.cpp \
bytecode/MethodOfGettingAValueProfile.cpp \
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 572eb6c..8d6705f 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -2545,13 +2545,8 @@
}
} // 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)
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index d5d3891..dc91e94 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -566,43 +566,27 @@
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 @@
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*);
diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h
index 9aab786..3db6a81 100644
--- a/Source/JavaScriptCore/bytecode/CodeOrigin.h
+++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h
@@ -100,6 +100,15 @@
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; }
diff --git a/Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp b/Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp
new file mode 100644
index 0000000..8e43724
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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
+
diff --git a/Source/JavaScriptCore/bytecode/InlineCallFrameSet.h b/Source/JavaScriptCore/bytecode/InlineCallFrameSet.h
new file mode 100644
index 0000000..222df65
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/InlineCallFrameSet.h
@@ -0,0 +1,59 @@
+/*
+ * 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
+
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index 8022b52..66544e7 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -122,8 +122,8 @@
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.
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index cc9179c9..28b2e45 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -3374,56 +3374,53 @@
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());
diff --git a/Source/JavaScriptCore/dfg/DFGCommonData.cpp b/Source/JavaScriptCore/dfg/DFGCommonData.cpp
index dc8b2e4..513085e 100644
--- a/Source/JavaScriptCore/dfg/DFGCommonData.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCommonData.cpp
@@ -45,8 +45,19 @@
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();
}
diff --git a/Source/JavaScriptCore/dfg/DFGCommonData.h b/Source/JavaScriptCore/dfg/DFGCommonData.h
index 16d34c2..95cad5e 100644
--- a/Source/JavaScriptCore/dfg/DFGCommonData.h
+++ b/Source/JavaScriptCore/dfg/DFGCommonData.h
@@ -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 @@
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;
diff --git a/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.cpp b/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.cpp
index 03afa9e..672a032 100644
--- a/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.cpp
@@ -38,35 +38,42 @@
: 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()
diff --git a/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.h b/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.h
index bfc933c..b4fd754 100644
--- a/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.h
+++ b/Source/JavaScriptCore/dfg/DFGDesiredWriteBarriers.h
@@ -36,6 +36,7 @@
class JSFunction;
class ScriptExecutable;
class VM;
+struct InlineCallFrame;
namespace DFG {
@@ -43,6 +44,7 @@
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 @@
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 @@
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 @@
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);
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index 6f0df2c..796634a 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -54,6 +54,7 @@
, 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)
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index f516cf2..191bc77 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -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 @@
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;
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index ae881cd..79274fc 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -49,7 +49,6 @@
, m_graph(dfg)
, m_jitCode(adoptRef(new JITCode()))
, m_blockHeads(dfg.numBlocks())
- , m_currentCodeOriginIndex(0)
{
if (shouldShowDisassembly() || m_graph.m_vm.m_perBytecodeProfiler)
m_disassembler = adoptPtr(new Disassembler(dfg));
@@ -120,33 +119,21 @@
void JITCompiler::compileExceptionHandlers()
{
- // 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);
- didLinkExceptionCheck = true;
- }
- }
+ if (m_exceptionChecks.empty())
+ return;
+
+ m_exceptionChecks.link(this);
- // If any exception checks were linked, generate code to lookup a handler.
- if (didLinkExceptionCheck) {
- // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
- // the index of the CodeOrigin. The latter is unused, see
- // https://bugs.webkit.org/show_bug.cgi?id=121734.
- move(GPRInfo::nonPreservedNonReturnGPR, GPRInfo::argumentGPR1);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ // lookupExceptionHandler is passed one argument, the exec (the CallFrame*).
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
#if CPU(X86)
- // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
- poke(GPRInfo::argumentGPR0);
- poke(GPRInfo::argumentGPR1, 1);
+ // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+ poke(GPRInfo::argumentGPR0);
#endif
- 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);
- }
+ 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);
}
void JITCompiler::link(LinkBuffer& linkBuffer)
@@ -155,6 +142,11 @@
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLogF("JIT code for %p start at [%p, %p). Size = %zu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
#endif
+
+ if (!m_graph.m_inlineCallFrames->isEmpty()) {
+ m_graph.m_inlineCallFrames->shrinkToFit();
+ m_jitCode->common.inlineCallFrames = m_graph.m_inlineCallFrames.release();
+ }
BitVector usedJumpTables;
for (unsigned i = m_graph.m_switchData.size(); i--;) {
@@ -216,14 +208,6 @@
for (unsigned i = 0; i < m_calls.size(); ++i)
linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
- Vector<CodeOrigin, 0, UnsafeVectorOverflow>& codeOrigins = m_codeBlock->codeOrigins();
- codeOrigins.resize(m_exceptionChecks.size());
-
- for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
- CallExceptionRecord& record = m_exceptionChecks[i];
- codeOrigins[i] = record.m_codeOrigin;
- }
-
m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size() + m_ins.size());
for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) {
StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
@@ -383,10 +367,8 @@
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- CallBeginToken token;
- beginCall(CodeOrigin(0), token);
+ emitStoreCodeOrigin(CodeOrigin(0));
m_callStackCheck = call();
- notifyCall(m_callStackCheck, CodeOrigin(0), token);
jump(fromStackCheck);
// The fast entry point into a function does not check the correct number of arguments
@@ -401,13 +383,11 @@
branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this);
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
- beginCall(CodeOrigin(0), token);
+ emitStoreCodeOrigin(CodeOrigin(0));
m_callArityCheck = call();
- notifyCall(m_callArityCheck, CodeOrigin(0), token);
branchTest32(Zero, GPRInfo::regT0).linkTo(fromArityCheck, this);
- beginCall(CodeOrigin(0), token);
+ emitStoreCodeOrigin(CodeOrigin(0));
m_callArityFixup = call();
- notifyCall(m_callArityFixup, CodeOrigin(0), token);
jump(fromArityCheck);
// Generate slow path code.
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index 0c95133..7b9588f 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -77,89 +77,6 @@
FunctionPtr m_function;
};
-class CallBeginToken {
-public:
- CallBeginToken()
-#if !ASSERT_DISABLED
- : m_registered(false)
- , m_exceptionCheckIndex(std::numeric_limits<unsigned>::max())
-#endif
- {
- }
-
- ~CallBeginToken()
- {
- ASSERT(m_registered || !m_codeOrigin.isSet());
- ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
- }
-
- void set(CodeOrigin codeOrigin, unsigned index)
- {
-#if !ASSERT_DISABLED
- ASSERT(m_registered || !m_codeOrigin.isSet());
- ASSERT(m_codeOrigin.isSet() == (m_exceptionCheckIndex != std::numeric_limits<unsigned>::max()));
- m_codeOrigin = codeOrigin;
- m_registered = false;
- m_exceptionCheckIndex = index;
-#else
- UNUSED_PARAM(codeOrigin);
- UNUSED_PARAM(index);
-#endif
- }
-
- void registerWithExceptionCheck(CodeOrigin codeOrigin, unsigned index)
- {
-#if !ASSERT_DISABLED
- ASSERT(m_codeOrigin == codeOrigin);
- if (m_registered)
- return;
- ASSERT(m_exceptionCheckIndex == index);
- m_registered = true;
-#else
- UNUSED_PARAM(codeOrigin);
- UNUSED_PARAM(index);
-#endif
- }
-
-#if !ASSERT_DISABLED
- const CodeOrigin& codeOrigin() const
- {
- return m_codeOrigin;
- }
-#endif
-
-private:
-#if !ASSERT_DISABLED
- CodeOrigin m_codeOrigin;
- bool m_registered;
- unsigned m_exceptionCheckIndex;
-#endif
-};
-
-// === 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_codeOrigin(codeOrigin)
- {
- }
-
- CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
- : m_call(call)
- , m_exceptionCheck(exceptionCheck)
- , m_codeOrigin(codeOrigin)
- {
- }
-
- MacroAssembler::Call m_call;
- MacroAssembler::Jump m_exceptionCheck;
- CodeOrigin m_codeOrigin;
-};
-
struct PropertyAccessRecord {
enum RegisterMode { RegistersFlushed, RegistersInUse };
@@ -324,28 +241,11 @@
m_disassembler->setEndOfCode(labelIgnoringWatchpoints());
}
- unsigned currentCodeOriginIndex() const
+ void emitStoreCodeOrigin(CodeOrigin codeOrigin)
{
- return m_currentCodeOriginIndex;
- }
-
- // Get a token for beginning a call, and set the current code origin index in
- // the call frame. For each beginCall() there must be at least one exception
- // check, and all of the exception checks must have the same CodeOrigin as the
- // beginCall().
- void beginCall(CodeOrigin codeOrigin, CallBeginToken& token)
- {
- unsigned index = m_exceptionChecks.size();
+ unsigned index = m_jitCode->common.addCodeOrigin(codeOrigin);
unsigned locationBits = CallFrame::Location::encodeAsCodeOriginIndex(index);
store32(TrustedImm32(locationBits), tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
- token.set(codeOrigin, index);
- }
-
- // Notify the JIT of a call that does not require linking.
- void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
- {
- token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
- m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin));
}
// Add a call out from JIT code, without an exception check.
@@ -356,26 +256,20 @@
return functionCall;
}
- void prepareForExceptionCheck()
+ void exceptionCheck(Jump jumpToHandler)
{
- move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
+ m_exceptionChecks.append(jumpToHandler);
}
-
- // Add a call out from JIT code, with an exception check.
- void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
+
+ void exceptionCheck()
{
- prepareForExceptionCheck();
- token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
- m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin));
+ m_exceptionChecks.append(emitExceptionCheck());
}
// Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
- void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken& token)
+ void fastExceptionCheck()
{
- prepareForExceptionCheck();
- Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
- token.registerWithExceptionCheck(codeOrigin, m_exceptionChecks.size());
- m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
+ m_exceptionChecks.append(branchTestPtr(Zero, GPRInfo::returnValueGPR));
}
void appendExitInfo(MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList())
@@ -498,7 +392,7 @@
// Vector of calls out from JIT code, including exception handler information.
// Count of the number of CallRecords with exception handlers.
Vector<CallLinkRecord> m_calls;
- Vector<CallExceptionRecord> m_exceptionChecks;
+ JumpList m_exceptionChecks;
Vector<Label> m_blockHeads;
@@ -526,7 +420,6 @@
Vector<JSCallRecord, 4> m_jsCalls;
Vector<OSRExitCompilationInfo> m_exitCompilationInfo;
Vector<Vector<Label> > m_exitSiteLabels;
- unsigned m_currentCodeOriginIndex;
Call m_callStackCheck;
Call m_callArityCheck;
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 84b22e7..046ca0b 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -1904,29 +1904,8 @@
return JSC::stringFromCharCode(exec, op1);
}
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex)
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec)
{
- // FIXME: This isn't needed anymore.
- // https://bugs.webkit.org/show_bug.cgi?id=121734
- UNUSED_PARAM(callIndex);
-
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
-
- JSValue exceptionValue = exec->exception();
- ASSERT(exceptionValue);
-
- ExceptionHandler handler = genericUnwind(vm, exec, exceptionValue);
- ASSERT(handler.catchRoutine);
- return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
-}
-
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
-{
- // FIXME: This isn't needed anymore.
- // https://bugs.webkit.org/show_bug.cgi?id=121734
- UNUSED_PARAM(stubInfo);
-
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index f07a61a..6e8fed2 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -300,8 +300,7 @@
return createDFGHandler(exec, handler).u.encoded;
}
#endif
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t) WTF_INTERNAL;
-DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*) WTF_INTERNAL;
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*) WTF_INTERNAL;
// These operations implement the implicitly called ToInt32 and ToBoolean conversions from ES5.
// This conversion returns an int32_t within a size_t such that the value is zero extended to fill the register.
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 8dabd13..54baab2 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -514,8 +514,7 @@
#endif
success = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
- stubJit.setupArgumentsWithExecState(
- MacroAssembler::TrustedImmPtr(&stubInfo));
+ stubJit.setupArgumentsExecState();
handlerCall = stubJit.call();
stubJit.jump(GPRInfo::returnValueGPR2);
} else {
@@ -550,7 +549,7 @@
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
if (!isDirect) {
patchBuffer.link(operationCall, operationFunction);
- patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
+ patchBuffer.link(handlerCall, lookupExceptionHandler);
}
RefPtr<JITStubRoutine> stubRoutine =
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index dd29385..3b4432c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1693,11 +1693,9 @@
JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
{
prepareForExternalCall();
- CodeOrigin codeOrigin = m_currentNode->codeOrigin;
- CallBeginToken token;
- m_jit.beginCall(codeOrigin, token);
+ m_jit.emitStoreCodeOrigin(m_currentNode->codeOrigin);
JITCompiler::Call call = m_jit.appendCall(function);
- m_jit.addExceptionCheck(call, codeOrigin, token);
+ m_jit.exceptionCheck();
return call;
}
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
@@ -1710,6 +1708,7 @@
JITCompiler::Call appendCallSetResult(const FunctionPtr& function, GPRReg result)
{
prepareForExternalCall();
+ m_jit.emitStoreCodeOrigin(m_currentNode->codeOrigin);
JITCompiler::Call call = m_jit.appendCall(function);
if (result != InvalidGPRReg)
m_jit.move(GPRInfo::returnValueGPR, result);
@@ -1718,6 +1717,7 @@
JITCompiler::Call appendCall(const FunctionPtr& function)
{
prepareForExternalCall();
+ m_jit.emitStoreCodeOrigin(m_currentNode->codeOrigin);
return m_jit.appendCall(function);
}
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
@@ -1738,7 +1738,7 @@
}
JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
{
- JITCompiler::Call call = m_jit.appendCall(function);
+ JITCompiler::Call call = appendCall(function);
if (result != InvalidFPRReg) {
m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
@@ -1756,7 +1756,7 @@
}
JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
{
- JITCompiler::Call call = m_jit.appendCall(function);
+ JITCompiler::Call call = appendCall(function);
if (result != InvalidFPRReg)
m_jit.moveDouble(result, FPRInfo::argumentFPR0);
return call;
@@ -1771,7 +1771,7 @@
}
JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
{
- JITCompiler::Call call = m_jit.appendCall(function);
+ JITCompiler::Call call = appendCall(function);
if (result != InvalidFPRReg)
m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
return call;
@@ -1787,7 +1787,7 @@
}
JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
{
- JITCompiler::Call call = m_jit.appendCall(function);
+ JITCompiler::Call call = appendCall(function);
if (result != InvalidFPRReg)
m_jit.moveDouble(FPRInfo::returnValueFPR, result);
return call;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index ae64d2e..9e7489a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -736,8 +736,7 @@
JITCompiler::DataLabelPtr targetToCheck;
JITCompiler::JumpList slowPath;
- CallBeginToken token;
- m_jit.beginCall(node->codeOrigin, token);
+ m_jit.emitStoreCodeOrigin(node->codeOrigin);
m_jit.addPtr(TrustedImm32(-(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register))), GPRInfo::callFrameRegister);
@@ -747,9 +746,7 @@
m_jit.storePtr(resultPayloadGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
- CodeOrigin codeOrigin = node->codeOrigin;
JITCompiler::Call fastCall = m_jit.nearCall();
- m_jit.notifyCall(fastCall, codeOrigin, token);
JITCompiler::Jump done = m_jit.jump();
@@ -766,9 +763,7 @@
m_jit.move(calleePayloadGPR, GPRInfo::nonArgGPR0);
m_jit.move(calleeTagGPR, GPRInfo::nonArgGPR1);
}
- m_jit.prepareForExceptionCheck();
JITCompiler::Call slowCall = m_jit.nearCall();
- m_jit.notifyCall(slowCall, codeOrigin, token);
done.link(&m_jit);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 8c477e8..843433f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -747,8 +747,7 @@
JITCompiler::DataLabelPtr targetToCheck;
JITCompiler::JumpList slowPath;
- CallBeginToken token;
- m_jit.beginCall(node->codeOrigin, token);
+ m_jit.emitStoreCodeOrigin(node->codeOrigin);
m_jit.addPtr(TrustedImm32(-(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register))), GPRInfo::callFrameRegister);
@@ -757,18 +756,14 @@
m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
m_jit.store64(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
- CodeOrigin codeOrigin = m_currentNode->codeOrigin;
JITCompiler::Call fastCall = m_jit.nearCall();
- m_jit.notifyCall(fastCall, codeOrigin, token);
JITCompiler::Jump done = m_jit.jump();
slowPath.link(&m_jit);
m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
- m_jit.prepareForExceptionCheck();
JITCompiler::Call slowCall = m_jit.nearCall();
- m_jit.notifyCall(slowCall, codeOrigin, token);
done.link(&m_jit);
diff --git a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp
index 7262796..446e060 100644
--- a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp
@@ -122,11 +122,11 @@
// for the function (and checked for on entry). Since we perform a new and
// different allocation of temporaries, more registers may now be required.
unsigned calleeRegisters = scoreBoard.highWatermark() + m_graph.m_parameterSlots;
- size_t inlineCallFrameCount = codeBlock()->inlineCallFrames().size();
+ size_t inlineCallFrameCount = m_graph.m_inlineCallFrames->size();
for (size_t i = 0; i < inlineCallFrameCount; i++) {
- InlineCallFrame& inlineCallFrame = codeBlock()->inlineCallFrames()[i];
- CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(&inlineCallFrame);
- unsigned requiredCalleeRegisters = operandToLocal(inlineCallFrame.stackOffset) + codeBlock->m_numCalleeRegisters;
+ InlineCallFrame* inlineCallFrame = m_graph.m_inlineCallFrames->at(i);
+ CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
+ unsigned requiredCalleeRegisters = operandToLocal(inlineCallFrame->stackOffset) + codeBlock->m_numCalleeRegisters;
if (requiredCalleeRegisters > calleeRegisters)
calleeRegisters = requiredCalleeRegisters;
}
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
index 89614ca..8a3b204 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
@@ -3236,7 +3236,7 @@
m_out.store32(
m_out.constInt32(
CallFrame::Location::encodeAsCodeOriginIndex(
- codeBlock()->addCodeOrigin(codeOrigin))),
+ m_ftlState.jitCode->common.addCodeOrigin(codeOrigin))),
tagFor(JSStack::ArgumentCount));
}
void callPreflight()
diff --git a/Source/JavaScriptCore/jit/AssemblyHelpers.h b/Source/JavaScriptCore/jit/AssemblyHelpers.h
index 4f540e7..7b7bccc 100644
--- a/Source/JavaScriptCore/jit/AssemblyHelpers.h
+++ b/Source/JavaScriptCore/jit/AssemblyHelpers.h
@@ -327,9 +327,9 @@
Jump emitExceptionCheck(ExceptionCheckKind kind = NormalExceptionCheck)
{
#if USE(JSVALUE64)
- return branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException()));
+ return branchTest64(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(vm()->addressOfException()));
#elif USE(JSVALUE32_64)
- return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast<char*>(vm()->addressOfException()) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+ return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast<char*>(vm()->addressOfException()) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
#endif
}