| 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 |