OLD | NEW |
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 26 matching lines...) Expand all Loading... |
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 state_ = NORMAL; | 42 state_ = NORMAL; |
43 parameter_or_next_free_.parameter = NULL; | 43 parameter_or_next_free_.parameter = NULL; |
44 callback_ = NULL; | 44 callback_ = NULL; |
45 } | 45 } |
46 | 46 |
| 47 Node() { |
| 48 state_ = DESTROYED; |
| 49 } |
| 50 |
47 explicit Node(Object* object) { | 51 explicit Node(Object* object) { |
48 Initialize(object); | 52 Initialize(object); |
49 // Initialize link structure. | 53 // Initialize link structure. |
50 next_ = NULL; | 54 next_ = NULL; |
51 } | 55 } |
52 | 56 |
53 ~Node() { | 57 ~Node() { |
54 if (state_ != DESTROYED) Destroy(); | 58 if (state_ != DESTROYED) Destroy(); |
55 #ifdef DEBUG | 59 #ifdef DEBUG |
56 // Zap the values for eager trapping. | 60 // Zap the values for eager trapping. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } parameter_or_next_free_; | 197 } parameter_or_next_free_; |
194 | 198 |
195 // Linkage for the list. | 199 // Linkage for the list. |
196 Node* next_; | 200 Node* next_; |
197 | 201 |
198 public: | 202 public: |
199 TRACK_MEMORY("GlobalHandles::Node") | 203 TRACK_MEMORY("GlobalHandles::Node") |
200 }; | 204 }; |
201 | 205 |
202 | 206 |
| 207 class GlobalHandles::Pool BASE_EMBEDDED { |
| 208 public: |
| 209 Pool() { |
| 210 current_ = new Chunk(); |
| 211 current_->previous = NULL; |
| 212 next_ = current_->nodes; |
| 213 limit_ = current_->nodes + kNodesPerChunk; |
| 214 } |
| 215 |
| 216 Node* Allocate() { |
| 217 if (next_ < limit_) { |
| 218 return next_++; |
| 219 } |
| 220 return SlowAllocate(); |
| 221 } |
| 222 |
| 223 void Release() { |
| 224 Chunk* current = current_; |
| 225 ASSERT(current != NULL); // At least a single block must by allocated |
| 226 do { |
| 227 Chunk* previous = current->previous; |
| 228 delete current; |
| 229 current = previous; |
| 230 } while (current != NULL); |
| 231 current_ = NULL; |
| 232 next_ = limit_ = NULL; |
| 233 } |
| 234 |
| 235 private: |
| 236 static const int kNodesPerChunk = (1 << 13) - 1; |
| 237 struct Chunk : public Malloced { |
| 238 Chunk* previous; |
| 239 Node nodes[kNodesPerChunk]; |
| 240 }; |
| 241 |
| 242 Node* SlowAllocate() { |
| 243 Chunk* chunk = new Chunk(); |
| 244 chunk->previous = current_; |
| 245 current_ = chunk; |
| 246 |
| 247 Node* new_nodes = current_->nodes; |
| 248 next_ = new_nodes + 1; |
| 249 limit_ = new_nodes + kNodesPerChunk; |
| 250 return new_nodes; |
| 251 } |
| 252 |
| 253 Chunk* current_; |
| 254 Node* next_; |
| 255 Node* limit_; |
| 256 }; |
| 257 |
| 258 |
| 259 static GlobalHandles::Pool pool_; |
| 260 |
| 261 |
203 Handle<Object> GlobalHandles::Create(Object* value) { | 262 Handle<Object> GlobalHandles::Create(Object* value) { |
204 Counters::global_handles.Increment(); | 263 Counters::global_handles.Increment(); |
205 Node* result; | 264 Node* result; |
206 if (first_free() == NULL) { | 265 if (first_free()) { |
207 // Allocate a new node. | |
208 result = new Node(value); | |
209 result->set_next(head()); | |
210 set_head(result); | |
211 } else { | |
212 // Take the first node in the free list. | 266 // Take the first node in the free list. |
213 result = first_free(); | 267 result = first_free(); |
214 set_first_free(result->next_free()); | 268 set_first_free(result->next_free()); |
215 result->Initialize(value); | 269 } else if (first_deallocated()) { |
| 270 // Next try deallocated list |
| 271 result = first_deallocated(); |
| 272 set_first_deallocated(result->next_free()); |
| 273 set_head(result); |
| 274 } else { |
| 275 // Allocate a new node. |
| 276 result = pool_.Allocate(); |
| 277 result->set_next(head()); |
| 278 set_head(result); |
216 } | 279 } |
| 280 result->Initialize(value); |
217 return result->handle(); | 281 return result->handle(); |
218 } | 282 } |
219 | 283 |
220 | 284 |
221 void GlobalHandles::Destroy(Object** location) { | 285 void GlobalHandles::Destroy(Object** location) { |
222 Counters::global_handles.Decrement(); | 286 Counters::global_handles.Decrement(); |
223 if (location == NULL) return; | 287 if (location == NULL) return; |
224 Node* node = Node::FromLocation(location); | 288 Node* node = Node::FromLocation(location); |
225 node->Destroy(); | 289 node->Destroy(); |
226 // Link the destroyed. | 290 // Link the destroyed. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 } | 349 } |
286 } | 350 } |
287 | 351 |
288 | 352 |
289 int post_gc_processing_count = 0; | 353 int post_gc_processing_count = 0; |
290 | 354 |
291 void GlobalHandles::PostGarbageCollectionProcessing() { | 355 void GlobalHandles::PostGarbageCollectionProcessing() { |
292 // Process weak global handle callbacks. This must be done after the | 356 // Process weak global handle callbacks. This must be done after the |
293 // GC is completely done, because the callbacks may invoke arbitrary | 357 // GC is completely done, because the callbacks may invoke arbitrary |
294 // API functions. | 358 // API functions. |
295 // At the same time deallocate all DESTROYED nodes | 359 // At the same time deallocate all DESTROYED nodes. |
296 ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); | 360 ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); |
297 const int initial_post_gc_processing_count = ++post_gc_processing_count; | 361 const int initial_post_gc_processing_count = ++post_gc_processing_count; |
298 Node** p = &head_; | 362 Node** p = &head_; |
299 while (*p != NULL) { | 363 while (*p != NULL) { |
300 if ((*p)->PostGarbageCollectionProcessing()) { | 364 if ((*p)->PostGarbageCollectionProcessing()) { |
301 if (initial_post_gc_processing_count != post_gc_processing_count) { | 365 if (initial_post_gc_processing_count != post_gc_processing_count) { |
302 // Weak callback triggered another GC and another round of | 366 // Weak callback triggered another GC and another round of |
303 // PostGarbageCollection processing. The current node might | 367 // PostGarbageCollection processing. The current node might |
304 // have been deleted in that round, so we need to bail out (or | 368 // have been deleted in that round, so we need to bail out (or |
305 // restart the processing). | 369 // restart the processing). |
306 break; | 370 break; |
307 } | 371 } |
308 } | 372 } |
309 if ((*p)->state_ == Node::DESTROYED) { | 373 if ((*p)->state_ == Node::DESTROYED) { |
310 // Delete the link. | 374 // Delete the link. |
311 Node* node = *p; | 375 Node* node = *p; |
312 *p = node->next(); // Update the link. | 376 *p = node->next(); // Update the link. |
313 delete node; | 377 if (first_deallocated()) { |
| 378 first_deallocated()->set_next(node); |
| 379 } |
| 380 node->set_next_free(first_deallocated()); |
| 381 set_first_deallocated(node); |
314 } else { | 382 } else { |
315 p = (*p)->next_addr(); | 383 p = (*p)->next_addr(); |
316 } | 384 } |
317 } | 385 } |
318 set_first_free(NULL); | 386 set_first_free(NULL); |
| 387 if (first_deallocated()) { |
| 388 first_deallocated()->set_next(head()); |
| 389 } |
319 } | 390 } |
320 | 391 |
321 | 392 |
322 void GlobalHandles::IterateRoots(ObjectVisitor* v) { | 393 void GlobalHandles::IterateRoots(ObjectVisitor* v) { |
323 // Traversal of global handles marked as NORMAL or NEAR_DEATH. | 394 // Traversal of global handles marked as NORMAL or NEAR_DEATH. |
324 for (Node* current = head_; current != NULL; current = current->next()) { | 395 for (Node* current = head_; current != NULL; current = current->next()) { |
325 if (current->state_ == Node::NORMAL) { | 396 if (current->state_ == Node::NORMAL) { |
326 v->VisitPointer(¤t->object_); | 397 v->VisitPointer(¤t->object_); |
327 } | 398 } |
328 } | 399 } |
329 } | 400 } |
330 | 401 |
331 void GlobalHandles::TearDown() { | 402 void GlobalHandles::TearDown() { |
332 // Delete all the nodes in the linked list. | 403 // Reset all the lists. |
333 Node* current = head_; | |
334 while (current != NULL) { | |
335 Node* n = current; | |
336 current = current->next(); | |
337 delete n; | |
338 } | |
339 // Reset the head and free_list. | |
340 set_head(NULL); | 404 set_head(NULL); |
341 set_first_free(NULL); | 405 set_first_free(NULL); |
| 406 set_first_deallocated(NULL); |
| 407 pool_.Release(); |
342 } | 408 } |
343 | 409 |
344 | 410 |
345 int GlobalHandles::number_of_weak_handles_ = 0; | 411 int GlobalHandles::number_of_weak_handles_ = 0; |
346 int GlobalHandles::number_of_global_object_weak_handles_ = 0; | 412 int GlobalHandles::number_of_global_object_weak_handles_ = 0; |
347 | 413 |
348 GlobalHandles::Node* GlobalHandles::head_ = NULL; | 414 GlobalHandles::Node* GlobalHandles::head_ = NULL; |
349 GlobalHandles::Node* GlobalHandles::first_free_ = NULL; | 415 GlobalHandles::Node* GlobalHandles::first_free_ = NULL; |
| 416 GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL; |
350 | 417 |
351 #ifdef DEBUG | 418 #ifdef DEBUG |
352 | 419 |
353 void GlobalHandles::PrintStats() { | 420 void GlobalHandles::PrintStats() { |
354 int total = 0; | 421 int total = 0; |
355 int weak = 0; | 422 int weak = 0; |
356 int pending = 0; | 423 int pending = 0; |
357 int near_death = 0; | 424 int near_death = 0; |
358 int destroyed = 0; | 425 int destroyed = 0; |
359 | 426 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 void GlobalHandles::RemoveObjectGroups() { | 468 void GlobalHandles::RemoveObjectGroups() { |
402 List<ObjectGroup*>* object_groups = ObjectGroups(); | 469 List<ObjectGroup*>* object_groups = ObjectGroups(); |
403 for (int i = 0; i< object_groups->length(); i++) { | 470 for (int i = 0; i< object_groups->length(); i++) { |
404 delete object_groups->at(i); | 471 delete object_groups->at(i); |
405 } | 472 } |
406 object_groups->Clear(); | 473 object_groups->Clear(); |
407 } | 474 } |
408 | 475 |
409 | 476 |
410 } } // namespace v8::internal | 477 } } // namespace v8::internal |
OLD | NEW |