Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
weak_table.cc
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
7#include "platform/assert.h"
8#include "vm/isolate.h"
9#include "vm/raw_object.h"
10
11namespace dart {
12
13intptr_t WeakTable::SizeFor(intptr_t count, intptr_t size) {
14 intptr_t result = size;
15 if (count <= (size / 4)) {
16 // Reduce the capacity.
17 result = size / 2;
18 } else {
19 // Increase the capacity.
20 result = size * 2;
21 if (result < size) {
22 FATAL(
23 "Reached impossible state of having more weak table entries"
24 " than memory available for heap objects.");
25 }
26 }
27 if (result < kMinSize) {
28 result = kMinSize;
29 }
30 return result;
31}
32
34 const intptr_t mask = size() - 1;
35 intptr_t idx = Hash(key) & mask;
36 intptr_t empty_idx = -1;
38
39 while (obj != static_cast<ObjectPtr>(kNoEntry)) {
40 if (obj == key) {
41 SetValueAt(idx, val);
42 return;
43 } else if ((empty_idx < 0) &&
44 (static_cast<intptr_t>(obj) == kDeletedEntry)) {
45 empty_idx = idx; // Insert at this location if not found.
46 }
47 idx = (idx + 1) & mask;
48 obj = ObjectAtExclusive(idx);
49 }
50
51 if (val == 0) {
52 // Do not enter an invalid value. Associating 0 with a key deletes it from
53 // this weak table above in SetValueAt. If the key was not present in the
54 // weak table we are done.
55 return;
56 }
57
58 if (empty_idx >= 0) {
59 // We will be reusing a slot below.
60 set_used(used() - 1);
61 idx = empty_idx;
62 }
63
65 // Set the key and value.
66 SetObjectAt(idx, key);
67 SetValueAt(idx, val);
68 // Update the counts.
69 set_used(used() + 1);
70 set_count(count() + 1);
71
72 // Rehash if needed to ensure that there are empty slots available.
73 if (used_ >= limit()) {
74 Rehash();
75 }
76}
77
79 const intptr_t mask = size() - 1;
80 intptr_t idx = Hash(key) & mask;
81 intptr_t empty_idx = -1;
83
84 while (obj != static_cast<ObjectPtr>(kNoEntry)) {
85 if (obj == key) {
86 return false;
87 } else if ((empty_idx < 0) &&
88 (static_cast<intptr_t>(obj) == kDeletedEntry)) {
89 empty_idx = idx; // Insert at this location if not found.
90 }
91 idx = (idx + 1) & mask;
92 obj = ObjectAtExclusive(idx);
93 }
94
95 ASSERT(val != 0);
96
97 if (empty_idx >= 0) {
98 // We will be reusing a slot below.
99 set_used(used() - 1);
100 idx = empty_idx;
101 }
102
104 // Set the key and value.
105 SetObjectAt(idx, key);
106 SetValueAt(idx, val);
107 // Update the counts.
108 set_used(used() + 1);
109 set_count(count() + 1);
110
111 // Rehash if needed to ensure that there are empty slots available.
112 if (used_ >= limit()) {
113 Rehash();
114 }
115 return true;
116}
117
119 intptr_t* old_data = data_;
120 used_ = 0;
121 count_ = 0;
122 size_ = kMinSize;
123 free(old_data);
124 data_ = reinterpret_cast<intptr_t*>(malloc(size_ * kEntrySize * kWordSize));
125 for (intptr_t i = 0; i < size_; i++) {
126 data_[ObjectIndex(i)] = kNoEntry;
127 data_[ValueIndex(i)] = kNoValue;
128 }
129}
130
132 if (used_ == 0) return;
133
134 for (intptr_t i = 0; i < size_; i++) {
136 visitor->VisitPointer(ObjectPointerAt(i));
137 }
138 }
139
140 Rehash();
141}
142
143#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
146 void* context) {
147 MutexLocker ml(&mutex_);
148 for (intptr_t i = 0; i < size_; i++) {
150 void* data = reinterpret_cast<void*>(data_[ValueIndex(i)]);
151 callback(context, data);
152 }
153 }
154}
155
157 for (intptr_t i = 0; i < size_; i++) {
159 cleanup(reinterpret_cast<void*>(data_[ValueIndex(i)]));
160 }
161 }
162}
163#endif
164
165void WeakTable::Rehash() {
166 intptr_t old_size = size();
167 intptr_t* old_data = data_;
168
169 intptr_t new_size = SizeFor(count(), size());
170 ASSERT(Utils::IsPowerOfTwo(new_size));
171 intptr_t* new_data =
172 reinterpret_cast<intptr_t*>(malloc(new_size * kEntrySize * kWordSize));
173 for (intptr_t i = 0; i < new_size; i++) {
174 new_data[ObjectIndex(i)] = kNoEntry;
175 new_data[ValueIndex(i)] = kNoValue;
176 }
177
178 intptr_t mask = new_size - 1;
179 set_used(0);
180 for (intptr_t i = 0; i < old_size; i++) {
182 // Find the new hash location for this entry.
183 ObjectPtr key = ObjectAtExclusive(i);
184 intptr_t idx = Hash(key) & mask;
185 ObjectPtr obj = static_cast<ObjectPtr>(new_data[ObjectIndex(idx)]);
186 while (obj != static_cast<ObjectPtr>(kNoEntry)) {
187 ASSERT(obj != key); // Duplicate entry is not expected.
188 idx = (idx + 1) & mask;
189 obj = static_cast<ObjectPtr>(new_data[ObjectIndex(idx)]);
190 }
191
192 new_data[ObjectIndex(idx)] = static_cast<intptr_t>(key);
193 new_data[ValueIndex(idx)] = ValueAtExclusive(i);
194 set_used(used() + 1);
195 }
196 }
197 // We should only have used valid entries.
198 ASSERT(used() == count());
199
200 // Switch to using the newly allocated backing store.
201 size_ = new_size;
202 data_ = new_data;
203 free(old_data);
204}
205
206} // namespace dart
int count
void VisitPointer(ObjectPtr *p)
Definition visitor.h:55
static constexpr bool IsPowerOfTwo(T x)
Definition utils.h:61
intptr_t used() const
Definition weak_table.h:50
static constexpr intptr_t kNoValue
Definition weak_table.h:18
bool MarkValueExclusive(ObjectPtr key, intptr_t val)
Definition weak_table.cc:78
intptr_t ValueAtExclusive(intptr_t i) const
Definition weak_table.h:100
void SetValueExclusive(ObjectPtr key, intptr_t val)
Definition weak_table.cc:33
intptr_t count() const
Definition weak_table.h:51
bool IsValidEntryAtExclusive(intptr_t i) const
Definition weak_table.h:80
intptr_t size() const
Definition weak_table.h:49
void ReportSurvivingAllocations(Dart_HeapSamplingReportCallback callback, void *context)
ObjectPtr ObjectAtExclusive(intptr_t i) const
Definition weak_table.h:94
void Forward(ObjectPointerVisitor *visitor)
void CleanupValues(Dart_HeapSamplingDeleteCallback cleanup)
void(* Dart_HeapSamplingDeleteCallback)(void *data)
Definition dart_api.h:1287
void(* Dart_HeapSamplingReportCallback)(void *context, void *data)
Definition dart_api.h:1280
#define ASSERT(E)
#define FATAL(error)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
void * malloc(size_t size)
Definition allocation.cc:19
constexpr intptr_t kWordSize
Definition globals.h:509
static int8_t data[kExtLength]