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

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: patch 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 23 matching lines...) Expand all
34 34
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 38
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 const uint8_t NodeIndependentFlag = 6;
45 const uint8_t NodePartiallyDependentFlag = 5;
46 const uint8_t NodeInNewSpaceListFlag = 4;
47 const uint8_t NodeIndependentFlagMask = 1 << NodeIndependentFlag;
48 const uint8_t NodePartiallyDependentFlagMask = 1 << NodePartiallyDependentFlag;
49 const uint8_t NodeInNewSpaceListFlagMask = 1 << NodeInNewSpaceListFlag;
50 const uint8_t NodeStateMask = 0xf;
51
52
44 class GlobalHandles::Node { 53 class GlobalHandles::Node {
45 public: 54 public:
46 // State transition diagram: 55 // State transition diagram:
47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } 56 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
48 enum State { 57 enum State {
49 FREE, 58 FREE = 0,
50 NORMAL, // Normal global handle. 59 NORMAL, // Normal global handle.
51 WEAK, // Flagged as weak but not yet finalized. 60 WEAK, // Flagged as weak but not yet finalized.
52 PENDING, // Has been recognized as only reachable by weak handles. 61 PENDING, // Has been recognized as only reachable by weak handles.
53 NEAR_DEATH // Callback has informed the handle is near death. 62 NEAR_DEATH // Callback has informed the handle is near death.
54 }; 63 };
55 64
56 // Maps handle location (slot) to the containing node. 65 // Maps handle location (slot) to the containing node.
57 static Node* FromLocation(Object** location) { 66 static Node* FromLocation(Object** location) {
58 ASSERT(OFFSET_OF(Node, object_) == 0); 67 ASSERT(OFFSET_OF(Node, object_) == 0);
59 return reinterpret_cast<Node*>(location); 68 return reinterpret_cast<Node*>(location);
60 } 69 }
61 70
62 Node() {} 71 Node() {}
63 72
64 #ifdef DEBUG 73 #ifdef DEBUG
65 ~Node() { 74 ~Node() {
66 // TODO(1428): if it's a weak handle we should have invoked its callback. 75 // TODO(1428): if it's a weak handle we should have invoked its callback.
67 // Zap the values for eager trapping. 76 // Zap the values for eager trapping.
68 object_ = NULL; 77 object_ = NULL;
69 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; 78 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
70 index_ = 0; 79 index_ = 0;
71 independent_ = false; 80 set_independent(false);
72 partially_dependent_ = false; 81 set_partially_dependent_(false);
73 in_new_space_list_ = false; 82 set_in_new_space_list_(false);
74 parameter_or_next_free_.next_free = NULL; 83 parameter_or_next_free_.next_free = NULL;
75 callback_ = NULL; 84 callback_ = NULL;
76 } 85 }
77 #endif 86 #endif
78 87
79 void Initialize(int index, Node** first_free) { 88 void Initialize(int index, Node** first_free) {
80 index_ = static_cast<uint8_t>(index); 89 index_ = static_cast<uint8_t>(index);
81 ASSERT(static_cast<int>(index_) == index); 90 ASSERT(static_cast<int>(index_) == index);
82 state_ = FREE; 91 set_state(FREE);
83 in_new_space_list_ = false; 92 set_in_new_space_list(false);
84 parameter_or_next_free_.next_free = *first_free; 93 parameter_or_next_free_.next_free = *first_free;
85 *first_free = this; 94 *first_free = this;
86 } 95 }
87 96
88 void Acquire(Object* object, GlobalHandles* global_handles) { 97 void Acquire(Object* object, GlobalHandles* global_handles) {
89 ASSERT(state_ == FREE); 98 ASSERT(state() == FREE);
90 object_ = object; 99 object_ = object;
91 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; 100 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
92 independent_ = false; 101 set_independent(false);
93 partially_dependent_ = false; 102 set_partially_dependent(false);
94 state_ = NORMAL; 103 set_state(NORMAL);
95 parameter_or_next_free_.parameter = NULL; 104 parameter_or_next_free_.parameter = NULL;
96 callback_ = NULL; 105 callback_ = NULL;
97 IncreaseBlockUses(global_handles); 106 IncreaseBlockUses(global_handles);
98 } 107 }
99 108
100 void Release(GlobalHandles* global_handles) { 109 void Release(GlobalHandles* global_handles) {
101 ASSERT(state_ != FREE); 110 ASSERT(state() != FREE);
102 if (IsWeakRetainer()) { 111 if (IsWeakRetainer()) {
103 global_handles->number_of_weak_handles_--; 112 global_handles->number_of_weak_handles_--;
104 if (object_->IsJSGlobalObject()) { 113 if (object_->IsJSGlobalObject()) {
105 global_handles->number_of_global_object_weak_handles_--; 114 global_handles->number_of_global_object_weak_handles_--;
106 } 115 }
107 } 116 }
108 state_ = FREE; 117 set_state(FREE);
109 parameter_or_next_free_.next_free = global_handles->first_free_; 118 parameter_or_next_free_.next_free = global_handles->first_free_;
110 global_handles->first_free_ = this; 119 global_handles->first_free_ = this;
111 DecreaseBlockUses(global_handles); 120 DecreaseBlockUses(global_handles);
112 } 121 }
113 122
114 // Object slot accessors. 123 // Object slot accessors.
115 Object* object() const { return object_; } 124 Object* object() const { return object_; }
116 Object** location() { return &object_; } 125 Object** location() { return &object_; }
117 Handle<Object> handle() { return Handle<Object>(location()); } 126 Handle<Object> handle() { return Handle<Object>(location()); }
118 127
119 // Wrapper class ID accessors. 128 // Wrapper class ID accessors.
120 bool has_wrapper_class_id() const { 129 bool has_wrapper_class_id() const {
121 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; 130 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
122 } 131 }
132
123 uint16_t wrapper_class_id() const { return class_id_; } 133 uint16_t wrapper_class_id() const { return class_id_; }
124 void set_wrapper_class_id(uint16_t class_id) { 134 void set_wrapper_class_id(uint16_t class_id) {
125 class_id_ = class_id; 135 class_id_ = static_cast<uint8_t>(class_id);
Michael Starzinger 2013/01/15 09:06:41 The class_id is a full 16 bit, we can drop this ca
haraken 2013/01/15 09:40:39 Done.
126 } 136 }
127 137
128 // State accessors. 138 // State and flag accessors.
129 139
130 State state() const { return state_; } 140 State state() const {
141 return static_cast<State>(flags_and_state_ & NodeStateMask);
Michael Starzinger 2013/01/15 09:06:41 Instead of using all of this hand-written magic, c
haraken 2013/01/15 09:40:39 Done.
142 }
143 void set_state(State state) {
144 flags_and_state_ =
145 (flags_and_state_ & ~NodeStateMask) | state;
146 }
147
148 bool is_independent() {
149 return flags_and_state_ & NodeIndependentFlagMask;
150 }
151 void set_independent(bool v) {
152 flags_and_state_ =
153 (flags_and_state_ & ~NodeIndependentFlagMask) |
154 (static_cast<uint8_t>(v) << NodeIndependentFlag);
155 }
156
157 bool is_partially_dependent() {
158 return flags_and_state_ & NodePartiallyDependentFlagMask;
159 }
160 void set_partially_dependent(bool v) {
161 flags_and_state_ =
162 (flags_and_state_ & ~NodePartiallyDependentFlagMask) |
163 (static_cast<uint8_t>(v) << NodePartiallyDependentFlag);
164 }
165
166 bool is_in_new_space_list() {
167 return flags_and_state_ & NodeInNewSpaceListFlagMask;
168 }
169 void set_in_new_space_list(bool v) {
170 flags_and_state_ =
171 (flags_and_state_ & ~NodeInNewSpaceListFlagMask) |
172 (static_cast<uint8_t>(v) << NodeInNewSpaceListFlag);
173 }
131 174
132 bool IsNearDeath() const { 175 bool IsNearDeath() const {
133 // Check for PENDING to ensure correct answer when processing callbacks. 176 // Check for PENDING to ensure correct answer when processing callbacks.
134 return state_ == PENDING || state_ == NEAR_DEATH; 177 return state() == PENDING || state() == NEAR_DEATH;
135 } 178 }
136 179
137 bool IsWeak() const { return state_ == WEAK; } 180 bool IsWeak() const { return state() == WEAK; }
138 181
139 bool IsRetainer() const { return state_ != FREE; } 182 bool IsRetainer() const { return state() != FREE; }
140 183
141 bool IsStrongRetainer() const { return state_ == NORMAL; } 184 bool IsStrongRetainer() const { return state() == NORMAL; }
142 185
143 bool IsWeakRetainer() const { 186 bool IsWeakRetainer() const {
144 return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH; 187 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH;
145 } 188 }
146 189
147 void MarkPending() { 190 void MarkPending() {
148 ASSERT(state_ == WEAK); 191 ASSERT(state() == WEAK);
149 state_ = PENDING; 192 set_state(PENDING);
150 } 193 }
151 194
152 // Independent flag accessors. 195 // Independent flag accessors.
153 void MarkIndependent() { 196 void MarkIndependent() {
154 ASSERT(state_ != FREE); 197 ASSERT(state() != FREE);
155 independent_ = true; 198 set_independent(true);
156 } 199 }
157 bool is_independent() const { return independent_; }
158 200
159 void MarkPartiallyDependent(GlobalHandles* global_handles) { 201 void MarkPartiallyDependent(GlobalHandles* global_handles) {
160 ASSERT(state_ != FREE); 202 ASSERT(state() != FREE);
161 if (global_handles->isolate()->heap()->InNewSpace(object_)) { 203 if (global_handles->isolate()->heap()->InNewSpace(object_)) {
162 partially_dependent_ = true; 204 set_partially_dependent(true);
163 } 205 }
164 } 206 }
165 bool is_partially_dependent() const { return partially_dependent_; } 207 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 208
172 // Callback accessor. 209 // Callback accessor.
173 WeakReferenceCallback callback() { return callback_; } 210 WeakReferenceCallback callback() { return callback_; }
174 211
175 // Callback parameter accessors. 212 // Callback parameter accessors.
176 void set_parameter(void* parameter) { 213 void set_parameter(void* parameter) {
177 ASSERT(state_ != FREE); 214 ASSERT(state() != FREE);
178 parameter_or_next_free_.parameter = parameter; 215 parameter_or_next_free_.parameter = parameter;
179 } 216 }
180 void* parameter() const { 217 void* parameter() const {
181 ASSERT(state_ != FREE); 218 ASSERT(state() != FREE);
182 return parameter_or_next_free_.parameter; 219 return parameter_or_next_free_.parameter;
183 } 220 }
184 221
185 // Accessors for next free node in the free list. 222 // Accessors for next free node in the free list.
186 Node* next_free() { 223 Node* next_free() {
187 ASSERT(state_ == FREE); 224 ASSERT(state() == FREE);
188 return parameter_or_next_free_.next_free; 225 return parameter_or_next_free_.next_free;
189 } 226 }
190 void set_next_free(Node* value) { 227 void set_next_free(Node* value) {
191 ASSERT(state_ == FREE); 228 ASSERT(state() == FREE);
192 parameter_or_next_free_.next_free = value; 229 parameter_or_next_free_.next_free = value;
193 } 230 }
194 231
195 void MakeWeak(GlobalHandles* global_handles, 232 void MakeWeak(GlobalHandles* global_handles,
196 void* parameter, 233 void* parameter,
197 WeakReferenceCallback callback) { 234 WeakReferenceCallback callback) {
198 ASSERT(state_ != FREE); 235 ASSERT(state() != FREE);
199 if (!IsWeakRetainer()) { 236 if (!IsWeakRetainer()) {
200 global_handles->number_of_weak_handles_++; 237 global_handles->number_of_weak_handles_++;
201 if (object_->IsJSGlobalObject()) { 238 if (object_->IsJSGlobalObject()) {
202 global_handles->number_of_global_object_weak_handles_++; 239 global_handles->number_of_global_object_weak_handles_++;
203 } 240 }
204 } 241 }
205 state_ = WEAK; 242 set_state(WEAK);
206 set_parameter(parameter); 243 set_parameter(parameter);
207 callback_ = callback; 244 callback_ = callback;
208 } 245 }
209 246
210 void ClearWeakness(GlobalHandles* global_handles) { 247 void ClearWeakness(GlobalHandles* global_handles) {
211 ASSERT(state_ != FREE); 248 ASSERT(state() != FREE);
212 if (IsWeakRetainer()) { 249 if (IsWeakRetainer()) {
213 global_handles->number_of_weak_handles_--; 250 global_handles->number_of_weak_handles_--;
214 if (object_->IsJSGlobalObject()) { 251 if (object_->IsJSGlobalObject()) {
215 global_handles->number_of_global_object_weak_handles_--; 252 global_handles->number_of_global_object_weak_handles_--;
216 } 253 }
217 } 254 }
218 state_ = NORMAL; 255 set_state(NORMAL);
219 set_parameter(NULL); 256 set_parameter(NULL);
220 } 257 }
221 258
222 bool PostGarbageCollectionProcessing(Isolate* isolate, 259 bool PostGarbageCollectionProcessing(Isolate* isolate,
223 GlobalHandles* global_handles) { 260 GlobalHandles* global_handles) {
224 if (state_ != Node::PENDING) return false; 261 if (state() != Node::PENDING) return false;
225 WeakReferenceCallback func = callback(); 262 WeakReferenceCallback func = callback();
226 if (func == NULL) { 263 if (func == NULL) {
227 Release(global_handles); 264 Release(global_handles);
228 return false; 265 return false;
229 } 266 }
230 void* par = parameter(); 267 void* par = parameter();
231 state_ = NEAR_DEATH; 268 set_state(NEAR_DEATH);
232 set_parameter(NULL); 269 set_parameter(NULL);
233 270
234 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); 271 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
235 { 272 {
236 // Check that we are not passing a finalized external string to 273 // Check that we are not passing a finalized external string to
237 // the callback. 274 // the callback.
238 ASSERT(!object_->IsExternalAsciiString() || 275 ASSERT(!object_->IsExternalAsciiString() ||
239 ExternalAsciiString::cast(object_)->resource() != NULL); 276 ExternalAsciiString::cast(object_)->resource() != NULL);
240 ASSERT(!object_->IsExternalTwoByteString() || 277 ASSERT(!object_->IsExternalTwoByteString() ||
241 ExternalTwoByteString::cast(object_)->resource() != NULL); 278 ExternalTwoByteString::cast(object_)->resource() != NULL);
242 // Leaving V8. 279 // Leaving V8.
243 VMState state(isolate, EXTERNAL); 280 VMState state(isolate, EXTERNAL);
244 func(object, par); 281 func(object, par);
245 } 282 }
246 // Absence of explicit cleanup or revival of weak handle 283 // Absence of explicit cleanup or revival of weak handle
247 // in most of the cases would lead to memory leak. 284 // in most of the cases would lead to memory leak.
248 ASSERT(state_ != NEAR_DEATH); 285 ASSERT(state() != NEAR_DEATH);
249 return true; 286 return true;
250 } 287 }
251 288
252 private: 289 private:
253 inline NodeBlock* FindBlock(); 290 inline NodeBlock* FindBlock();
254 inline void IncreaseBlockUses(GlobalHandles* global_handles); 291 inline void IncreaseBlockUses(GlobalHandles* global_handles);
255 inline void DecreaseBlockUses(GlobalHandles* global_handles); 292 inline void DecreaseBlockUses(GlobalHandles* global_handles);
256 293
257 // Storage for object pointer. 294 // Storage for object pointer.
258 // Placed first to avoid offset computation. 295 // Placed first to avoid offset computation.
259 Object* object_; 296 Object* object_;
260 297
261 // Next word stores class_id, index, state, and independent. 298 // Next word stores class_id, index, state, and independent.
262 // Note: the most aligned fields should go first. 299 // Note: the most aligned fields should go first.
263 300
264 // Wrapper class ID. 301 // Wrapper class ID.
265 uint16_t class_id_; 302 uint16_t class_id_;
266 303
267 // Index in the containing handle block. 304 // Index in the containing handle block.
268 uint8_t index_; 305 uint8_t index_;
269 306
270 // Need one more bit for MSVC as it treats enums as signed. 307 // This stores three flags (independent, partially_dependent and
271 State state_ : 4; 308 // in_new_space_list) and a State.
272 309 uint8_t flags_and_state_;
Michael Starzinger 2013/01/15 09:06:41 Let's just call this field "flags_".
haraken 2013/01/15 09:40:39 Done.
273 bool independent_ : 1;
274 bool partially_dependent_ : 1;
275 bool in_new_space_list_ : 1;
276 310
277 // Handle specific callback. 311 // Handle specific callback.
278 WeakReferenceCallback callback_; 312 WeakReferenceCallback callback_;
279 313
280 // Provided data for callback. In FREE state, this is used for 314 // Provided data for callback. In FREE state, this is used for
281 // the free list link. 315 // the free list link.
282 union { 316 union {
283 void* parameter; 317 void* parameter;
284 Node* next_free; 318 Node* next_free;
285 } parameter_or_next_free_; 319 } parameter_or_next_free_;
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 implicit_ref_groups_.Clear(); 832 implicit_ref_groups_.Clear();
799 } 833 }
800 834
801 835
802 void GlobalHandles::TearDown() { 836 void GlobalHandles::TearDown() {
803 // TODO(1428): invoke weak callbacks. 837 // TODO(1428): invoke weak callbacks.
804 } 838 }
805 839
806 840
807 } } // namespace v8::internal 841 } } // 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