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

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

Issue 260017: Implemented really weak handles. (Closed)
Patch Set: Fix typo. Created 11 years, 2 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
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 21 matching lines...) Expand all
32 32
33 namespace v8 { 33 namespace v8 {
34 namespace internal { 34 namespace internal {
35 35
36 class GlobalHandles::Node : public Malloced { 36 class GlobalHandles::Node : public Malloced {
37 public: 37 public:
38 38
39 void Initialize(Object* object) { 39 void Initialize(Object* object) {
40 // Set the initial value of the handle. 40 // Set the initial value of the handle.
41 object_ = object; 41 object_ = object;
42 really_weak_ = false;
42 state_ = NORMAL; 43 state_ = NORMAL;
43 parameter_or_next_free_.parameter = NULL; 44 parameter_or_next_free_.parameter = NULL;
44 callback_ = NULL; 45 callback_ = NULL;
45 } 46 }
46 47
47 explicit Node(Object* object) { 48 explicit Node(Object* object) {
48 Initialize(object); 49 Initialize(object);
49 // Initialize link structure. 50 // Initialize link structure.
50 next_ = NULL; 51 next_ = NULL;
51 } 52 }
52 53
53 ~Node() { 54 ~Node() {
54 if (state_ != DESTROYED) Destroy(); 55 if (state_ != DESTROYED) Destroy();
55 #ifdef DEBUG 56 #ifdef DEBUG
56 // Zap the values for eager trapping. 57 // Zap the values for eager trapping.
57 object_ = NULL; 58 object_ = NULL;
58 next_ = NULL; 59 next_ = NULL;
59 parameter_or_next_free_.next_free = NULL; 60 parameter_or_next_free_.next_free = NULL;
60 #endif 61 #endif
61 } 62 }
62 63
63 void Destroy() { 64 void Destroy() {
64 if (state_ == WEAK || IsNearDeath()) { 65 if (state_ == WEAK || IsNearDeath()) {
65 GlobalHandles::number_of_weak_handles_--; 66 GlobalHandles::number_of_weak_handles_--;
66 if (object_->IsJSGlobalObject()) {
67 GlobalHandles::number_of_global_object_weak_handles_--;
68 }
69 } 67 }
70 state_ = DESTROYED; 68 state_ = DESTROYED;
71 } 69 }
72 70
73 // Accessors for next_. 71 // Accessors for next_.
74 Node* next() { return next_; } 72 Node* next() { return next_; }
75 void set_next(Node* value) { next_ = value; } 73 void set_next(Node* value) { next_ = value; }
76 Node** next_addr() { return &next_; } 74 Node** next_addr() { return &next_; }
77 75
78 // Accessors for next free node in the free list. 76 // Accessors for next free node in the free list.
79 Node* next_free() { 77 Node* next_free() {
80 ASSERT(state_ == DESTROYED); 78 ASSERT(state_ == DESTROYED);
81 return parameter_or_next_free_.next_free; 79 return parameter_or_next_free_.next_free;
82 } 80 }
83 void set_next_free(Node* value) { 81 void set_next_free(Node* value) {
84 ASSERT(state_ == DESTROYED); 82 ASSERT(state_ == DESTROYED);
85 parameter_or_next_free_.next_free = value; 83 parameter_or_next_free_.next_free = value;
86 } 84 }
87 85
88 // Returns a link from the handle. 86 // Returns a link from the handle.
89 static Node* FromLocation(Object** location) { 87 static Node* FromLocation(Object** location) {
90 ASSERT(OFFSET_OF(Node, object_) == 0); 88 ASSERT(OFFSET_OF(Node, object_) == 0);
91 return reinterpret_cast<Node*>(location); 89 return reinterpret_cast<Node*>(location);
92 } 90 }
93 91
94 // Returns the handle. 92 // Returns the handle.
95 Handle<Object> handle() { return Handle<Object>(&object_); } 93 Handle<Object> handle() { return Handle<Object>(&object_); }
96 94
97 // Make this handle weak. 95 // Make this handle weak.
98 void MakeWeak(void* parameter, WeakReferenceCallback callback) { 96 void MakeWeak(void* parameter, WeakReferenceCallback callback,
Christian Plesner Hansen 2009/10/06 13:47:21 The 'callback' parameter should be moved to the ne
97 bool really_weak) {
99 LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location())); 98 LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
100 ASSERT(state_ != DESTROYED); 99 ASSERT(state_ != DESTROYED);
101 if (state_ != WEAK && !IsNearDeath()) { 100 if (state_ != WEAK && !IsNearDeath()) {
102 GlobalHandles::number_of_weak_handles_++; 101 GlobalHandles::number_of_weak_handles_++;
103 if (object_->IsJSGlobalObject()) {
104 GlobalHandles::number_of_global_object_weak_handles_++;
105 }
106 } 102 }
103 really_weak_ = really_weak;
107 state_ = WEAK; 104 state_ = WEAK;
108 set_parameter(parameter); 105 set_parameter(parameter);
109 callback_ = callback; 106 callback_ = callback;
110 } 107 }
111 108
112 void ClearWeakness() { 109 void ClearWeakness() {
113 LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location())); 110 LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
114 ASSERT(state_ != DESTROYED); 111 ASSERT(state_ != DESTROYED);
115 if (state_ == WEAK || IsNearDeath()) { 112 if (state_ == WEAK || IsNearDeath()) {
113 // Can't clear weakness of near death really weak handle because
114 // the object may have been collected already.
115 ASSERT(!IsNearDeath() || !really_weak_);
Christian Plesner Hansen 2009/10/06 13:47:21 Are we sure this can't happen? Wouldn't it be saf
116 GlobalHandles::number_of_weak_handles_--; 116 GlobalHandles::number_of_weak_handles_--;
117 if (object_->IsJSGlobalObject()) {
118 GlobalHandles::number_of_global_object_weak_handles_--;
119 }
120 } 117 }
118 really_weak_ = false;
121 state_ = NORMAL; 119 state_ = NORMAL;
122 set_parameter(NULL); 120 set_parameter(NULL);
123 } 121 }
124 122
125 bool IsNearDeath() { 123 bool IsNearDeath() {
126 // Check for PENDING to ensure correct answer when processing callbacks. 124 // Check for PENDING to ensure correct answer when processing callbacks.
127 return state_ == PENDING || state_ == NEAR_DEATH; 125 return state_ == PENDING || state_ == NEAR_DEATH;
128 } 126 }
129 127
130 bool IsWeak() { 128 bool IsWeak() {
131 return state_ == WEAK; 129 return state_ == WEAK;
132 } 130 }
133 131
132 bool IsReallyWeak() {
133 return really_weak_;
134 }
135
134 // Returns the id for this weak handle. 136 // Returns the id for this weak handle.
135 void set_parameter(void* parameter) { 137 void set_parameter(void* parameter) {
136 ASSERT(state_ != DESTROYED); 138 ASSERT(state_ != DESTROYED);
137 parameter_or_next_free_.parameter = parameter; 139 parameter_or_next_free_.parameter = parameter;
138 } 140 }
139 void* parameter() { 141 void* parameter() {
140 ASSERT(state_ != DESTROYED); 142 ASSERT(state_ != DESTROYED);
141 return parameter_or_next_free_.parameter; 143 return parameter_or_next_free_.parameter;
142 } 144 }
143 145
(...skipping 20 matching lines...) Expand all
164 // Leaving V8. 166 // Leaving V8.
165 VMState state(EXTERNAL); 167 VMState state(EXTERNAL);
166 func(object, par); 168 func(object, par);
167 } 169 }
168 return true; 170 return true;
169 } 171 }
170 172
171 // Place the handle address first to avoid offset computation. 173 // Place the handle address first to avoid offset computation.
172 Object* object_; // Storage for object pointer. 174 Object* object_; // Storage for object pointer.
173 175
176 bool really_weak_ : 1;
177
174 // Transition diagram: 178 // Transition diagram:
175 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } 179 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
176 enum State { 180 enum State {
177 NORMAL, // Normal global handle. 181 NORMAL, // Normal global handle.
178 WEAK, // Flagged as weak but not yet finalized. 182 WEAK, // Flagged as weak but not yet finalized.
179 PENDING, // Has been recognized as only reachable by weak handles. 183 PENDING, // Has been recognized as only reachable by weak handles.
180 NEAR_DEATH, // Callback has informed the handle is near death. 184 NEAR_DEATH, // Callback has informed the handle is near death.
181 DESTROYED 185 DESTROYED
182 }; 186 };
183 State state_; 187 State state_ : 3;
184 188
185 private: 189 private:
186 // Handle specific callback. 190 // Handle specific callback.
187 WeakReferenceCallback callback_; 191 WeakReferenceCallback callback_;
188 // Provided data for callback. In DESTROYED state, this is used for 192 // Provided data for callback. In DESTROYED state, this is used for
189 // the free list link. 193 // the free list link.
190 union { 194 union {
191 void* parameter; 195 void* parameter;
192 Node* next_free; 196 Node* next_free;
193 } parameter_or_next_free_; 197 } parameter_or_next_free_;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 node->Destroy(); 229 node->Destroy();
226 // Link the destroyed. 230 // Link the destroyed.
227 node->set_next_free(first_free()); 231 node->set_next_free(first_free());
228 set_first_free(node); 232 set_first_free(node);
229 } 233 }
230 234
231 235
232 void GlobalHandles::MakeWeak(Object** location, void* parameter, 236 void GlobalHandles::MakeWeak(Object** location, void* parameter,
233 WeakReferenceCallback callback) { 237 WeakReferenceCallback callback) {
234 ASSERT(callback != NULL); 238 ASSERT(callback != NULL);
235 Node::FromLocation(location)->MakeWeak(parameter, callback); 239 Node::FromLocation(location)->MakeWeak(parameter, callback, false);
236 } 240 }
237 241
238 242
243 void GlobalHandles::MakeReallyWeak(Object** location, void* parameter,
244 WeakReferenceCallback callback) {
245 ASSERT(callback != NULL);
246 Node::FromLocation(location)->MakeWeak(parameter, callback, true);
247 }
248
249
239 void GlobalHandles::ClearWeakness(Object** location) { 250 void GlobalHandles::ClearWeakness(Object** location) {
240 Node::FromLocation(location)->ClearWeakness(); 251 Node::FromLocation(location)->ClearWeakness();
241 } 252 }
242 253
243 254
244 bool GlobalHandles::IsNearDeath(Object** location) { 255 bool GlobalHandles::IsNearDeath(Object** location) {
245 return Node::FromLocation(location)->IsNearDeath(); 256 return Node::FromLocation(location)->IsNearDeath();
246 } 257 }
247 258
248 259
249 bool GlobalHandles::IsWeak(Object** location) { 260 bool GlobalHandles::IsWeak(Object** location) {
250 return Node::FromLocation(location)->IsWeak(); 261 return Node::FromLocation(location)->IsWeak();
251 } 262 }
252 263
253 264
265 bool GlobalHandles::IsReallyWeak(Object** location) {
266 return Node::FromLocation(location)->IsReallyWeak();
267 }
268
269
254 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { 270 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
255 // Traversal of GC roots in the global handle list that are marked as 271 // Traversal of GC roots in the global handle list that are marked as
256 // WEAK or PENDING. 272 // WEAK or PENDING.
257 for (Node* current = head_; current != NULL; current = current->next()) { 273 for (Node* current = head_; current != NULL; current = current->next()) {
258 if (current->state_ == Node::WEAK 274 if (current->state_ == Node::WEAK ||
259 || current->state_ == Node::PENDING 275 (!current->really_weak_ &&
260 || current->state_ == Node::NEAR_DEATH) { 276 (current->state_ == Node::PENDING ||
277 current->state_ == Node::NEAR_DEATH))) {
261 v->VisitPointer(&current->object_); 278 v->VisitPointer(&current->object_);
262 } 279 }
263 } 280 }
264 } 281 }
265 282
266 283
267 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { 284 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
268 for (Node* current = head_; current != NULL; current = current->next()) { 285 for (Node* current = head_; current != NULL; current = current->next()) {
269 if (current->state_ == Node::WEAK) { 286 if (current->state_ == Node::WEAK) {
270 if (f(&current->object_)) { 287 if (f(&current->object_)) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 delete node; 320 delete node;
304 } else { 321 } else {
305 p = (*p)->next_addr(); 322 p = (*p)->next_addr();
306 } 323 }
307 } 324 }
308 set_first_free(NULL); 325 set_first_free(NULL);
309 } 326 }
310 327
311 328
312 void GlobalHandles::IterateRoots(ObjectVisitor* v) { 329 void GlobalHandles::IterateRoots(ObjectVisitor* v) {
313 // Traversal of global handles marked as NORMAL or NEAR_DEATH. 330 // Traversal of global handles marked as NORMAL.
314 for (Node* current = head_; current != NULL; current = current->next()) { 331 for (Node* current = head_; current != NULL; current = current->next()) {
315 if (current->state_ == Node::NORMAL) { 332 if (current->state_ == Node::NORMAL) {
316 v->VisitPointer(&current->object_); 333 v->VisitPointer(&current->object_);
317 } 334 }
318 } 335 }
319 } 336 }
320 337
321 void GlobalHandles::TearDown() { 338 void GlobalHandles::TearDown() {
322 // Delete all the nodes in the linked list. 339 // Delete all the nodes in the linked list.
323 Node* current = head_; 340 Node* current = head_;
324 while (current != NULL) { 341 while (current != NULL) {
325 Node* n = current; 342 Node* n = current;
326 current = current->next(); 343 current = current->next();
327 delete n; 344 delete n;
328 } 345 }
329 // Reset the head and free_list. 346 // Reset the head and free_list.
330 set_head(NULL); 347 set_head(NULL);
331 set_first_free(NULL); 348 set_first_free(NULL);
332 } 349 }
333 350
334 351
335 int GlobalHandles::number_of_weak_handles_ = 0; 352 int GlobalHandles::number_of_weak_handles_ = 0;
336 int GlobalHandles::number_of_global_object_weak_handles_ = 0;
337 353
338 GlobalHandles::Node* GlobalHandles::head_ = NULL; 354 GlobalHandles::Node* GlobalHandles::head_ = NULL;
339 GlobalHandles::Node* GlobalHandles::first_free_ = NULL; 355 GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
340 356
341 #ifdef DEBUG 357 #ifdef DEBUG
342 358
343 void GlobalHandles::PrintStats() { 359 void GlobalHandles::PrintStats() {
344 int total = 0; 360 int total = 0;
345 int weak = 0; 361 int weak = 0;
346 int pending = 0; 362 int pending = 0;
(...skipping 26 matching lines...) Expand all
373 } 389 }
374 390
375 #endif 391 #endif
376 392
377 List<ObjectGroup*>* GlobalHandles::ObjectGroups() { 393 List<ObjectGroup*>* GlobalHandles::ObjectGroups() {
378 // Lazily initialize the list to avoid startup time static constructors. 394 // Lazily initialize the list to avoid startup time static constructors.
379 static List<ObjectGroup*> groups(4); 395 static List<ObjectGroup*> groups(4);
380 return &groups; 396 return &groups;
381 } 397 }
382 398
399
383 void GlobalHandles::AddGroup(Object*** handles, size_t length) { 400 void GlobalHandles::AddGroup(Object*** handles, size_t length) {
384 ObjectGroup* new_entry = new ObjectGroup(length); 401 ObjectGroup* new_entry = new ObjectGroup(length);
385 for (size_t i = 0; i < length; ++i) 402 for (size_t i = 0; i < length; ++i)
386 new_entry->objects_.Add(handles[i]); 403 new_entry->objects_.Add(handles[i]);
387 ObjectGroups()->Add(new_entry); 404 ObjectGroups()->Add(new_entry);
388 } 405 }
389 406
390 407
391 void GlobalHandles::RemoveObjectGroups() { 408 void GlobalHandles::RemoveObjectGroups() {
392 List<ObjectGroup*>* object_groups = ObjectGroups(); 409 List<ObjectGroup*>* object_groups = ObjectGroups();
393 for (int i = 0; i< object_groups->length(); i++) { 410 for (int i = 0; i < object_groups->length(); ++i) {
Christian Plesner Hansen 2009/10/06 13:47:21 Changing from i++ to ++i shouldn't make any differ
394 delete object_groups->at(i); 411 delete object_groups->at(i);
395 } 412 }
396 object_groups->Clear(); 413 object_groups->Clear();
397 } 414 }
398 415
399 416
400 } } // namespace v8::internal 417 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698