1 // Copyright 2018 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 "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
6 
7 #include "third_party/blink/public/common/features.h"
8 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
9 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
10 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
11 #include "third_party/blink/renderer/platform/heap/blink_gc.h"
12 #include "third_party/blink/renderer/platform/heap/thread_state.h"
13 #include "third_party/blink/renderer/platform/heap/unified_heap_controller.h"
14 
15 namespace blink {
16 
UnifiedHeapMarkingVisitorBase(ThreadState * thread_state,v8::Isolate * isolate,int task_id)17 UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase(
18     ThreadState* thread_state,
19     v8::Isolate* isolate,
20     int task_id)
21     : isolate_(isolate),
22       controller_(thread_state->unified_heap_controller()),
23       v8_references_worklist_(thread_state->Heap().GetV8ReferencesWorklist(),
24                               task_id),
25       task_id_(task_id) {
26   DCHECK(controller_);
27 }
28 
VisitImpl(const TraceWrapperV8Reference<v8::Value> & v8_reference)29 void UnifiedHeapMarkingVisitorBase::VisitImpl(
30     const TraceWrapperV8Reference<v8::Value>& v8_reference) {
31   DCHECK(isolate_);
32   if (v8_reference.IsEmptySafe())
33     return;
34   if (task_id_ != WorklistTaskId::MutatorThread) {
35     // This is a temporary solution. Pushing directly from concurrent threads
36     // to V8 marking worklist will currently result in data races. This
37     // solution guarantees correctness until we implement a long-term solution
38     // (i.e. allowing Oilpan concurrent threads concurrent-safe access to V8
39     // marking worklist without data-races)
40     v8_references_worklist_.Push(&v8_reference);
41     return;
42   }
43   controller_->RegisterEmbedderReference(
44       v8_reference.template Cast<v8::Data>().Get());
45 }
46 
UnifiedHeapMarkingVisitor(ThreadState * thread_state,MarkingMode mode,v8::Isolate * isolate)47 UnifiedHeapMarkingVisitor::UnifiedHeapMarkingVisitor(ThreadState* thread_state,
48                                                      MarkingMode mode,
49                                                      v8::Isolate* isolate)
50     : MarkingVisitor(thread_state, mode),
51       UnifiedHeapMarkingVisitorBase(thread_state,
52                                     isolate,
53                                     WorklistTaskId::MutatorThread) {}
54 
55 // static
WriteBarrier(const TraceWrapperV8Reference<v8::Value> & object)56 void UnifiedHeapMarkingVisitor::WriteBarrier(
57     const TraceWrapperV8Reference<v8::Value>& object) {
58   if (object.IsEmpty() || !ThreadState::IsAnyIncrementalMarking())
59     return;
60 
61   ThreadState* thread_state = ThreadState::Current();
62   if (!thread_state->IsIncrementalMarking())
63     return;
64 
65   thread_state->CurrentVisitor()->Trace(object);
66 }
67 
68 // static
WriteBarrier(v8::Isolate * isolate,const WrapperTypeInfo * wrapper_type_info,const void * object)69 void UnifiedHeapMarkingVisitor::WriteBarrier(
70     v8::Isolate* isolate,
71     const WrapperTypeInfo* wrapper_type_info,
72     const void* object) {
73   // |object| here is either ScriptWrappable or CustomWrappable.
74 
75   if (!ThreadState::IsAnyIncrementalMarking())
76     return;
77 
78   ThreadState* thread_state = ThreadState::Current();
79   if (!thread_state->IsIncrementalMarking())
80     return;
81 
82   wrapper_type_info->Trace(thread_state->CurrentVisitor(), object);
83 }
84 
Visit(const TraceWrapperV8Reference<v8::Value> & v)85 void UnifiedHeapMarkingVisitor::Visit(
86     const TraceWrapperV8Reference<v8::Value>& v) {
87   VisitImpl(v);
88 }
89 
ConcurrentUnifiedHeapMarkingVisitor(ThreadState * thread_state,MarkingMode mode,v8::Isolate * isolate,int task_id)90 ConcurrentUnifiedHeapMarkingVisitor::ConcurrentUnifiedHeapMarkingVisitor(
91     ThreadState* thread_state,
92     MarkingMode mode,
93     v8::Isolate* isolate,
94     int task_id)
95     : ConcurrentMarkingVisitor(thread_state, mode, task_id),
96       UnifiedHeapMarkingVisitorBase(thread_state, isolate, task_id) {}
97 
FlushWorklists()98 void ConcurrentUnifiedHeapMarkingVisitor::FlushWorklists() {
99   ConcurrentMarkingVisitor::FlushWorklists();
100   v8_references_worklist_.FlushToGlobal();
101 }
102 
Visit(const TraceWrapperV8Reference<v8::Value> & v)103 void ConcurrentUnifiedHeapMarkingVisitor::Visit(
104     const TraceWrapperV8Reference<v8::Value>& v) {
105   VisitImpl(v);
106 }
107 
108 }  // namespace blink
109