source: webkit/trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp

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

[JSC] Do not use Bag<> for DFG / FTL watchpoints
https://bugs.webkit.org/show_bug.cgi?id=224715

Reviewed by Darin Adler.

While Bag<> is useful since its allocated memory will not be moved,
this is really memory-inefficient data structure. Each entry gets a
tail pointer (so adding 8 bytes) and we allocate each entry separately.

In DFG and FTL, we are using Bag<> for watchpoints. But this is not necessary actually: thanks to
concurrent compilers, our watchpoint registration is batched at the end of compilation. This means
that we have a way to know how many watchpoints we should register at that point.

In this patch, we introduce WatchpointCollector. In DesiredGlobalProperties, we run reallyAdd twice
with WatchpointCollector. First time, we just count # of watchpoints. Then we allocate FixedVector<XXXWatchpoint>
and install them. Since we do not (cannot) grow this fixed vector, watchpoint's address will not be changed as required.

We also move DesiredGlobalProperties under DesiredWatchpoints since this basically registers watchpoints.

  • bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp:

(JSC::AdaptiveInferredPropertyValueWatchpointBase::AdaptiveInferredPropertyValueWatchpointBase):
(JSC::AdaptiveInferredPropertyValueWatchpointBase::initialize):

  • bytecode/AdaptiveInferredPropertyValueWatchpointBase.h:
  • bytecode/CodeBlockJettisoningWatchpoint.h:
  • dfg/DFGAdaptiveInferredPropertyValueWatchpoint.cpp:

(JSC::DFG::AdaptiveInferredPropertyValueWatchpoint::AdaptiveInferredPropertyValueWatchpoint):
(JSC::DFG::AdaptiveInferredPropertyValueWatchpoint::initialize):

  • dfg/DFGAdaptiveInferredPropertyValueWatchpoint.h:
  • dfg/DFGAdaptiveStructureWatchpoint.cpp:

(JSC::DFG::AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint):
(JSC::DFG::AdaptiveStructureWatchpoint::initialize):

  • dfg/DFGAdaptiveStructureWatchpoint.h:
  • dfg/DFGCommonData.cpp:

(JSC::DFG::CommonData::validateReferences):
(JSC::DFG::CommonData::clearWatchpoints):

  • dfg/DFGCommonData.h:
  • dfg/DFGDesiredGlobalProperties.cpp:

(JSC::DFG::DesiredGlobalProperties::reallyAdd):

  • dfg/DFGDesiredGlobalProperties.h:
  • dfg/DFGDesiredWatchpoints.cpp:

(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
(JSC::DFG::SymbolTableAdaptor::add):
(JSC::DFG::FunctionExecutableAdaptor::add):
(JSC::DFG::AdaptiveStructureWatchpointAdaptor::add):
(JSC::DFG::DesiredWatchpoints::addLazily):
(JSC::DFG::DesiredWatchpoints::reallyAdd):
(JSC::DFG::DesiredWatchpoints::areStillValidOnMainThread):
(JSC::DFG::WatchpointCollector::finalize):

  • dfg/DFGDesiredWatchpoints.h:

(JSC::DFG::SetPointerAdaptor::add):
(JSC::DFG::GenericDesiredWatchpoints::reallyAdd):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::watchGlobalProperty):

  • dfg/DFGGraph.h:
  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::reallyAdd):
(JSC::DFG::Plan::isStillValidOnMainThread):
(JSC::DFG::Plan::cancel):

  • dfg/DFGPlan.h:

(JSC::DFG::Plan::transitions):
(JSC::DFG::Plan::globalProperties): Deleted.

