Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp

Issue 2843603002: Move ScriptWrappable and dependencies to platform/bindings (Closed)
Patch Set: Rebase and try again Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "bindings/core/v8/ScriptWrappableVisitor.h"
6
7 #include "bindings/core/v8/ActiveScriptWrappable.h"
8 #include "bindings/core/v8/DOMWrapperWorld.h"
9 #include "bindings/core/v8/ScopedPersistent.h"
10 #include "bindings/core/v8/ScriptWrappable.h"
11 #include "bindings/core/v8/ScriptWrappableVisitorVerifier.h"
12 #include "bindings/core/v8/V8AbstractEventListener.h"
13 #include "bindings/core/v8/WrapperTypeInfo.h"
14 #include "core/dom/DocumentStyleSheetCollection.h"
15 #include "core/dom/ElementRareData.h"
16 #include "core/dom/NodeListsNodeData.h"
17 #include "core/dom/NodeRareData.h"
18 #include "core/dom/StyleEngine.h"
19 #include "core/dom/shadow/ElementShadow.h"
20 #include "core/html/imports/HTMLImportsController.h"
21 #include "platform/heap/HeapCompact.h"
22 #include "platform/heap/HeapPage.h"
23 #include "platform/scheduler/child/web_scheduler.h"
24 #include "platform/wtf/AutoReset.h"
25 #include "public/platform/Platform.h"
26
27 namespace blink {
28
29 ScriptWrappableVisitor::~ScriptWrappableVisitor() {}
30
31 void ScriptWrappableVisitor::TracePrologue() {
32 // This CHECK ensures that wrapper tracing is not started from scopes
33 // that forbid GC execution, e.g., constructors.
34 CHECK(ThreadState::Current());
35 CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
36 PerformCleanup();
37
38 CHECK(!tracing_in_progress_);
39 CHECK(!should_cleanup_);
40 CHECK(headers_to_unmark_.IsEmpty());
41 CHECK(marking_deque_.IsEmpty());
42 CHECK(verifier_deque_.IsEmpty());
43 tracing_in_progress_ = true;
44 }
45
46 void ScriptWrappableVisitor::EnterFinalPause() {
47 CHECK(ThreadState::Current());
48 CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
49 ActiveScriptWrappableBase::TraceActiveScriptWrappables(isolate_, this);
50 }
51
52 void ScriptWrappableVisitor::TraceEpilogue() {
53 CHECK(ThreadState::Current());
54 CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
55 DCHECK(marking_deque_.IsEmpty());
56 #if DCHECK_IS_ON()
57 ScriptWrappableVisitorVerifier verifier;
58 for (auto& marking_data : verifier_deque_) {
59 marking_data.TraceWrappers(&verifier);
60 }
61 #endif
62
63 should_cleanup_ = true;
64 tracing_in_progress_ = false;
65 ScheduleIdleLazyCleanup();
66 }
67
68 void ScriptWrappableVisitor::AbortTracing() {
69 CHECK(ThreadState::Current());
70 should_cleanup_ = true;
71 tracing_in_progress_ = false;
72 PerformCleanup();
73 }
74
75 size_t ScriptWrappableVisitor::NumberOfWrappersToTrace() {
76 CHECK(ThreadState::Current());
77 return marking_deque_.size();
78 }
79
80 void ScriptWrappableVisitor::PerformCleanup() {
81 if (!should_cleanup_)
82 return;
83
84 CHECK(!tracing_in_progress_);
85 for (auto header : headers_to_unmark_) {
86 // Dead objects residing in the marking deque may become invalid due to
87 // minor garbage collections and are therefore set to nullptr. We have
88 // to skip over such objects.
89 if (header)
90 header->UnmarkWrapperHeader();
91 }
92
93 headers_to_unmark_.clear();
94 marking_deque_.clear();
95 verifier_deque_.clear();
96 should_cleanup_ = false;
97 }
98
99 void ScriptWrappableVisitor::ScheduleIdleLazyCleanup() {
100 // Some threads (e.g. PPAPI thread) don't have a scheduler.
101 if (!Platform::Current()->CurrentThread()->Scheduler())
102 return;
103
104 if (idle_cleanup_task_scheduled_)
105 return;
106
107 Platform::Current()->CurrentThread()->Scheduler()->PostIdleTask(
108 BLINK_FROM_HERE, WTF::Bind(&ScriptWrappableVisitor::PerformLazyCleanup,
109 WTF::Unretained(this)));
110 idle_cleanup_task_scheduled_ = true;
111 }
112
113 void ScriptWrappableVisitor::PerformLazyCleanup(double deadline_seconds) {
114 idle_cleanup_task_scheduled_ = false;
115
116 if (!should_cleanup_)
117 return;
118
119 TRACE_EVENT1("blink_gc,devtools.timeline",
120 "ScriptWrappableVisitor::performLazyCleanup",
121 "idleDeltaInSeconds",
122 deadline_seconds - MonotonicallyIncreasingTime());
123
124 const int kDeadlineCheckInterval = 2500;
125 int processed_wrapper_count = 0;
126 for (auto it = headers_to_unmark_.rbegin();
127 it != headers_to_unmark_.rend();) {
128 auto header = *it;
129 // Dead objects residing in the marking deque may become invalid due to
130 // minor garbage collections and are therefore set to nullptr. We have
131 // to skip over such objects.
132 if (header)
133 header->UnmarkWrapperHeader();
134
135 ++it;
136 headers_to_unmark_.pop_back();
137
138 processed_wrapper_count++;
139 if (processed_wrapper_count % kDeadlineCheckInterval == 0) {
140 if (deadline_seconds <= MonotonicallyIncreasingTime()) {
141 ScheduleIdleLazyCleanup();
142 return;
143 }
144 }
145 }
146
147 // Unmarked all headers.
148 CHECK(headers_to_unmark_.IsEmpty());
149 marking_deque_.clear();
150 verifier_deque_.clear();
151 should_cleanup_ = false;
152 }
153
154 void ScriptWrappableVisitor::RegisterV8Reference(
155 const std::pair<void*, void*>& internal_fields) {
156 if (!tracing_in_progress_) {
157 return;
158 }
159
160 WrapperTypeInfo* wrapper_type_info =
161 reinterpret_cast<WrapperTypeInfo*>(internal_fields.first);
162 if (wrapper_type_info->gin_embedder != gin::GinEmbedder::kEmbedderBlink) {
163 return;
164 }
165 DCHECK(wrapper_type_info->wrapper_class_id == WrapperTypeInfo::kNodeClassId ||
166 wrapper_type_info->wrapper_class_id ==
167 WrapperTypeInfo::kObjectClassId);
168
169 ScriptWrappable* script_wrappable =
170 reinterpret_cast<ScriptWrappable*>(internal_fields.second);
171
172 wrapper_type_info->TraceWrappers(this, script_wrappable);
173 }
174
175 void ScriptWrappableVisitor::RegisterV8References(
176 const std::vector<std::pair<void*, void*>>&
177 internal_fields_of_potential_wrappers) {
178 CHECK(ThreadState::Current());
179 // TODO(hlopko): Visit the vector in the V8 instead of passing it over if
180 // there is no performance impact
181 for (auto& pair : internal_fields_of_potential_wrappers) {
182 RegisterV8Reference(pair);
183 }
184 }
185
186 bool ScriptWrappableVisitor::AdvanceTracing(
187 double deadline_in_ms,
188 v8::EmbedderHeapTracer::AdvanceTracingActions actions) {
189 // Do not drain the marking deque in a state where we can generally not
190 // perform a GC. This makes sure that TraceTraits and friends find
191 // themselves in a well-defined environment, e.g., properly set up vtables.
192 CHECK(ThreadState::Current());
193 CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
194 CHECK(tracing_in_progress_);
195 WTF::AutoReset<bool>(&advancing_tracing_, true);
196 while (actions.force_completion ==
197 v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION ||
198 WTF::MonotonicallyIncreasingTimeMS() < deadline_in_ms) {
199 if (marking_deque_.IsEmpty()) {
200 return false;
201 }
202 marking_deque_.TakeFirst().TraceWrappers(this);
203 }
204 return true;
205 }
206
207 bool ScriptWrappableVisitor::MarkWrapperHeader(HeapObjectHeader* header) const {
208 if (header->IsWrapperHeaderMarked())
209 return false;
210
211 // Verify that no compactable & movable objects are slated for
212 // lazy unmarking.
213 DCHECK(!HeapCompact::IsCompactableArena(
214 PageFromObject(header)->Arena()->ArenaIndex()));
215 header->MarkWrapperHeader();
216 headers_to_unmark_.push_back(header);
217 return true;
218 }
219
220 void ScriptWrappableVisitor::MarkWrappersInAllWorlds(
221 const ScriptWrappable* script_wrappable) const {
222 DOMWrapperWorld::MarkWrappersInAllWorlds(
223 const_cast<ScriptWrappable*>(script_wrappable), this);
224 }
225
226 void ScriptWrappableVisitor::WriteBarrier(
227 v8::Isolate* isolate,
228 const void* src_object,
229 const TraceWrapperV8Reference<v8::Value>* dst_object) {
230 if (!src_object || !dst_object || dst_object->IsEmpty()) {
231 return;
232 }
233 // We only require a write barrier if |srcObject| is already marked. Note
234 // that this implicitly disables the write barrier when the GC is not
235 // active as object will not be marked in this case.
236 if (!HeapObjectHeader::FromPayload(src_object)->IsWrapperHeaderMarked()) {
237 return;
238 }
239 CurrentVisitor(isolate)->MarkWrapper(
240 &(const_cast<TraceWrapperV8Reference<v8::Value>*>(dst_object)->Get()));
241 }
242
243 void ScriptWrappableVisitor::WriteBarrier(
244 v8::Isolate* isolate,
245 const v8::Persistent<v8::Object>* dst_object) {
246 if (!dst_object || dst_object->IsEmpty()) {
247 return;
248 }
249 CurrentVisitor(isolate)->MarkWrapper(&(dst_object->As<v8::Value>()));
250 }
251
252 void ScriptWrappableVisitor::TraceWrappers(
253 const TraceWrapperV8Reference<v8::Value>& traced_wrapper) const {
254 MarkWrapper(
255 &(const_cast<TraceWrapperV8Reference<v8::Value>&>(traced_wrapper).Get()));
256 }
257
258 void ScriptWrappableVisitor::MarkWrapper(
259 const v8::PersistentBase<v8::Value>* handle) const {
260 // The write barrier may try to mark a wrapper because cleanup is still
261 // delayed. Bail out in this case. We also allow unconditional marking which
262 // requires us to bail out here when tracing is not in progress.
263 if (!tracing_in_progress_ || handle->IsEmpty())
264 return;
265 handle->RegisterExternalReference(isolate_);
266 }
267
268 void ScriptWrappableVisitor::DispatchTraceWrappers(
269 const TraceWrapperBase* wrapper_base) const {
270 wrapper_base->TraceWrappers(this);
271 }
272
273 void ScriptWrappableVisitor::InvalidateDeadObjectsInMarkingDeque() {
274 for (auto it = marking_deque_.begin(); it != marking_deque_.end(); ++it) {
275 auto& marking_data = *it;
276 if (marking_data.ShouldBeInvalidated()) {
277 marking_data.Invalidate();
278 }
279 }
280 for (auto it = verifier_deque_.begin(); it != verifier_deque_.end(); ++it) {
281 auto& marking_data = *it;
282 if (marking_data.ShouldBeInvalidated()) {
283 marking_data.Invalidate();
284 }
285 }
286 for (auto it = headers_to_unmark_.begin(); it != headers_to_unmark_.end();
287 ++it) {
288 auto header = *it;
289 if (header && !header->IsMarked()) {
290 *it = nullptr;
291 }
292 }
293 }
294
295 void ScriptWrappableVisitor::InvalidateDeadObjectsInMarkingDeque(
296 v8::Isolate* isolate) {
297 ScriptWrappableVisitor* script_wrappable_visitor =
298 V8PerIsolateData::From(isolate)->GetScriptWrappableVisitor();
299 if (script_wrappable_visitor)
300 script_wrappable_visitor->InvalidateDeadObjectsInMarkingDeque();
301 }
302
303 void ScriptWrappableVisitor::PerformCleanup(v8::Isolate* isolate) {
304 ScriptWrappableVisitor* script_wrappable_visitor =
305 V8PerIsolateData::From(isolate)->GetScriptWrappableVisitor();
306 if (script_wrappable_visitor)
307 script_wrappable_visitor->PerformCleanup();
308 }
309
310 WrapperVisitor* ScriptWrappableVisitor::CurrentVisitor(v8::Isolate* isolate) {
311 return V8PerIsolateData::From(isolate)->GetScriptWrappableVisitor();
312 }
313
314 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698