Commit 5ba07883 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Baseline JIT and DFG IC code generation should be unified and rationalized

https://bugs.webkit.org/show_bug.cgi?id=122939

Reviewed by Geoffrey Garen.
        
Introduce the JITInlineCacheGenerator, which takes a CodeBlock and a CodeOrigin plus
some register info and creates JIT inline caches for you. Used this to even furhter
unify the baseline and DFG ICs. In the future we can use this for FTL ICs. And my hope
is that we'll be able to use it for cascading ICs: an IC for some instruction may realize
that it needs to do the equivalent of get_by_id, so with this generator it will be able
to create an IC even though it wasn't associated with a get_by_id bytecode instruction.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::DataLabelCompact::label):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::ecmaMode):
* dfg/DFGInlineCacheWrapper.h: Added.
(JSC::DFG::InlineCacheWrapper::InlineCacheWrapper):
* dfg/DFGInlineCacheWrapperInlines.h: Added.
(JSC::DFG::::finalize):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addGetById):
(JSC::DFG::JITCompiler::addPutById):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::isStrictModeFor):
(JSC::AssemblyHelpers::strictModeFor):
* jit/GPRInfo.h:
(JSC::JSValueRegs::tagGPR):
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITInlineCacheGenerator.cpp: Added.
(JSC::JITInlineCacheGenerator::JITInlineCacheGenerator):
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITByIdGenerator::finalize):
(JSC::JITByIdGenerator::generateFastPathChecks):
(JSC::JITGetByIdGenerator::generateFastPath):
(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
(JSC::JITPutByIdGenerator::generateFastPath):
(JSC::JITPutByIdGenerator::slowPathFunction):
* jit/JITInlineCacheGenerator.h: Added.
(JSC::JITInlineCacheGenerator::JITInlineCacheGenerator):
(JSC::JITInlineCacheGenerator::stubInfo):
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITByIdGenerator::reportSlowPathCall):
(JSC::JITByIdGenerator::slowPathJump):
(JSC::JITGetByIdGenerator::JITGetByIdGenerator):
(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
* jit/RegisterSet.h:
(JSC::RegisterSet::set):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@157685 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6395a0fe
......@@ -226,6 +226,7 @@ set(JavaScriptCore_SOURCES
jit/JITCode.cpp
jit/JITDisassembler.cpp
jit/JITExceptions.cpp
jit/JITInlineCacheGenerator.cpp
jit/JITOpcodes.cpp
jit/JITOpcodes32_64.cpp
jit/JITOperations.cpp
......
2013-10-19 Filip Pizlo <fpizlo@apple.com>
Baseline JIT and DFG IC code generation should be unified and rationalized
https://bugs.webkit.org/show_bug.cgi?id=122939
Reviewed by Geoffrey Garen.
Introduce the JITInlineCacheGenerator, which takes a CodeBlock and a CodeOrigin plus
some register info and creates JIT inline caches for you. Used this to even furhter
unify the baseline and DFG ICs. In the future we can use this for FTL ICs. And my hope
is that we'll be able to use it for cascading ICs: an IC for some instruction may realize
that it needs to do the equivalent of get_by_id, so with this generator it will be able
to create an IC even though it wasn't associated with a get_by_id bytecode instruction.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::DataLabelCompact::label):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::ecmaMode):
* dfg/DFGInlineCacheWrapper.h: Added.
(JSC::DFG::InlineCacheWrapper::InlineCacheWrapper):
* dfg/DFGInlineCacheWrapperInlines.h: Added.
(JSC::DFG::::finalize):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addGetById):
(JSC::DFG::JITCompiler::addPutById):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::isStrictModeFor):
(JSC::AssemblyHelpers::strictModeFor):
* jit/GPRInfo.h:
(JSC::JSValueRegs::tagGPR):
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITInlineCacheGenerator.cpp: Added.
(JSC::JITInlineCacheGenerator::JITInlineCacheGenerator):
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITByIdGenerator::finalize):
(JSC::JITByIdGenerator::generateFastPathChecks):
(JSC::JITGetByIdGenerator::generateFastPath):
(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
(JSC::JITPutByIdGenerator::generateFastPath):
(JSC::JITPutByIdGenerator::slowPathFunction):
* jit/JITInlineCacheGenerator.h: Added.
(JSC::JITInlineCacheGenerator::JITInlineCacheGenerator):
(JSC::JITInlineCacheGenerator::stubInfo):
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITByIdGenerator::reportSlowPathCall):
(JSC::JITByIdGenerator::slowPathJump):
(JSC::JITGetByIdGenerator::JITGetByIdGenerator):
(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
* jit/RegisterSet.h:
(JSC::RegisterSet::set):
2013-10-19 Alexey Proskuryakov <ap@apple.com>
APICast.h uses functions from JSCJSValueInlines.h, but doesn't include it
......
......@@ -280,6 +280,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGGraph.h \
Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp \
Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h \
Source/JavaScriptCore/dfg/DFGInlineCacheWrapper.h \
Source/JavaScriptCore/dfg/DFGInlineCacheWrapperInlines.h \
Source/JavaScriptCore/dfg/DFGInsertionSet.h \
Source/JavaScriptCore/dfg/DFGJITCode.cpp \
Source/JavaScriptCore/dfg/DFGJITCode.h \
......@@ -630,6 +632,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/JIT.h \
Source/JavaScriptCore/jit/JITExceptions.cpp \
Source/JavaScriptCore/jit/JITExceptions.h \
Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp \
Source/JavaScriptCore/jit/JITInlineCacheGenerator.h \
Source/JavaScriptCore/jit/JITInlines.h \
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp \
Source/JavaScriptCore/jit/JITOpcodes.cpp \
......
......@@ -378,6 +378,7 @@
<ClCompile Include="..\jit\JITCode.cpp" />
<ClCompile Include="..\jit\JITDisassembler.cpp" />
<ClCompile Include="..\jit\JITExceptions.cpp" />
<ClCompile Include="..\jit\JITInlineCacheGenerator.cpp" />
<ClCompile Include="..\jit\JITOpcodes.cpp" />
<ClCompile Include="..\jit\JITOpcodes32_64.cpp" />
<ClCompile Include="..\jit\JITOperations.cpp" />
......@@ -775,6 +776,7 @@
<ClInclude Include="..\jit\JITCompilationEffort.h" />
<ClInclude Include="..\jit\JITDisassembler.h" />
<ClInclude Include="..\jit\JITExceptions.h" />
<ClInclude Include="..\jit\JITInlineCacheGenerator.h" />
<ClInclude Include="..\jit\JITInlines.h" />
<ClInclude Include="..\jit\JITOperationWrappers.h" />
<ClInclude Include="..\jit\JITOperations.h" />
......
......@@ -334,6 +334,10 @@
0FB1058C1675483300F8AB6E /* ProfilerOSRExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB105881675482E00F8AB6E /* ProfilerOSRExit.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB105891675482E00F8AB6E /* ProfilerOSRExitSite.cpp */; };
0FB1058E1675483A00F8AB6E /* ProfilerOSRExitSite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB1058A1675482E00F8AB6E /* ProfilerOSRExitSite.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB14E1E18124ACE009B6B4D /* JITInlineCacheGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB14E1C18124ACE009B6B4D /* JITInlineCacheGenerator.cpp */; };
0FB14E1F18124ACE009B6B4D /* JITInlineCacheGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E1D18124ACE009B6B4D /* JITInlineCacheGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB14E211812570B009B6B4D /* DFGInlineCacheWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB14E2318130955009B6B4D /* DFGInlineCacheWrapperInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; };
0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1580,6 +1584,10 @@
0FB105881675482E00F8AB6E /* ProfilerOSRExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOSRExit.h; path = profiler/ProfilerOSRExit.h; sourceTree = "<group>"; };
0FB105891675482E00F8AB6E /* ProfilerOSRExitSite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOSRExitSite.cpp; path = profiler/ProfilerOSRExitSite.cpp; sourceTree = "<group>"; };
0FB1058A1675482E00F8AB6E /* ProfilerOSRExitSite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOSRExitSite.h; path = profiler/ProfilerOSRExitSite.h; sourceTree = "<group>"; };
0FB14E1C18124ACE009B6B4D /* JITInlineCacheGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITInlineCacheGenerator.cpp; sourceTree = "<group>"; };
0FB14E1D18124ACE009B6B4D /* JITInlineCacheGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITInlineCacheGenerator.h; sourceTree = "<group>"; };
0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapper.h; path = dfg/DFGInlineCacheWrapper.h; sourceTree = "<group>"; };
0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapperInlines.h; path = dfg/DFGInlineCacheWrapperInlines.h; sourceTree = "<group>"; };
0FB4B51016B3A964003F696B /* DFGMinifiedID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMinifiedID.h; path = dfg/DFGMinifiedID.h; sourceTree = "<group>"; };
0FB4B51916B62772003F696B /* DFGAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAllocator.h; path = dfg/DFGAllocator.h; sourceTree = "<group>"; };
0FB4B51A16B62772003F696B /* DFGCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCommon.cpp; path = dfg/DFGCommon.cpp; sourceTree = "<group>"; };
......@@ -2870,6 +2878,8 @@
0FAF7EFB165BA919000C8455 /* JITDisassembler.h */,
0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
0F46808014BA572700BFE272 /* JITExceptions.h */,
0FB14E1C18124ACE009B6B4D /* JITInlineCacheGenerator.cpp */,
0FB14E1D18124ACE009B6B4D /* JITInlineCacheGenerator.h */,
86CC85A00EE79A4700288682 /* JITInlines.h */,
BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */,
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */,
......@@ -3616,8 +3626,6 @@
86EC9DB31328DF44002B2AD7 /* dfg */ = {
isa = PBXGroup;
children = (
0F9D339417FFC4E60073C2BC /* DFGFlushedAt.cpp */,
0F9D339517FFC4E60073C2BC /* DFGFlushedAt.h */,
A77A423617A0BBFD00A8DB81 /* DFGAbstractHeap.cpp */,
A77A423717A0BBFD00A8DB81 /* DFGAbstractHeap.h */,
A704D8FE17A0BAA8006BA554 /* DFGAbstractInterpreter.h */,
......@@ -3706,6 +3714,8 @@
A78A976F179738B8009DF744 /* DFGFinalizer.h */,
0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */,
0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */,
0F9D339417FFC4E60073C2BC /* DFGFlushedAt.cpp */,
0F9D339517FFC4E60073C2BC /* DFGFlushedAt.h */,
A7D89CE817A0B8CC00773AD8 /* DFGFlushFormat.cpp */,
A7D89CE917A0B8CC00773AD8 /* DFGFlushFormat.h */,
A7D89CEA17A0B8CC00773AD8 /* DFGFlushLivenessAnalysisPhase.cpp */,
......@@ -3713,6 +3723,8 @@
86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */,
86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */,
86EC9DB81328DF82002B2AD7 /* DFGGraph.h */,
0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
A704D90117A0BAA8006BA554 /* DFGInPlaceAbstractState.h */,
0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */,
......@@ -4417,6 +4429,7 @@
BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */,
9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */,
7C184E1B17BEDBD3007CB63A /* JSPromise.h in Headers */,
0FB14E1F18124ACE009B6B4D /* JITInlineCacheGenerator.h in Headers */,
7C15F65E17C199CE00794D40 /* JSPromiseCallback.h in Headers */,
7C184E2317BEE240007CB63A /* JSPromiseConstructor.h in Headers */,
7C184E1F17BEE22E007CB63A /* JSPromisePrototype.h in Headers */,
......@@ -4449,8 +4462,10 @@
0F2B670217B6B5AB00A7AE3F /* JSUint16Array.h in Headers */,
0F2B670317B6B5AB00A7AE3F /* JSUint32Array.h in Headers */,
0F2B670017B6B5AB00A7AE3F /* JSUint8Array.h in Headers */,
0FB14E2318130955009B6B4D /* DFGInlineCacheWrapperInlines.h in Headers */,
0F2B670117B6B5AB00A7AE3F /* JSUint8ClampedArray.h in Headers */,
86E3C612167BABD7006D760A /* JSValue.h in Headers */,
0FB14E211812570B009B6B4D /* DFGInlineCacheWrapper.h in Headers */,
86E3C61B167BABEE006D760A /* JSValueInternal.h in Headers */,
BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */,
BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */,
......@@ -5269,6 +5284,7 @@
0F235BD317178E1C00690C7F /* FTLExitArgument.cpp in Sources */,
0F235BD517178E1C00690C7F /* FTLExitArgumentForOperand.cpp in Sources */,
0F235BD817178E1C00690C7F /* FTLExitThunkGenerator.cpp in Sources */,
0FB14E1E18124ACE009B6B4D /* JITInlineCacheGenerator.cpp in Sources */,
0F235BDA17178E1C00690C7F /* FTLExitValue.cpp in Sources */,
A7F2996B17A0BB670010417A /* FTLFail.cpp in Sources */,
0FEA0A281709623B00BB722C /* FTLIntrinsicRepository.cpp in Sources */,
......
......@@ -464,6 +464,8 @@ public:
{
}
AssemblerLabel label() const { return m_label; }
private:
AssemblerLabel m_label;
};
......
......@@ -147,6 +147,7 @@ public:
void printStructure(PrintStream&, const char* name, const Instruction*, int operand);
bool isStrictMode() const { return m_isStrictMode; }
ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
inline bool isKnownNotImmediate(int index)
{
......
/*
* 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 DFGInlineCacheWrapper_h
#define DFGInlineCacheWrapper_h
#if ENABLE(DFG_JIT)
#include "JITInlineCacheGenerator.h"
namespace JSC { namespace DFG {
class SlowPathGenerator;
template<typename GeneratorType>
struct InlineCacheWrapper {
InlineCacheWrapper() { }
InlineCacheWrapper(const GeneratorType& generator, SlowPathGenerator* slowPath)
: m_generator(generator)
, m_slowPath(slowPath)
{
}
void finalize(LinkBuffer&);
GeneratorType m_generator;
SlowPathGenerator* m_slowPath;
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGInlineCacheWrapper_h
/*
* 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 DFGInlineCacheWrapperInlines_h
#define DFGInlineCacheWrapperInlines_h
#if ENABLE(DFG_JIT)
#include "DFGInlineCacheWrapper.h"
#include "DFGSlowPathGenerator.h"
namespace JSC { namespace DFG {
template<typename GeneratorType>
void InlineCacheWrapper<GeneratorType>::finalize(LinkBuffer& linkBuffer)
{
m_generator.reportSlowPathCall(m_slowPath->label(), m_slowPath->call());
m_generator.finalize(linkBuffer);
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGInlineCacheWrapperInlines_h
......@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "DFGFailedFinalizer.h"
#include "DFGInlineCacheWrapperInlines.h"
#include "DFGJITCode.h"
#include "DFGJITFinalizer.h"
#include "DFGOSRExitCompiler.h"
......@@ -222,22 +223,11 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
for (unsigned i = 0; i < m_calls.size(); ++i)
linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) {
StructureStubInfo& info = *m_propertyAccesses[i].m_stubInfo;
CodeLocationCall callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_slowPathGenerator->call());
info.callReturnLocation = callReturnLocation;
info.patch.deltaCheckImmToCall = differenceBetweenCodePtr(linkBuffer.locationOf(m_propertyAccesses[i].m_structureImm), callReturnLocation);
info.patch.deltaCallToStructCheck = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_structureCheck));
#if USE(JSVALUE64)
info.patch.deltaCallToLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_loadOrStore));
#else
info.patch.deltaCallToTagLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_tagLoadOrStore));
info.patch.deltaCallToPayloadLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_payloadLoadOrStore));
#endif
info.patch.deltaCallToSlowCase = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_slowPathGenerator->label()));
info.patch.deltaCallToDone = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_done));
info.patch.deltaCallToStorageLoad = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_propertyStorageLoad));
}
for (unsigned i = m_getByIds.size(); i--;)
m_getByIds[i].finalize(linkBuffer);
for (unsigned i = m_putByIds.size(); i--;)
m_putByIds[i].finalize(linkBuffer);
for (unsigned i = 0; i < m_ins.size(); ++i) {
StructureStubInfo& info = *m_ins[i].m_stubInfo;
CodeLocationLabel jump = linkBuffer.locationOf(m_ins[i].m_jump);
......
......@@ -33,12 +33,14 @@
#include "CodeBlock.h"
#include "DFGDisassembler.h"
#include "DFGGraph.h"
#include "DFGInlineCacheWrapper.h"
#include "DFGJITCode.h"
#include "DFGOSRExitCompilationInfo.h"
#include "DFGRegisterBank.h"
#include "FPRInfo.h"
#include "GPRInfo.h"
#include "JITCode.h"
#include "JITInlineCacheGenerator.h"
#include "LinkBuffer.h"
#include "MacroAssembler.h"
#include "RegisterSet.h"
......@@ -77,49 +79,6 @@ struct CallLinkRecord {
FunctionPtr m_function;
};
struct PropertyAccessRecord {
PropertyAccessRecord(
MacroAssembler::DataLabelPtr structureImm,
MacroAssembler::PatchableJump structureCheck,
MacroAssembler::ConvertibleLoadLabel propertyStorageLoad,
#if USE(JSVALUE64)
MacroAssembler::DataLabelCompact loadOrStore,
#elif USE(JSVALUE32_64)
MacroAssembler::DataLabelCompact tagLoadOrStore,
MacroAssembler::DataLabelCompact payloadLoadOrStore,
#endif
SlowPathGenerator* slowPathGenerator,
MacroAssembler::Label done,
StructureStubInfo* stubInfo)
: m_structureImm(structureImm)
, m_structureCheck(structureCheck)
, m_propertyStorageLoad(propertyStorageLoad)
#if USE(JSVALUE64)
, m_loadOrStore(loadOrStore)
#elif USE(JSVALUE32_64)
, m_tagLoadOrStore(tagLoadOrStore)
, m_payloadLoadOrStore(payloadLoadOrStore)
#endif
, m_slowPathGenerator(slowPathGenerator)
, m_done(done)
, m_stubInfo(stubInfo)
{
}
MacroAssembler::DataLabelPtr m_structureImm;
MacroAssembler::PatchableJump m_structureCheck;
MacroAssembler::ConvertibleLoadLabel m_propertyStorageLoad;
#if USE(JSVALUE64)
MacroAssembler::DataLabelCompact m_loadOrStore;
#elif USE(JSVALUE32_64)
MacroAssembler::DataLabelCompact m_tagLoadOrStore;
MacroAssembler::DataLabelCompact m_payloadLoadOrStore;
#endif
SlowPathGenerator* m_slowPathGenerator;
MacroAssembler::Label m_done;
StructureStubInfo* m_stubInfo;
};
struct InRecord {
InRecord(
MacroAssembler::PatchableJump jump, SlowPathGenerator* slowPathGenerator,
......@@ -254,11 +213,16 @@ public:
}
#endif
void addPropertyAccess(const PropertyAccessRecord& record)
void addGetById(const JITGetByIdGenerator& gen, SlowPathGenerator* slowPath)
{
m_propertyAccesses.append(record);
m_getByIds.append(InlineCacheWrapper<JITGetByIdGenerator>(gen, slowPath));
}
void addPutById(const JITPutByIdGenerator& gen, SlowPathGenerator* slowPath)
{
m_putByIds.append(InlineCacheWrapper<JITPutByIdGenerator>(gen, slowPath));
}
void addIn(const InRecord& record)
{
m_ins.append(record);
......@@ -385,7 +349,8 @@ private:
CodeOrigin m_codeOrigin;
};
Vector<PropertyAccessRecord, 4> m_propertyAccesses;
Vector<InlineCacheWrapper<JITGetByIdGenerator>, 4> m_getByIds;
Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds;
Vector<InRecord, 4> m_ins;
Vector<JSCallRecord, 4> m_jsCalls;
Vector<OSRExitCompilationInfo> m_exitCompilationInfo;
......
......@@ -197,129 +197,57 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
{
StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo();
JITGetByIdGenerator gen(
m_jit.codeBlock(), codeOrigin, usedRegisters(),
JSValueRegs(baseTagGPROrNone, basePayloadGPR),
JSValueRegs(resultTagGPR, resultPayloadGPR), spillMode != NeedToSpill);
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(unusedPointer)));
gen.generateFastPath(m_jit);
JITCompiler::ConvertibleLoadLabel propertyStorageLoad = m_jit.convertibleLoadPtr(JITCompiler::Address(basePayloadGPR, JSObject::butterflyOffset()), resultPayloadGPR);
JITCompiler::DataLabelCompact tagLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
JITCompiler::DataLabelCompact payloadLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
JITCompiler::JumpList slowCases;
if (slowPathTarget.isSet())
slowCases.append(slowPathTarget);
slowCases.append(gen.slowPathJump());
JITCompiler::Label doneLabel = m_jit.label();
OwnPtr<SlowPathGenerator> slowPath;
if (baseTagGPROrNone == InvalidGPRReg) {
if (!slowPathTarget.isSet()) {
slowPath = slowPathCall(
structureCheck.m_jump, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), stubInfo,
static_cast<int32_t>(JSValue::CellTag), basePayloadGPR,
identifierUID(identifierNumber));
} else {
JITCompiler::JumpList slowCases;
slowCases.append(structureCheck.m_jump);
slowCases.append(slowPathTarget);
slowPath = slowPathCall(
slowCases, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), stubInfo,
static_cast<int32_t>(JSValue::CellTag), basePayloadGPR,
identifierUID(identifierNumber));
}
slowPath = slowPathCall(
slowCases, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
static_cast<int32_t>(JSValue::CellTag), basePayloadGPR,
identifierUID(identifierNumber));
} else {
if (!slowPathTarget.isSet()) {
slowPath = slowPathCall(
structureCheck.m_jump, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), stubInfo, baseTagGPROrNone,
basePayloadGPR, identifierUID(identifierNumber));
} else {
JITCompiler::JumpList slowCases;
slowCases.append(structureCheck.m_jump);
slowCases.append(slowPathTarget);
slowPath = slowPathCall(
slowCases, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), stubInfo, baseTagGPROrNone,
basePayloadGPR, identifierUID(identifierNumber));
}
slowPath = slowPathCall(
slowCases, this, operationGetByIdOptimize,
JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), baseTagGPROrNone,
basePayloadGPR, identifierUID(identifierNumber));
}
RegisterSet currentlyUsedRegisters = usedRegisters();
ASSERT(currentlyUsedRegisters.get(basePayloadGPR));
ASSERT(currentlyUsedRegisters.get(resultTagGPR));
ASSERT(currentlyUsedRegisters.get(resultPayloadGPR));
stubInfo->codeOrigin = codeOrigin;
stubInfo->patch.baseGPR = static_cast<int8_t>(basePayloadGPR);
stubInfo->patch.valueGPR = static_cast<int8_t>(resultPayloadGPR);
stubInfo->patch.valueTagGPR = static_cast<int8_t>(resultTagGPR);
stubInfo->patch.usedRegisters = currentlyUsedRegisters;
stubInfo->patch.registersFlushed = spillMode != NeedToSpill;
m_jit.addPropertyAccess(
PropertyAccessRecord(
structureToCompare, structureCheck, propertyStorageLoad,
tagLoadWithPatch, payloadLoadWithPatch, slowPath.get(), doneLabel,
stubInfo));
m_jit.addGetById(gen, slowPath.get());
addSlowPathGenerator(slowPath.release());
}
void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
{
StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo();
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(unusedPointer)));
writeBarrier(basePayloadGPR, valueTagGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR);
JITPutByIdGenerator gen(
m_jit.codeBlock(), codeOrigin, usedRegisters(), JSValueRegs::payloadOnly(basePayloadGPR),
JSValueRegs(valueTagGPR, valuePayloadGPR), scratchGPR, false,
m_jit.ecmaModeFor(codeOrigin), putKind);
gen.generateFastPath(m_jit);
JITCompiler::JumpList slowCases;
if (slowPathTarget.isSet())
slowCases.append(slowPathTarget);
slowCases.append(gen.slowPathJump());
JITCompiler::ConvertibleLoadLabel propertyStorageLoad = m_jit.convertibleLoadPtr(JITCompiler::Address(basePayloadGPR, JSObject::butterflyOffset()), scratchGPR);
JITCompiler::DataLabel32 tagStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valueTagGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
JITCompiler::DataLabel32 payloadStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valuePayloadGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
OwnPtr<SlowPathGenerator> slowPath = slowPathCall(
slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), valueTagGPR,
valuePayloadGPR, basePayloadGPR, identifierUID(identifierNumber));
JITCompiler::Label doneLabel = m_jit.label();
V_JITOperation_ESsiJJI optimizedCall;
if (m_jit.strictModeFor(m_currentNode->codeOrigin)) {
if (putKind == Direct)
optimizedCall = operationPutByIdDirectStrictOptimize;
else
optimizedCall = operationPutByIdStrictOptimize;
} else {
if (putKind == Direct)
optimizedCall = operationPutByIdDirectNonStrictOptimize;
else
optimizedCall = operationPutByIdNonStrictOptimize;
}
OwnPtr<SlowPathGenerator> slowPath;
if (!slowPathTarget.isSet()) {
slowPath = slowPathCall(
structureCheck.m_jump, this, optimizedCall, NoResult, stubInfo, valueTagGPR,
valuePayloadGPR, basePayloadGPR, identifierUID(identifierNumber));
} else {
JITCompiler::JumpList slowCases;
slowCases.append(structureCheck.m_jump);
slowCases.append(slowPathTarget);
slowPath = slowPathCall(
slowCases, this, optimizedCall, NoResult, stubInfo, valueTagGPR, valuePayloadGPR,
basePayloadGPR, identifierUID(identifierNumber));
}
RegisterSet currentlyUsedRegisters = usedRegisters();
currentlyUsedRegisters.clear(scratchGPR);
ASSERT(currentlyUsedRegisters.get(basePayloadGPR));
ASSERT(currentlyUsedRegisters.get(valueTagGPR));
ASSERT(currentlyUsedRegisters.get(valuePayloadGPR));
stubInfo->codeOrigin = codeOrigin;
stubInfo->patch.baseGPR = static_cast<int8_t>(basePayloadGPR);
stubInfo->patch.valueGPR = static_cast<int8_t>(valuePayloadGPR);
stubInfo->patch.valueTagGPR = static_cast<int8_t>(valueTagGPR);
stubInfo->patch.usedRegisters = currentlyUsedRegisters;
stubInfo->patch.registersFlushed = false;
m_jit.addPropertyAccess(
PropertyAccessRecord(
structureToCompare, structureCheck, propertyStorageLoad,
JITCompiler::DataLabelCompact(tagStoreWithPatch.label()),
JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()),
slowPath.get(), doneLabel, stubInfo));
m_jit.addPutById(gen, slowPath.get());
addSlowPathGenerator(slowPath.release());
}
......
......@@ -209,103 +209,43 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
{
StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo();
JITGetByIdGenerator gen(
m_jit.codeBlock(), codeOrigin, usedRegisters(), JSValueRegs(baseGPR),
JSValueRegs(resultGPR), spillMode != NeedToSpill);
gen.generateFastPath(m_jit);
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(unusedPointer)));
JITCompiler::JumpList slowCases;
if (slowPathTarget.isSet())
slowCases.append(slowPathTarget);
slowCases.append(gen.slowPathJump());
JITCompiler::ConvertibleLoadLabel propertyStorageLoad =
m_jit.convertibleLoadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), resultGPR);
JITCompiler::DataLabelCompact loadWithPatch = m_jit.load64WithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
OwnPtr<SlowPathGenerator> slowPath = slowPathCall(
slowCases, this, operationGetByIdOptimize, resultGPR, gen.stubInfo(), baseGPR,
identifierUID(identifierNumber), spillMode);
JITCompiler::Label doneLabel = m_jit.label();
OwnPtr<SlowPathGenerator> slowPath;
if (!slowPathTarget.isSet()) {
slowPath = slowPathCall(
structureCheck.m_jump, this, operationGetByIdOptimize, resultGPR, stubInfo, baseGPR,