Line data Source code
1 : // Copyright 2016 the V8 project 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 : #ifndef V8_HEAP_ARRAY_BUFFER_TRACKER_INL_H_
6 : #define V8_HEAP_ARRAY_BUFFER_TRACKER_INL_H_
7 :
8 : #include "src/conversions-inl.h"
9 : #include "src/heap/array-buffer-tracker.h"
10 : #include "src/heap/heap-inl.h"
11 : #include "src/heap/spaces-inl.h"
12 : #include "src/objects.h"
13 : #include "src/objects/js-array-buffer-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 519126 : void ArrayBufferTracker::RegisterNew(Heap* heap, JSArrayBuffer buffer) {
19 519126 : if (buffer->backing_store() == nullptr) return;
20 :
21 : // ArrayBuffer tracking works only for small objects.
22 : DCHECK(!heap->IsLargeObject(buffer));
23 :
24 : const size_t length = buffer->byte_length();
25 : Page* page = Page::FromHeapObject(buffer);
26 : {
27 : base::MutexGuard guard(page->mutex());
28 : LocalArrayBufferTracker* tracker = page->local_tracker();
29 519151 : if (tracker == nullptr) {
30 9713 : page->AllocateLocalTracker();
31 : tracker = page->local_tracker();
32 : }
33 : DCHECK_NOT_NULL(tracker);
34 519151 : tracker->Add(buffer, length);
35 : }
36 :
37 : // TODO(wez): Remove backing-store from external memory accounting.
38 : // We may go over the limit of externally allocated memory here. We call the
39 : // api function to trigger a GC in this case.
40 : reinterpret_cast<v8::Isolate*>(heap->isolate())
41 519154 : ->AdjustAmountOfExternalAllocatedMemory(length);
42 : }
43 :
44 5327 : void ArrayBufferTracker::Unregister(Heap* heap, JSArrayBuffer buffer) {
45 5327 : if (buffer->backing_store() == nullptr) return;
46 :
47 : Page* page = Page::FromHeapObject(buffer);
48 : const size_t length = buffer->byte_length();
49 : {
50 : base::MutexGuard guard(page->mutex());
51 : LocalArrayBufferTracker* tracker = page->local_tracker();
52 : DCHECK_NOT_NULL(tracker);
53 5303 : tracker->Remove(buffer, length);
54 : }
55 :
56 : // TODO(wez): Remove backing-store from external memory accounting.
57 5303 : heap->update_external_memory(-static_cast<intptr_t>(length));
58 : }
59 :
60 : Space* LocalArrayBufferTracker::space() { return page_->owner(); }
61 :
62 : template <typename Callback>
63 296086 : void LocalArrayBufferTracker::Free(Callback should_free) {
64 : size_t freed_memory = 0;
65 296086 : Isolate* isolate = page_->heap()->isolate();
66 594518 : for (TrackingData::iterator it = array_buffers_.begin();
67 : it != array_buffers_.end();) {
68 : // Unchecked cast because the map might already be dead at this point.
69 : JSArrayBuffer buffer = JSArrayBuffer::unchecked_cast(it->first);
70 298428 : const size_t length = it->second.length;
71 :
72 : if (should_free(buffer)) {
73 256350 : JSArrayBuffer::FreeBackingStore(isolate, it->second);
74 : it = array_buffers_.erase(it);
75 256354 : freed_memory += length;
76 : } else {
77 : ++it;
78 : }
79 : }
80 296090 : if (freed_memory > 0) {
81 9226 : page_->DecrementExternalBackingStoreBytes(
82 : ExternalBackingStoreType::kArrayBuffer, freed_memory);
83 :
84 : // TODO(wez): Remove backing-store from external memory accounting.
85 9226 : page_->heap()->update_external_memory_concurrently_freed(
86 : static_cast<intptr_t>(freed_memory));
87 : }
88 296090 : }
89 :
90 : template <typename MarkingState>
91 477884 : void ArrayBufferTracker::FreeDead(Page* page, MarkingState* marking_state) {
92 : // Callers need to ensure having the page lock.
93 : LocalArrayBufferTracker* tracker = page->local_tracker();
94 477884 : if (tracker == nullptr) return;
95 19328 : tracker->Free([marking_state](JSArrayBuffer buffer) {
96 : return marking_state->IsWhite(buffer);
97 : });
98 19331 : if (tracker->IsEmpty()) {
99 7277 : page->ReleaseLocalTracker();
100 : }
101 : }
102 :
103 519149 : void LocalArrayBufferTracker::Add(JSArrayBuffer buffer, size_t length) {
104 519149 : page_->IncrementExternalBackingStoreBytes(
105 519149 : ExternalBackingStoreType::kArrayBuffer, length);
106 :
107 519145 : AddInternal(buffer, length);
108 519145 : }
109 :
110 550349 : void LocalArrayBufferTracker::AddInternal(JSArrayBuffer buffer, size_t length) {
111 : auto ret = array_buffers_.insert(
112 : {buffer,
113 : {buffer->backing_store(), length, buffer->backing_store(),
114 550346 : buffer->is_wasm_memory()}});
115 : USE(ret);
116 : // Check that we indeed inserted a new value and did not overwrite an existing
117 : // one (which would be a bug).
118 : DCHECK(ret.second);
119 550346 : }
120 :
121 5303 : void LocalArrayBufferTracker::Remove(JSArrayBuffer buffer, size_t length) {
122 5303 : page_->DecrementExternalBackingStoreBytes(
123 5303 : ExternalBackingStoreType::kArrayBuffer, length);
124 :
125 : TrackingData::iterator it = array_buffers_.find(buffer);
126 : // Check that we indeed find a key to remove.
127 : DCHECK(it != array_buffers_.end());
128 : DCHECK_EQ(length, it->second.length);
129 : array_buffers_.erase(it);
130 5303 : }
131 :
132 : } // namespace internal
133 : } // namespace v8
134 :
135 : #endif // V8_HEAP_ARRAY_BUFFER_TRACKER_INL_H_
|