Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/global-handles.cc

Issue 11875015: Pack GlobalHandles::Node::state_ and three flags into uint8_t (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Used BitField Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 28 matching lines...) Expand all
39 ObjectGroup::~ObjectGroup() { 39 ObjectGroup::~ObjectGroup() {
40 if (info_ != NULL) info_->Dispose(); 40 if (info_ != NULL) info_->Dispose();
41 } 41 }
42 42
43 43
44 class GlobalHandles::Node { 44 class GlobalHandles::Node {
45 public: 45 public:
46 // State transition diagram: 46 // State transition diagram:
47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } 47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
48 enum State { 48 enum State {
49 FREE, 49 FREE = 0,
50 NORMAL, // Normal global handle. 50 NORMAL, // Normal global handle.
51 WEAK, // Flagged as weak but not yet finalized. 51 WEAK, // Flagged as weak but not yet finalized.
52 PENDING, // Has been recognized as only reachable by weak handles. 52 PENDING, // Has been recognized as only reachable by weak handles.
53 NEAR_DEATH // Callback has informed the handle is near death. 53 NEAR_DEATH // Callback has informed the handle is near death.
54 }; 54 };
55 55
56 // Maps handle location (slot) to the containing node. 56 // Maps handle location (slot) to the containing node.
57 static Node* FromLocation(Object** location) { 57 static Node* FromLocation(Object** location) {
58 ASSERT(OFFSET_OF(Node, object_) == 0); 58 ASSERT(OFFSET_OF(Node, object_) == 0);
59 return reinterpret_cast<Node*>(location); 59 return reinterpret_cast<Node*>(location);
60 } 60 }
61 61
62 Node() {} 62 Node() {}
63 63
64 #ifdef DEBUG 64 #ifdef DEBUG
65 ~Node() { 65 ~Node() {
66 // TODO(1428): if it's a weak handle we should have invoked its callback. 66 // TODO(1428): if it's a weak handle we should have invoked its callback.
67 // Zap the values for eager trapping. 67 // Zap the values for eager trapping.
68 object_ = NULL; 68 object_ = NULL;
69 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; 69 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
70 index_ = 0; 70 index_ = 0;
71 independent_ = false; 71 set_independent(false);
72 partially_dependent_ = false; 72 set_partially_dependent_(false);
73 in_new_space_list_ = false; 73 set_in_new_space_list_(false);
Michael Starzinger 2013/01/15 10:27:13 Two small typos at the trailing underscore. Fixed
74 parameter_or_next_free_.next_free = NULL; 74 parameter_or_next_free_.next_free = NULL;
75 callback_ = NULL; 75 callback_ = NULL;
76 } 76 }
77 #endif 77 #endif
78 78
79 void Initialize(int index, Node** first_free) { 79 void Initialize(int index, Node** first_free) {
80 index_ = static_cast<uint8_t>(index); 80 index_ = static_cast<uint8_t>(index);
81 ASSERT(static_cast<int>(index_) == index); 81 ASSERT(static_cast<int>(index_) == index);
82 state_ = FREE; 82 set_state(FREE);
83 in_new_space_list_ = false; 83 set_in_new_space_list(false);
84 parameter_or_next_free_.next_free = *first_free; 84 parameter_or_next_free_.next_free = *first_free;
85 *first_free = this; 85 *first_free = this;
86 } 86 }
87 87
88 void Acquire(Object* object, GlobalHandles* global_handles) { 88 void Acquire(Object* object, GlobalHandles* global_handles) {
89 ASSERT(state_ == FREE); 89 ASSERT(state() == FREE);
90 object_ = object; 90 object_ = object;
91 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; 91 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
92 independent_ = false; 92 set_independent(false);
93 partially_dependent_ = false; 93 set_partially_dependent(false);
94 state_ = NORMAL; 94 set_state(NORMAL);
95 parameter_or_next_free_.parameter = NULL; 95 parameter_or_next_free_.parameter = NULL;
96 callback_ = NULL; 96 callback_ = NULL;
97 IncreaseBlockUses(global_handles); 97 IncreaseBlockUses(global_handles);
98 } 98 }
99 99
100 void Release(GlobalHandles* global_handles) { 100 void Release(GlobalHandles* global_handles) {
101 ASSERT(state_ != FREE); 101 ASSERT(state() != FREE);
102 if (IsWeakRetainer()) { 102 if (IsWeakRetainer()) {
103 global_handles->number_of_weak_handles_--; 103 global_handles->number_of_weak_handles_--;
104 if (object_->IsJSGlobalObject()) { 104 if (object_->IsJSGlobalObject()) {
105 global_handles->number_of_global_object_weak_handles_--; 105 global_handles->number_of_global_object_weak_handles_--;
106 } 106 }
107 } 107 }
108 state_ = FREE; 108 set_state(FREE);
109 parameter_or_next_free_.next_free = global_handles->first_free_; 109 parameter_or_next_free_.next_free = global_handles->first_free_;
110 global_handles->first_free_ = this; 110 global_handles->first_free_ = this;
111 DecreaseBlockUses(global_handles); 111 DecreaseBlockUses(global_handles);
112 } 112 }
113 113
114 // Object slot accessors. 114 // Object slot accessors.
115 Object* object() const { return object_; } 115 Object* object() const { return object_; }
116 Object** location() { return &object_; } 116 Object** location() { return &object_; }
117 Handle<Object> handle() { return Handle<Object>(location()); } 117 Handle<Object> handle() { return Handle<Object>(location()); }
118 118
119 // Wrapper class ID accessors. 119 // Wrapper class ID accessors.
120 bool has_wrapper_class_id() const { 120 bool has_wrapper_class_id() const {
121 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; 121 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
122 } 122 }
123
123 uint16_t wrapper_class_id() const { return class_id_; } 124 uint16_t wrapper_class_id() const { return class_id_; }
124 void set_wrapper_class_id(uint16_t class_id) { 125 void set_wrapper_class_id(uint16_t class_id) { class_id_ = class_id; }
125 class_id_ = class_id; 126
127 // State and flag accessors.
128
129 State state() const {
130 return NodeState::decode(flags_);
131 }
132 void set_state(State state) {
133 flags_ = NodeState::update(flags_, state);
126 } 134 }
127 135
128 // State accessors. 136 bool is_independent() {
137 return IsIndependent::decode(flags_);
138 }
139 void set_independent(bool v) {
140 flags_ = IsIndependent::update(flags_, v);
141 }
129 142
130 State state() const { return state_; } 143 bool is_partially_dependent() {
144 return IsPartiallyDependent::decode(flags_);
145 }
146 void set_partially_dependent(bool v) {
147 flags_ = IsPartiallyDependent::update(flags_, v);
148 }
149
150 bool is_in_new_space_list() {
151 return IsInNewSpaceList::decode(flags_);
152 }
153 void set_in_new_space_list(bool v) {
154 flags_ = IsInNewSpaceList::update(flags_, v);
155 }
131 156
132 bool IsNearDeath() const { 157 bool IsNearDeath() const {
133 // Check for PENDING to ensure correct answer when processing callbacks. 158 // Check for PENDING to ensure correct answer when processing callbacks.
134 return state_ == PENDING || state_ == NEAR_DEATH; 159 return state() == PENDING || state() == NEAR_DEATH;
135 } 160 }
136 161
137 bool IsWeak() const { return state_ == WEAK; } 162 bool IsWeak() const { return state() == WEAK; }
138 163
139 bool IsRetainer() const { return state_ != FREE; } 164 bool IsRetainer() const { return state() != FREE; }
140 165
141 bool IsStrongRetainer() const { return state_ == NORMAL; } 166 bool IsStrongRetainer() const { return state() == NORMAL; }
142 167
143 bool IsWeakRetainer() const { 168 bool IsWeakRetainer() const {
144 return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH; 169 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH;
145 } 170 }
146 171
147 void MarkPending() { 172 void MarkPending() {
148 ASSERT(state_ == WEAK); 173 ASSERT(state() == WEAK);
149 state_ = PENDING; 174 set_state(PENDING);
150 } 175 }
151 176
152 // Independent flag accessors. 177 // Independent flag accessors.
153 void MarkIndependent() { 178 void MarkIndependent() {
154 ASSERT(state_ != FREE); 179 ASSERT(state() != FREE);
155 independent_ = true; 180 set_independent(true);
156 } 181 }
157 bool is_independent() const { return independent_; }
158 182
159 void MarkPartiallyDependent(GlobalHandles* global_handles) { 183 void MarkPartiallyDependent(GlobalHandles* global_handles) {
160 ASSERT(state_ != FREE); 184 ASSERT(state() != FREE);
161 if (global_handles->isolate()->heap()->InNewSpace(object_)) { 185 if (global_handles->isolate()->heap()->InNewSpace(object_)) {
162 partially_dependent_ = true; 186 set_partially_dependent(true);
163 } 187 }
164 } 188 }
165 bool is_partially_dependent() const { return partially_dependent_; } 189 void clear_partially_dependent() { set_partially_dependent(false); }
166 void clear_partially_dependent() { partially_dependent_ = false; }
167
168 // In-new-space-list flag accessors.
169 void set_in_new_space_list(bool v) { in_new_space_list_ = v; }
170 bool is_in_new_space_list() const { return in_new_space_list_; }
171 190
172 // Callback accessor. 191 // Callback accessor.
173 WeakReferenceCallback callback() { return callback_; } 192 WeakReferenceCallback callback() { return callback_; }
174 193
175 // Callback parameter accessors. 194 // Callback parameter accessors.
176 void set_parameter(void* parameter) { 195 void set_parameter(void* parameter) {
177 ASSERT(state_ != FREE); 196 ASSERT(state() != FREE);
178 parameter_or_next_free_.parameter = parameter; 197 parameter_or_next_free_.parameter = parameter;
179 } 198 }
180 void* parameter() const { 199 void* parameter() const {
181 ASSERT(state_ != FREE); 200 ASSERT(state() != FREE);
182 return parameter_or_next_free_.parameter; 201 return parameter_or_next_free_.parameter;
183 } 202 }
184 203
185 // Accessors for next free node in the free list. 204 // Accessors for next free node in the free list.
186 Node* next_free() { 205 Node* next_free() {
187 ASSERT(state_ == FREE); 206 ASSERT(state() == FREE);
188 return parameter_or_next_free_.next_free; 207 return parameter_or_next_free_.next_free;
189 } 208 }
190 void set_next_free(Node* value) { 209 void set_next_free(Node* value) {
191 ASSERT(state_ == FREE); 210 ASSERT(state() == FREE);
192 parameter_or_next_free_.next_free = value; 211 parameter_or_next_free_.next_free = value;
193 } 212 }
194 213
195 void MakeWeak(GlobalHandles* global_handles, 214 void MakeWeak(GlobalHandles* global_handles,
196 void* parameter, 215 void* parameter,
197 WeakReferenceCallback callback) { 216 WeakReferenceCallback callback) {
198 ASSERT(state_ != FREE); 217 ASSERT(state() != FREE);
199 if (!IsWeakRetainer()) { 218 if (!IsWeakRetainer()) {
200 global_handles->number_of_weak_handles_++; 219 global_handles->number_of_weak_handles_++;
201 if (object_->IsJSGlobalObject()) { 220 if (object_->IsJSGlobalObject()) {
202 global_handles->number_of_global_object_weak_handles_++; 221 global_handles->number_of_global_object_weak_handles_++;
203 } 222 }
204 } 223 }
205 state_ = WEAK; 224 set_state(WEAK);
206 set_parameter(parameter); 225 set_parameter(parameter);
207 callback_ = callback; 226 callback_ = callback;
208 } 227 }
209 228
210 void ClearWeakness(GlobalHandles* global_handles) { 229 void ClearWeakness(GlobalHandles* global_handles) {
211 ASSERT(state_ != FREE); 230 ASSERT(state() != FREE);
212 if (IsWeakRetainer()) { 231 if (IsWeakRetainer()) {
213 global_handles->number_of_weak_handles_--; 232 global_handles->number_of_weak_handles_--;
214 if (object_->IsJSGlobalObject()) { 233 if (object_->IsJSGlobalObject()) {
215 global_handles->number_of_global_object_weak_handles_--; 234 global_handles->number_of_global_object_weak_handles_--;
216 } 235 }
217 } 236 }
218 state_ = NORMAL; 237 set_state(NORMAL);
219 set_parameter(NULL); 238 set_parameter(NULL);
220 } 239 }
221 240
222 bool PostGarbageCollectionProcessing(Isolate* isolate, 241 bool PostGarbageCollectionProcessing(Isolate* isolate,
223 GlobalHandles* global_handles) { 242 GlobalHandles* global_handles) {
224 if (state_ != Node::PENDING) return false; 243 if (state() != Node::PENDING) return false;
225 WeakReferenceCallback func = callback(); 244 WeakReferenceCallback func = callback();
226 if (func == NULL) { 245 if (func == NULL) {
227 Release(global_handles); 246 Release(global_handles);
228 return false; 247 return false;
229 } 248 }
230 void* par = parameter(); 249 void* par = parameter();
231 state_ = NEAR_DEATH; 250 set_state(NEAR_DEATH);
232 set_parameter(NULL); 251 set_parameter(NULL);
233 252
234 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); 253 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
235 { 254 {
236 // Check that we are not passing a finalized external string to 255 // Check that we are not passing a finalized external string to
237 // the callback. 256 // the callback.
238 ASSERT(!object_->IsExternalAsciiString() || 257 ASSERT(!object_->IsExternalAsciiString() ||
239 ExternalAsciiString::cast(object_)->resource() != NULL); 258 ExternalAsciiString::cast(object_)->resource() != NULL);
240 ASSERT(!object_->IsExternalTwoByteString() || 259 ASSERT(!object_->IsExternalTwoByteString() ||
241 ExternalTwoByteString::cast(object_)->resource() != NULL); 260 ExternalTwoByteString::cast(object_)->resource() != NULL);
242 // Leaving V8. 261 // Leaving V8.
243 VMState state(isolate, EXTERNAL); 262 VMState state(isolate, EXTERNAL);
244 func(object, par); 263 func(object, par);
245 } 264 }
246 // Absence of explicit cleanup or revival of weak handle 265 // Absence of explicit cleanup or revival of weak handle
247 // in most of the cases would lead to memory leak. 266 // in most of the cases would lead to memory leak.
248 ASSERT(state_ != NEAR_DEATH); 267 ASSERT(state() != NEAR_DEATH);
249 return true; 268 return true;
250 } 269 }
251 270
252 private: 271 private:
253 inline NodeBlock* FindBlock(); 272 inline NodeBlock* FindBlock();
254 inline void IncreaseBlockUses(GlobalHandles* global_handles); 273 inline void IncreaseBlockUses(GlobalHandles* global_handles);
255 inline void DecreaseBlockUses(GlobalHandles* global_handles); 274 inline void DecreaseBlockUses(GlobalHandles* global_handles);
256 275
257 // Storage for object pointer. 276 // Storage for object pointer.
258 // Placed first to avoid offset computation. 277 // Placed first to avoid offset computation.
259 Object* object_; 278 Object* object_;
260 279
261 // Next word stores class_id, index, state, and independent. 280 // Next word stores class_id, index, state, and independent.
262 // Note: the most aligned fields should go first. 281 // Note: the most aligned fields should go first.
263 282
264 // Wrapper class ID. 283 // Wrapper class ID.
265 uint16_t class_id_; 284 uint16_t class_id_;
266 285
267 // Index in the containing handle block. 286 // Index in the containing handle block.
268 uint8_t index_; 287 uint8_t index_;
269 288
270 // Need one more bit for MSVC as it treats enums as signed. 289 // This stores three flags (independent, partially_dependent and
271 State state_ : 4; 290 // in_new_space_list) and a State.
291 class NodeState: public BitField<State, 0, 4> {};
292 class IsIndependent: public BitField<bool, 4, 1> {};
293 class IsPartiallyDependent: public BitField<bool, 5, 1> {};
294 class IsInNewSpaceList: public BitField<bool, 6, 1> {};
272 295
273 bool independent_ : 1; 296 uint8_t flags_;
274 bool partially_dependent_ : 1;
275 bool in_new_space_list_ : 1;
276 297
277 // Handle specific callback. 298 // Handle specific callback.
278 WeakReferenceCallback callback_; 299 WeakReferenceCallback callback_;
279 300
280 // Provided data for callback. In FREE state, this is used for 301 // Provided data for callback. In FREE state, this is used for
281 // the free list link. 302 // the free list link.
282 union { 303 union {
283 void* parameter; 304 void* parameter;
284 Node* next_free; 305 Node* next_free;
285 } parameter_or_next_free_; 306 } parameter_or_next_free_;
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 implicit_ref_groups_.Clear(); 819 implicit_ref_groups_.Clear();
799 } 820 }
800 821
801 822
802 void GlobalHandles::TearDown() { 823 void GlobalHandles::TearDown() {
803 // TODO(1428): invoke weak callbacks. 824 // TODO(1428): invoke weak callbacks.
804 } 825 }
805 826
806 827
807 } } // namespace v8::internal 828 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698