source: webkit/trunk/Source/JavaScriptCore/jit/JITCode.cpp

Last change on this file was 293714, checked in by [email protected], 3 years ago

[JSC] Introduce unlinked version of invalidation
https://bugs.webkit.org/show_bug.cgi?id=239887

Reviewed by Saam Barati.

This patch makes invalidation mechanism unlinked for unlinked DFG.

  1. We always use CheckTraps instead of InvalidationPoint with VMTraps so that we do not need

to repatch existing code.

  1. We introduce load-and-branch based InvalidationPoint for unlinked DFG so that we do not need

to repatch it to jump to OSR exit when watchpoint fires. We store this condition in DFG::JITData
so that code can quickly access to that.

  1. We make isStillValid conditions in DFG::CommonData always true for unlinked DFG code. Instead,

we check isJettisoned() condition of CodeBlock since it will become eventually per CodeBlock
information (while this CodeBlock gets invalidated, unlinked DFG code itself can be used for
the other CodeBlock).

After this change, now, jumpReplacements for unlinked DFG becomes empty. We no longer repatch these invalidation points.

  • Source/JavaScriptCore/bytecode/CodeBlock.cpp:

(JSC::CodeBlock::jettison):
(JSC::CodeBlock::hasInstalledVMTrapsBreakpoints const):
(JSC::CodeBlock::canInstallVMTrapBreakpoints const):
(JSC::CodeBlock::installVMTrapBreakpoints):
(JSC::CodeBlock::hasInstalledVMTrapBreakpoints const): Deleted.

  • Source/JavaScriptCore/bytecode/CodeBlock.h:
  • Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • Source/JavaScriptCore/dfg/DFGCommonData.cpp:

(JSC::DFG::CommonData::invalidate):
(JSC::DFG::CommonData::~CommonData):
(JSC::DFG::CommonData::installVMTrapBreakpoints):
(JSC::DFG::CommonData::isVMTrapBreakpoint):

  • Source/JavaScriptCore/dfg/DFGCommonData.h:

(JSC::DFG::CommonData::CommonData):
(JSC::DFG::CommonData::hasInstalledVMTrapsBreakpoints const):
(JSC::DFG::CommonData::isStillValid const):

  • Source/JavaScriptCore/dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • Source/JavaScriptCore/dfg/DFGJITCode.cpp:

(JSC::DFG::JITCode::JITCode):

  • Source/JavaScriptCore/dfg/DFGJITCode.h:
  • Source/JavaScriptCore/dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::link):

  • Source/JavaScriptCore/dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):
(JSC::DFG::prepareCatchOSREntry):

  • Source/JavaScriptCore/dfg/DFGPlan.cpp:

(JSC::DFG::Plan::finalize):

  • Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileInvalidationPoint):
(JSC::DFG::SpeculativeJIT::compileCheckTraps):
(JSC::DFG::SpeculativeJIT::emitInvalidationPoint): Deleted.

  • Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
  • Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • Source/JavaScriptCore/ftl/FTLJITCode.cpp:

(JSC::FTL::JITCode::JITCode):

  • Source/JavaScriptCore/ftl/FTLJITCode.h:

(JSC::FTL::JITCode::isUnlinked const):

  • Source/JavaScriptCore/ftl/FTLOSREntry.cpp:

(JSC::FTL::prepareOSREntry):

  • Source/JavaScriptCore/jit/JITCode.cpp:

(JSC::JITCode::isUnlinked const):

  • Source/JavaScriptCore/jit/JITCode.h:
  • Source/JavaScriptCore/runtime/VMTraps.cpp:

(JSC::VMTraps::tryInstallTrapBreakpoints):
(JSC::VMTraps::handleTraps):

Canonical link: https://commits.webkit.org/250203@main

