| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef ScriptWrappableVisitor_h | 5 // This file has been moved to platform/bindings/ScriptWrappableVisitor.h. |
| 6 #define ScriptWrappableVisitor_h | 6 // TODO(adithyas): Remove this file. |
| 7 | 7 #include "platform/bindings/ScriptWrappableVisitor.h" |
| 8 #include "core/CoreExport.h" | |
| 9 #include "platform/RuntimeEnabledFeatures.h" | |
| 10 #include "platform/heap/HeapPage.h" | |
| 11 #include "platform/heap/VisitorImpl.h" | |
| 12 #include "platform/heap/WrapperVisitor.h" | |
| 13 #include "platform/wtf/Deque.h" | |
| 14 #include "platform/wtf/Vector.h" | |
| 15 #include "v8/include/v8.h" | |
| 16 | |
| 17 namespace blink { | |
| 18 | |
| 19 class HeapObjectHeader; | |
| 20 template <typename T> | |
| 21 class Member; | |
| 22 class ScriptWrappable; | |
| 23 template <typename T> | |
| 24 class TraceWrapperV8Reference; | |
| 25 | |
| 26 class WrapperMarkingData { | |
| 27 public: | |
| 28 WrapperMarkingData( | |
| 29 void (*trace_wrappers_callback)(const WrapperVisitor*, const void*), | |
| 30 HeapObjectHeader* (*heap_object_header_callback)(const void*), | |
| 31 const void* object) | |
| 32 : trace_wrappers_callback_(trace_wrappers_callback), | |
| 33 heap_object_header_callback_(heap_object_header_callback), | |
| 34 raw_object_pointer_(object) { | |
| 35 DCHECK(trace_wrappers_callback_); | |
| 36 DCHECK(heap_object_header_callback_); | |
| 37 DCHECK(raw_object_pointer_); | |
| 38 } | |
| 39 | |
| 40 inline void TraceWrappers(WrapperVisitor* visitor) { | |
| 41 if (raw_object_pointer_) { | |
| 42 trace_wrappers_callback_(visitor, raw_object_pointer_); | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 // Returns true when object was marked. Ignores (returns true) invalidated | |
| 47 // objects. | |
| 48 inline bool IsWrapperHeaderMarked() { | |
| 49 return !raw_object_pointer_ || | |
| 50 GetHeapObjectHeader()->IsWrapperHeaderMarked(); | |
| 51 } | |
| 52 | |
| 53 inline const void* RawObjectPointer() { return raw_object_pointer_; } | |
| 54 | |
| 55 private: | |
| 56 inline bool ShouldBeInvalidated() { | |
| 57 return raw_object_pointer_ && !GetHeapObjectHeader()->IsMarked(); | |
| 58 } | |
| 59 | |
| 60 inline void Invalidate() { raw_object_pointer_ = nullptr; } | |
| 61 | |
| 62 inline const HeapObjectHeader* GetHeapObjectHeader() { | |
| 63 DCHECK(raw_object_pointer_); | |
| 64 return heap_object_header_callback_(raw_object_pointer_); | |
| 65 } | |
| 66 | |
| 67 void (*trace_wrappers_callback_)(const WrapperVisitor*, const void*); | |
| 68 HeapObjectHeader* (*heap_object_header_callback_)(const void*); | |
| 69 const void* raw_object_pointer_; | |
| 70 | |
| 71 friend class ScriptWrappableVisitor; | |
| 72 }; | |
| 73 | |
| 74 // ScriptWrappableVisitor is able to trace through the objects to get all | |
| 75 // wrappers. It is used during V8 garbage collection. When this visitor is | |
| 76 // set to the v8::Isolate as its embedder heap tracer, V8 will call it during | |
| 77 // its garbage collection. At the beginning, it will call TracePrologue, then | |
| 78 // repeatedly it will call AdvanceTracing, and at the end it will call | |
| 79 // TraceEpilogue. Everytime V8 finds new wrappers, it will let the tracer | |
| 80 // know using RegisterV8References. | |
| 81 class CORE_EXPORT ScriptWrappableVisitor : public v8::EmbedderHeapTracer, | |
| 82 public WrapperVisitor { | |
| 83 DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptWrappableVisitor); | |
| 84 | |
| 85 public: | |
| 86 ScriptWrappableVisitor(v8::Isolate* isolate) : isolate_(isolate){}; | |
| 87 ~ScriptWrappableVisitor() override; | |
| 88 | |
| 89 // Replace all dead objects in the marking deque with nullptr after oilpan | |
| 90 // gc. | |
| 91 static void InvalidateDeadObjectsInMarkingDeque(v8::Isolate*); | |
| 92 | |
| 93 // Immediately clean up all wrappers. | |
| 94 static void PerformCleanup(v8::Isolate*); | |
| 95 | |
| 96 void TracePrologue() override; | |
| 97 | |
| 98 static WrapperVisitor* CurrentVisitor(v8::Isolate*); | |
| 99 | |
| 100 static void WriteBarrier(v8::Isolate*, | |
| 101 const void*, | |
| 102 const TraceWrapperV8Reference<v8::Value>*); | |
| 103 | |
| 104 // TODO(mlippautz): Remove once ScriptWrappable is converted to | |
| 105 // TraceWrapperV8Reference. | |
| 106 static void WriteBarrier(v8::Isolate*, const v8::Persistent<v8::Object>*); | |
| 107 | |
| 108 template <typename T> | |
| 109 static void WriteBarrier(const void* object, const Member<T>& value) { | |
| 110 WriteBarrier(object, value.Get()); | |
| 111 } | |
| 112 | |
| 113 template <typename T> | |
| 114 static void WriteBarrier(const void* src_object, const T* dst_object) { | |
| 115 static_assert(!NeedsAdjustAndMark<T>::value, | |
| 116 "wrapper tracing is not supported within mixins"); | |
| 117 if (!src_object || !dst_object) { | |
| 118 return; | |
| 119 } | |
| 120 // We only require a write barrier if |srcObject| is already marked. Note | |
| 121 // that this implicitly disables the write barrier when the GC is not | |
| 122 // active as object will not be marked in this case. | |
| 123 if (!HeapObjectHeader::FromPayload(src_object)->IsWrapperHeaderMarked()) { | |
| 124 return; | |
| 125 } | |
| 126 | |
| 127 const ThreadState* thread_state = ThreadState::Current(); | |
| 128 DCHECK(thread_state); | |
| 129 // If the wrapper is already marked we can bail out here. | |
| 130 if (TraceTrait<T>::GetHeapObjectHeader(dst_object)->IsWrapperHeaderMarked()) | |
| 131 return; | |
| 132 // Otherwise, eagerly mark the wrapper header and put the object on the | |
| 133 // marking deque for further processing. | |
| 134 WrapperVisitor* const visitor = CurrentVisitor(thread_state->GetIsolate()); | |
| 135 visitor->MarkAndPushToMarkingDeque(dst_object); | |
| 136 } | |
| 137 | |
| 138 void RegisterV8References(const std::vector<std::pair<void*, void*>>& | |
| 139 internal_fields_of_potential_wrappers) override; | |
| 140 void RegisterV8Reference(const std::pair<void*, void*>& internal_fields); | |
| 141 bool AdvanceTracing(double deadline_in_ms, | |
| 142 v8::EmbedderHeapTracer::AdvanceTracingActions) override; | |
| 143 void TraceEpilogue() override; | |
| 144 void AbortTracing() override; | |
| 145 void EnterFinalPause() override; | |
| 146 size_t NumberOfWrappersToTrace() override; | |
| 147 | |
| 148 void DispatchTraceWrappers(const TraceWrapperBase*) const override; | |
| 149 | |
| 150 void TraceWrappers(const TraceWrapperV8Reference<v8::Value>&) const override; | |
| 151 void MarkWrapper(const v8::PersistentBase<v8::Value>*) const override; | |
| 152 | |
| 153 void InvalidateDeadObjectsInMarkingDeque(); | |
| 154 | |
| 155 bool MarkWrapperHeader(HeapObjectHeader*) const; | |
| 156 | |
| 157 // Mark wrappers in all worlds for the given script wrappable as alive in | |
| 158 // V8. | |
| 159 void MarkWrappersInAllWorlds(const ScriptWrappable*) const override; | |
| 160 | |
| 161 WTF::Deque<WrapperMarkingData>* GetMarkingDeque() { return &marking_deque_; } | |
| 162 WTF::Deque<WrapperMarkingData>* GetVerifierDeque() { | |
| 163 return &verifier_deque_; | |
| 164 } | |
| 165 WTF::Vector<HeapObjectHeader*>* GetHeadersToUnmark() { | |
| 166 return &headers_to_unmark_; | |
| 167 } | |
| 168 | |
| 169 // Immediately cleans up all wrappers if necessary. | |
| 170 void PerformCleanup(); | |
| 171 | |
| 172 protected: | |
| 173 bool PushToMarkingDeque( | |
| 174 void (*trace_wrappers_callback)(const WrapperVisitor*, const void*), | |
| 175 HeapObjectHeader* (*heap_object_header_callback)(const void*), | |
| 176 void (*missed_write_barrier_callback)(void), | |
| 177 const void* object) const override { | |
| 178 if (!tracing_in_progress_) | |
| 179 return false; | |
| 180 | |
| 181 marking_deque_.push_back(WrapperMarkingData( | |
| 182 trace_wrappers_callback, heap_object_header_callback, object)); | |
| 183 #if DCHECK_IS_ON() | |
| 184 if (!advancing_tracing_) { | |
| 185 verifier_deque_.push_back(WrapperMarkingData( | |
| 186 trace_wrappers_callback, heap_object_header_callback, object)); | |
| 187 } | |
| 188 #endif | |
| 189 return true; | |
| 190 } | |
| 191 | |
| 192 // Returns true if wrapper tracing is currently in progress, i.e., | |
| 193 // TracePrologue has been called, and TraceEpilogue has not yet been called. | |
| 194 bool tracing_in_progress_ = false; | |
| 195 | |
| 196 // Is AdvanceTracing currently running? If not, we know that all calls of | |
| 197 // pushToMarkingDeque are from V8 or new wrapper associations. And this | |
| 198 // information is used by the verifier feature. | |
| 199 bool advancing_tracing_ = false; | |
| 200 | |
| 201 // Indicates whether an idle task for a lazy cleanup has already been | |
| 202 // scheduled. The flag is used to avoid scheduling multiple idle tasks for | |
| 203 // cleaning up. | |
| 204 bool idle_cleanup_task_scheduled_ = false; | |
| 205 | |
| 206 // Indicates whether cleanup should currently happen. The flag is used to | |
| 207 // avoid cleaning up in the next GC cycle. | |
| 208 bool should_cleanup_ = false; | |
| 209 | |
| 210 // Schedule an idle task to perform a lazy (incremental) clean up of | |
| 211 // wrappers. | |
| 212 void ScheduleIdleLazyCleanup(); | |
| 213 void PerformLazyCleanup(double deadline_seconds); | |
| 214 | |
| 215 // Collection of objects we need to trace from. We assume it is safe to hold | |
| 216 // on to the raw pointers because: | |
| 217 // - oilpan object cannot move | |
| 218 // - oilpan gc will call invalidateDeadObjectsInMarkingDeque to delete all | |
| 219 // obsolete objects | |
| 220 mutable WTF::Deque<WrapperMarkingData> marking_deque_; | |
| 221 | |
| 222 // Collection of objects we started tracing from. We assume it is safe to | |
| 223 // hold on to the raw pointers because: | |
| 224 // - oilpan object cannot move | |
| 225 // - oilpan gc will call invalidateDeadObjectsInMarkingDeque to delete | |
| 226 // all obsolete objects | |
| 227 // | |
| 228 // These objects are used when TraceWrappablesVerifier feature is enabled to | |
| 229 // verify that all objects reachable in the atomic pause were marked | |
| 230 // incrementally. If not, there is one or multiple write barriers missing. | |
| 231 mutable WTF::Deque<WrapperMarkingData> verifier_deque_; | |
| 232 | |
| 233 // Collection of headers we need to unmark after the tracing finished. We | |
| 234 // assume it is safe to hold on to the headers because: | |
| 235 // - oilpan objects cannot move | |
| 236 // - objects this headers belong to are invalidated by the oilpan GC in | |
| 237 // invalidateDeadObjectsInMarkingDeque. | |
| 238 mutable WTF::Vector<HeapObjectHeader*> headers_to_unmark_; | |
| 239 v8::Isolate* isolate_; | |
| 240 }; | |
| 241 | |
| 242 } // namespace blink | |
| 243 | |
| 244 #endif // ScriptWrappableVisitor_h | |
| OLD | NEW |