File size: 7.8 KB
Line 
1/*
2 * Copyright (C) 2013-2019 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 "DFGDesiredWatchpoints.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "CodeBlock.h"
32#include "DFGGraph.h"
33#include "JSCInlines.h"
34
35namespace JSC { namespace DFG {
36
37void ArrayBufferViewWatchpointAdaptor::add(CodeBlock* codeBlock, JSArrayBufferView* view, WatchpointCollector& collector)
38{
39 collector.addWatchpoint([&](CodeBlockJettisoningWatchpoint& watchpoint) {
40 // view is already frozen. If it is deallocated, jettisoning happens.
41 {
42 ConcurrentJSLocker locker(codeBlock->m_lock);
43 watchpoint.initialize(codeBlock);
44 }
45 ArrayBuffer* arrayBuffer = view->possiblySharedBuffer();
46 if (!arrayBuffer) {
47 watchpoint.fire(codeBlock->vm(), StringFireDetail("ArrayBuffer could not be allocated, probably because of OOM."));
48 return;
49 }
50
51 // FIXME: We don't need to set this watchpoint at all for shared buffers.
52 // https://bugs.webkit.org/show_bug.cgi?id=164108
53 arrayBuffer->detachingWatchpointSet().add(&watchpoint);
54 });
55}
56
57void SymbolTableAdaptor::add(CodeBlock* codeBlock, SymbolTable* symbolTable, WatchpointCollector& collector)
58{
59 collector.addWatchpoint([&](CodeBlockJettisoningWatchpoint& watchpoint) {
60 {
61 ConcurrentJSLocker locker(codeBlock->m_lock);
62 watchpoint.initialize(codeBlock);
63 }
64 codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), symbolTable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
65 symbolTable->singleton().add(&watchpoint);
66 });
67}
68
69void FunctionExecutableAdaptor::add(CodeBlock* codeBlock, FunctionExecutable* executable, WatchpointCollector& collector)
70{
71 collector.addWatchpoint([&](CodeBlockJettisoningWatchpoint& watchpoint) {
72 {
73 ConcurrentJSLocker locker(codeBlock->m_lock);
74 watchpoint.initialize(codeBlock);
75 }
76 codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), executable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
77 executable->singleton().add(&watchpoint);
78 });
79}
80
81void AdaptiveStructureWatchpointAdaptor::add(CodeBlock* codeBlock, const ObjectPropertyCondition& key, WatchpointCollector& collector)
82{
83 VM& vm = codeBlock->vm();
84 switch (key.kind()) {
85 case PropertyCondition::Equivalence: {
86 collector.addAdaptiveInferredPropertyValueWatchpoint([&](AdaptiveInferredPropertyValueWatchpoint& watchpoint) {
87 {
88 ConcurrentJSLocker locker(codeBlock->m_lock);
89 watchpoint.initialize(key, codeBlock);
90 }
91 watchpoint.install(vm);
92 });
93 break;
94 }
95 default: {
96 collector.addAdaptiveStructureWatchpoint([&](AdaptiveStructureWatchpoint& watchpoint) {
97 {
98 ConcurrentJSLocker locker(codeBlock->m_lock);
99 watchpoint.initialize(key, codeBlock);
100 }
101 watchpoint.install(vm);
102 });
103 break;
104 }
105 }
106}
107
108DesiredWatchpoints::DesiredWatchpoints() { }
109DesiredWatchpoints::~DesiredWatchpoints() { }
110
111void DesiredWatchpoints::addLazily(WatchpointSet* set)
112{
113 m_sets.addLazily(set);
114}
115
116void DesiredWatchpoints::addLazily(InlineWatchpointSet& set)
117{
118 m_inlineSets.addLazily(&set);
119}
120
121void DesiredWatchpoints::addLazily(SymbolTable* symbolTable)
122{
123 m_symbolTables.addLazily(symbolTable);
124}
125
126void DesiredWatchpoints::addLazily(FunctionExecutable* executable)
127{
128 m_functionExecutables.addLazily(executable);
129}
130
131void DesiredWatchpoints::addLazily(JSArrayBufferView* view)
132{
133 m_bufferViews.addLazily(view);
134}
135
136void DesiredWatchpoints::addLazily(const ObjectPropertyCondition& key)
137{
138 m_adaptiveStructureSets.addLazily(key);
139}
140
141void DesiredWatchpoints::addLazily(DesiredGlobalProperty&& property)
142{
143 m_globalProperties.addLazily(WTFMove(property));
144}
145
146bool DesiredWatchpoints::consider(Structure* structure)
147{
148 if (!structure->dfgShouldWatch())
149 return false;
150 addLazily(structure->transitionWatchpointSet());
151 return true;
152}
153
154void DesiredWatchpoints::reallyAdd(CodeBlock* codeBlock, DesiredIdentifiers& identifiers, CommonData* commonData)
155{
156 WatchpointCollector collector;
157
158 auto reallyAdd = [&]() {
159 m_sets.reallyAdd(codeBlock, collector);
160 m_inlineSets.reallyAdd(codeBlock, collector);
161 m_symbolTables.reallyAdd(codeBlock, collector);
162 m_functionExecutables.reallyAdd(codeBlock, collector);
163 m_bufferViews.reallyAdd(codeBlock, collector);
164 m_adaptiveStructureSets.reallyAdd(codeBlock, collector);
165 m_globalProperties.reallyAdd(codeBlock, identifiers, collector);
166 };
167 reallyAdd();
168 collector.materialize();
169
170 reallyAdd();
171 collector.finalize(codeBlock, *commonData);
172}
173
174bool DesiredWatchpoints::areStillValid() const
175{
176 return m_sets.areStillValid()
177 && m_inlineSets.areStillValid()
178 && m_symbolTables.areStillValid()
179 && m_functionExecutables.areStillValid()
180 && m_bufferViews.areStillValid()
181 && m_adaptiveStructureSets.areStillValid();
182}
183
184bool DesiredWatchpoints::areStillValidOnMainThread(VM& vm, DesiredIdentifiers& identifiers)
185{
186 return m_globalProperties.isStillValidOnMainThread(vm, identifiers);
187}
188
189void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
190{
191 Prefix noPrefix(Prefix::NoHeader);
192 Prefix& prefix = context && context->graph ? context->graph->prefix() : noPrefix;
193 out.print(prefix, "Desired watchpoints:\n");
194 out.print(prefix, " Watchpoint sets: ", inContext(m_sets, context), "\n");
195 out.print(prefix, " Inline watchpoint sets: ", inContext(m_inlineSets, context), "\n");
196 out.print(prefix, " SymbolTables: ", inContext(m_symbolTables, context), "\n");
197 out.print(prefix, " FunctionExecutables: ", inContext(m_functionExecutables, context), "\n");
198 out.print(prefix, " Buffer views: ", inContext(m_bufferViews, context), "\n");
199 out.print(prefix, " Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
200}
201
202void WatchpointCollector::finalize(CodeBlock* codeBlock, CommonData& common)
203{
204 ConcurrentJSLocker locker(codeBlock->m_lock);
205 common.m_watchpoints = WTFMove(m_watchpoints);
206 common.m_adaptiveStructureWatchpoints = WTFMove(m_adaptiveStructureWatchpoints);
207 common.m_adaptiveInferredPropertyValueWatchpoints = WTFMove(m_adaptiveInferredPropertyValueWatchpoints);
208}
209
210} } // namespace JSC::DFG
211
212#endif // ENABLE(DFG_JIT)
213
Note: See TracBrowser for help on using the repository browser.