File size: 7.9 KB
Line 
1/*
2 * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JITCode.h"
28
29#include "DFGJITCode.h"
30#include "FTLJITCode.h"
31
32#include <wtf/PrintStream.h>
33
34namespace JSC {
35
36DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(DirectJITCode);
37
38JITCode::JITCode(JITType jitType, ShareAttribute shareAttribute)
39 : m_jitType(jitType)
40 , m_shareAttribute(shareAttribute)
41{
42}
43
44JITCode::~JITCode()
45{
46}
47
48ASCIILiteral JITCode::typeName(JITType jitType)
49{
50 switch (jitType) {
51 case JITType::None:
52 return "None"_s;
53 case JITType::HostCallThunk:
54 return "Host"_s;
55 case JITType::InterpreterThunk:
56 return "LLInt"_s;
57 case JITType::BaselineJIT:
58 return "Baseline"_s;
59 case JITType::DFGJIT:
60 return "DFG"_s;
61 case JITType::FTLJIT:
62 return "FTL"_s;
63 default:
64 CRASH();
65 return ""_s;
66 }
67}
68
69bool JITCode::isUnlinked() const
70{
71 switch (m_jitType) {
72 case JITType::None:
73 case JITType::HostCallThunk:
74 case JITType::InterpreterThunk:
75 case JITType::BaselineJIT:
76 return true;
77 case JITType::DFGJIT:
78#if ENABLE(DFG_JIT)
79 return static_cast<const DFG::JITCode*>(this)->isUnlinked();
80#else
81 return false;
82#endif
83 case JITType::FTLJIT:
84#if ENABLE(FTL_JIT)
85 return static_cast<const FTL::JITCode*>(this)->isUnlinked();
86#else
87 return false;
88#endif
89 }
90 return true;
91}
92
93void JITCode::validateReferences(const TrackedReferences&)
94{
95}
96
97DFG::CommonData* JITCode::dfgCommon()
98{
99 RELEASE_ASSERT_NOT_REACHED();
100 return nullptr;
101}
102
103DFG::JITCode* JITCode::dfg()
104{
105 RELEASE_ASSERT_NOT_REACHED();
106 return nullptr;
107}
108
109FTL::JITCode* JITCode::ftl()
110{
111 RELEASE_ASSERT_NOT_REACHED();
112 return nullptr;
113}
114
115FTL::ForOSREntryJITCode* JITCode::ftlForOSREntry()
116{
117 RELEASE_ASSERT_NOT_REACHED();
118 return nullptr;
119}
120
121void JITCode::shrinkToFit(const ConcurrentJSLocker&)
122{
123}
124
125const RegisterAtOffsetList* JITCode::calleeSaveRegisters() const
126{
127#if ENABLE(FTL_JIT)
128 if (m_jitType == JITType::FTLJIT)
129 return static_cast<const FTL::JITCode*>(this)->calleeSaveRegisters();
130#endif
131#if ENABLE(DFG_JIT)
132 if (m_jitType == JITType::DFGJIT)
133 return &RegisterAtOffsetList::dfgCalleeSaveRegisters();
134#endif
135#if !ENABLE(C_LOOP)
136 return &RegisterAtOffsetList::llintBaselineCalleeSaveRegisters();
137#else
138 return nullptr;
139#endif
140}
141
142JITCodeWithCodeRef::JITCodeWithCodeRef(JITType jitType)
143 : JITCode(jitType)
144{
145}
146
147JITCodeWithCodeRef::JITCodeWithCodeRef(CodeRef<JSEntryPtrTag> ref, JITType jitType, JITCode::ShareAttribute shareAttribute)
148 : JITCode(jitType, shareAttribute)
149 , m_ref(ref)
150{
151}
152
153JITCodeWithCodeRef::~JITCodeWithCodeRef()
154{
155 if ((Options::dumpDisassembly() || (isOptimizingJIT(jitType()) && Options::dumpDFGDisassembly()))
156 && m_ref.executableMemory())
157 dataLog("Destroying JIT code at ", pointerDump(m_ref.executableMemory()), "\n");
158}
159
160void* JITCodeWithCodeRef::executableAddressAtOffset(size_t offset)
161{
162 RELEASE_ASSERT(m_ref);
163 assertIsTaggedWith<JSEntryPtrTag>(m_ref.code().executableAddress());
164 if (!offset)
165 return m_ref.code().executableAddress();
166
167 char* executableAddress = untagCodePtr<char*, JSEntryPtrTag>(m_ref.code().executableAddress());
168 return tagCodePtr<JSEntryPtrTag>(executableAddress + offset);
169}
170
171void* JITCodeWithCodeRef::dataAddressAtOffset(size_t offset)
172{
173 RELEASE_ASSERT(m_ref);
174 ASSERT(offset <= size()); // use <= instead of < because it is valid to ask for an address at the exclusive end of the code.
175 return m_ref.code().dataLocation<char*>() + offset;
176}
177
178unsigned JITCodeWithCodeRef::offsetOf(void* pointerIntoCode)
179{
180 RELEASE_ASSERT(m_ref);
181 intptr_t result = reinterpret_cast<intptr_t>(pointerIntoCode) - m_ref.code().executableAddress<intptr_t>();
182 ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result)) == result);
183 return static_cast<unsigned>(result);
184}
185
186size_t JITCodeWithCodeRef::size()
187{
188 RELEASE_ASSERT(m_ref);
189 return m_ref.size();
190}
191
192bool JITCodeWithCodeRef::contains(void* address)
193{
194 RELEASE_ASSERT(m_ref);
195 return m_ref.executableMemory()->contains(address);
196}
197
198DirectJITCode::DirectJITCode(JITType jitType)
199 : JITCodeWithCodeRef(jitType)
200{
201}
202
203DirectJITCode::DirectJITCode(JITCode::CodeRef<JSEntryPtrTag> ref, JITCode::CodePtr<JSEntryPtrTag> withArityCheck, JITType jitType, JITCode::ShareAttribute shareAttribute)
204 : JITCodeWithCodeRef(ref, jitType, shareAttribute)
205 , m_withArityCheck(withArityCheck)
206{
207 ASSERT(m_ref);
208 ASSERT(m_withArityCheck);
209}
210
211DirectJITCode::DirectJITCode(JITCode::CodeRef<JSEntryPtrTag> ref, JITCode::CodePtr<JSEntryPtrTag> withArityCheck, JITType jitType, Intrinsic intrinsic, JITCode::ShareAttribute shareAttribute)
212 : JITCodeWithCodeRef(ref, jitType, shareAttribute)
213 , m_withArityCheck(withArityCheck)
214{
215 m_intrinsic = intrinsic;
216 ASSERT(m_ref);
217 ASSERT(m_withArityCheck);
218}
219
220DirectJITCode::~DirectJITCode()
221{
222}
223
224void DirectJITCode::initializeCodeRefForDFG(JITCode::CodeRef<JSEntryPtrTag> ref, JITCode::CodePtr<JSEntryPtrTag> withArityCheck)
225{
226 RELEASE_ASSERT(!m_ref);
227 m_ref = ref;
228 m_withArityCheck = withArityCheck;
229 ASSERT(m_ref);
230 ASSERT(m_withArityCheck);
231}
232
233JITCode::CodePtr<JSEntryPtrTag> DirectJITCode::addressForCall(ArityCheckMode arity)
234{
235 switch (arity) {
236 case ArityCheckNotRequired:
237 RELEASE_ASSERT(m_ref);
238 return m_ref.code();
239 case MustCheckArity:
240 RELEASE_ASSERT(m_withArityCheck);
241 return m_withArityCheck;
242 }
243 RELEASE_ASSERT_NOT_REACHED();
244 return CodePtr<JSEntryPtrTag>();
245}
246
247NativeJITCode::NativeJITCode(JITType jitType)
248 : JITCodeWithCodeRef(jitType)
249{
250}
251
252NativeJITCode::NativeJITCode(CodeRef<JSEntryPtrTag> ref, JITType jitType, Intrinsic intrinsic, JITCode::ShareAttribute shareAttribute)
253 : JITCodeWithCodeRef(ref, jitType, shareAttribute)
254{
255 m_intrinsic = intrinsic;
256}
257
258NativeJITCode::~NativeJITCode()
259{
260}
261
262JITCode::CodePtr<JSEntryPtrTag> NativeJITCode::addressForCall(ArityCheckMode arity)
263{
264 RELEASE_ASSERT(m_ref);
265 switch (arity) {
266 case ArityCheckNotRequired:
267 return m_ref.code();
268 case MustCheckArity:
269 return m_ref.code();
270 }
271 RELEASE_ASSERT_NOT_REACHED();
272 return CodePtr<JSEntryPtrTag>();
273}
274
275NativeDOMJITCode::NativeDOMJITCode(CodeRef<JSEntryPtrTag> ref, JITType type, Intrinsic intrinsic, const DOMJIT::Signature* signature)
276 : NativeJITCode(ref, type, intrinsic)
277 , m_signature(signature)
278{
279}
280
281#if ENABLE(JIT)
282RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex)
283{
284 return { };
285}
286#endif
287
288} // namespace JSC
289
290namespace WTF {
291
292void printInternal(PrintStream& out, JSC::JITType type)
293{
294 out.print(JSC::JITCode::typeName(type));
295}
296
297} // namespace WTF
298
Note: See TracBrowser for help on using the repository browser.