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