| 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 parameter_or_next_free_.parameter = parameter; | 142 parameter_or_next_free_.parameter = parameter; |
| 143 } | 143 } |
| 144 void* parameter() { | 144 void* parameter() { |
| 145 ASSERT(state_ != DESTROYED); | 145 ASSERT(state_ != DESTROYED); |
| 146 return parameter_or_next_free_.parameter; | 146 return parameter_or_next_free_.parameter; |
| 147 } | 147 } |
| 148 | 148 |
| 149 // Returns the callback for this weak handle. | 149 // Returns the callback for this weak handle. |
| 150 WeakReferenceCallback callback() { return callback_; } | 150 WeakReferenceCallback callback() { return callback_; } |
| 151 | 151 |
| 152 bool PostGarbageCollectionProcessing(GlobalHandles* global_handles) { | 152 bool PostGarbageCollectionProcessing(Isolate* isolate, |
| 153 GlobalHandles* global_handles) { |
| 153 if (state_ != Node::PENDING) return false; | 154 if (state_ != Node::PENDING) return false; |
| 154 LOG(HandleEvent("GlobalHandle::Processing", handle().location())); | 155 LOG(HandleEvent("GlobalHandle::Processing", handle().location())); |
| 155 WeakReferenceCallback func = callback(); | 156 WeakReferenceCallback func = callback(); |
| 156 if (func == NULL) { | 157 if (func == NULL) { |
| 157 Destroy(global_handles); | 158 Destroy(global_handles); |
| 158 return false; | 159 return false; |
| 159 } | 160 } |
| 160 void* par = parameter(); | 161 void* par = parameter(); |
| 161 state_ = NEAR_DEATH; | 162 state_ = NEAR_DEATH; |
| 162 set_parameter(NULL); | 163 set_parameter(NULL); |
| 163 | 164 |
| 164 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 165 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
| 165 { | 166 { |
| 166 // Forbid reuse of destroyed nodes as they might be already deallocated. | 167 // Forbid reuse of destroyed nodes as they might be already deallocated. |
| 167 // It's fine though to reuse nodes that were destroyed in weak callback | 168 // It's fine though to reuse nodes that were destroyed in weak callback |
| 168 // as those cannot be deallocated until we are back from the callback. | 169 // as those cannot be deallocated until we are back from the callback. |
| 169 global_handles->set_first_free(NULL); | 170 global_handles->set_first_free(NULL); |
| 170 if (global_handles->first_deallocated()) { | 171 if (global_handles->first_deallocated()) { |
| 171 global_handles->first_deallocated()->set_next(global_handles->head()); | 172 global_handles->first_deallocated()->set_next(global_handles->head()); |
| 172 } | 173 } |
| 173 // Check that we are not passing a finalized external string to | 174 // Check that we are not passing a finalized external string to |
| 174 // the callback. | 175 // the callback. |
| 175 ASSERT(!object_->IsExternalAsciiString() || | 176 ASSERT(!object_->IsExternalAsciiString() || |
| 176 ExternalAsciiString::cast(object_)->resource() != NULL); | 177 ExternalAsciiString::cast(object_)->resource() != NULL); |
| 177 ASSERT(!object_->IsExternalTwoByteString() || | 178 ASSERT(!object_->IsExternalTwoByteString() || |
| 178 ExternalTwoByteString::cast(object_)->resource() != NULL); | 179 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 179 // Leaving V8. | 180 // Leaving V8. |
| 180 VMState state(EXTERNAL); | 181 VMState state(isolate, EXTERNAL); |
| 181 func(object, par); | 182 func(object, par); |
| 182 } | 183 } |
| 183 // Absense of explicit cleanup or revival of weak handle | 184 // Absense of explicit cleanup or revival of weak handle |
| 184 // in most of the cases would lead to memory leak. | 185 // in most of the cases would lead to memory leak. |
| 185 ASSERT(state_ != NEAR_DEATH); | 186 ASSERT(state_ != NEAR_DEATH); |
| 186 return true; | 187 return true; |
| 187 } | 188 } |
| 188 | 189 |
| 189 // Place the handle address first to avoid offset computation. | 190 // Place the handle address first to avoid offset computation. |
| 190 Object* object_; // Storage for object pointer. | 191 Object* object_; // Storage for object pointer. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 limit_ = new_nodes + kNodesPerChunk; | 270 limit_ = new_nodes + kNodesPerChunk; |
| 270 return new_nodes; | 271 return new_nodes; |
| 271 } | 272 } |
| 272 | 273 |
| 273 Chunk* current_; | 274 Chunk* current_; |
| 274 Node* next_; | 275 Node* next_; |
| 275 Node* limit_; | 276 Node* limit_; |
| 276 }; | 277 }; |
| 277 | 278 |
| 278 | 279 |
| 279 GlobalHandles::GlobalHandles() | 280 GlobalHandles::GlobalHandles(Isolate* isolate) |
| 280 : number_of_weak_handles_(0), | 281 : isolate_(isolate), |
| 282 number_of_weak_handles_(0), |
| 281 number_of_global_object_weak_handles_(0), | 283 number_of_global_object_weak_handles_(0), |
| 282 head_(NULL), | 284 head_(NULL), |
| 283 first_free_(NULL), | 285 first_free_(NULL), |
| 284 first_deallocated_(NULL), | 286 first_deallocated_(NULL), |
| 285 pool_(new Pool()), | 287 pool_(new Pool()), |
| 286 post_gc_processing_count_(0), | 288 post_gc_processing_count_(0), |
| 287 object_groups_(4) { | 289 object_groups_(4) { |
| 288 } | 290 } |
| 289 | 291 |
| 290 | 292 |
| 291 GlobalHandles::~GlobalHandles() { | 293 GlobalHandles::~GlobalHandles() { |
| 292 delete pool_; | 294 delete pool_; |
| 293 pool_ = 0; | 295 pool_ = 0; |
| 294 } | 296 } |
| 295 | 297 |
| 296 | 298 |
| 297 Handle<Object> GlobalHandles::Create(Object* value) { | 299 Handle<Object> GlobalHandles::Create(Object* value) { |
| 298 COUNTERS->global_handles()->Increment(); | 300 isolate_->counters()->global_handles()->Increment(); |
| 299 Node* result; | 301 Node* result; |
| 300 if (first_free()) { | 302 if (first_free()) { |
| 301 // Take the first node in the free list. | 303 // Take the first node in the free list. |
| 302 result = first_free(); | 304 result = first_free(); |
| 303 set_first_free(result->next_free()); | 305 set_first_free(result->next_free()); |
| 304 } else if (first_deallocated()) { | 306 } else if (first_deallocated()) { |
| 305 // Next try deallocated list | 307 // Next try deallocated list |
| 306 result = first_deallocated(); | 308 result = first_deallocated(); |
| 307 set_first_deallocated(result->next_free()); | 309 set_first_deallocated(result->next_free()); |
| 308 ASSERT(result->next() == head()); | 310 ASSERT(result->next() == head()); |
| 309 set_head(result); | 311 set_head(result); |
| 310 } else { | 312 } else { |
| 311 // Allocate a new node. | 313 // Allocate a new node. |
| 312 result = pool_->Allocate(); | 314 result = pool_->Allocate(); |
| 313 result->set_next(head()); | 315 result->set_next(head()); |
| 314 set_head(result); | 316 set_head(result); |
| 315 } | 317 } |
| 316 result->Initialize(value); | 318 result->Initialize(value); |
| 317 return result->handle(); | 319 return result->handle(); |
| 318 } | 320 } |
| 319 | 321 |
| 320 | 322 |
| 321 void GlobalHandles::Destroy(Object** location) { | 323 void GlobalHandles::Destroy(Object** location) { |
| 322 COUNTERS->global_handles()->Decrement(); | 324 isolate_->counters()->global_handles()->Decrement(); |
| 323 if (location == NULL) return; | 325 if (location == NULL) return; |
| 324 Node* node = Node::FromLocation(location); | 326 Node* node = Node::FromLocation(location); |
| 325 node->Destroy(this); | 327 node->Destroy(this); |
| 326 // Link the destroyed. | 328 // Link the destroyed. |
| 327 node->set_next_free(first_free()); | 329 node->set_next_free(first_free()); |
| 328 set_first_free(node); | 330 set_first_free(node); |
| 329 } | 331 } |
| 330 | 332 |
| 331 | 333 |
| 332 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 334 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 } | 386 } |
| 385 } | 387 } |
| 386 } | 388 } |
| 387 | 389 |
| 388 | 390 |
| 389 bool GlobalHandles::PostGarbageCollectionProcessing() { | 391 bool GlobalHandles::PostGarbageCollectionProcessing() { |
| 390 // Process weak global handle callbacks. This must be done after the | 392 // Process weak global handle callbacks. This must be done after the |
| 391 // GC is completely done, because the callbacks may invoke arbitrary | 393 // GC is completely done, because the callbacks may invoke arbitrary |
| 392 // API functions. | 394 // API functions. |
| 393 // At the same time deallocate all DESTROYED nodes. | 395 // At the same time deallocate all DESTROYED nodes. |
| 394 ASSERT(HEAP->gc_state() == Heap::NOT_IN_GC); | 396 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
| 395 const int initial_post_gc_processing_count = ++post_gc_processing_count_; | 397 const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
| 396 bool next_gc_likely_to_collect_more = false; | 398 bool next_gc_likely_to_collect_more = false; |
| 397 Node** p = &head_; | 399 Node** p = &head_; |
| 398 while (*p != NULL) { | 400 while (*p != NULL) { |
| 399 if ((*p)->PostGarbageCollectionProcessing(this)) { | 401 if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) { |
| 400 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 402 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
| 401 // Weak callback triggered another GC and another round of | 403 // Weak callback triggered another GC and another round of |
| 402 // PostGarbageCollection processing. The current node might | 404 // PostGarbageCollection processing. The current node might |
| 403 // have been deleted in that round, so we need to bail out (or | 405 // have been deleted in that round, so we need to bail out (or |
| 404 // restart the processing). | 406 // restart the processing). |
| 405 break; | 407 break; |
| 406 } | 408 } |
| 407 } | 409 } |
| 408 if ((*p)->state_ == Node::DESTROYED) { | 410 if ((*p)->state_ == Node::DESTROYED) { |
| 409 // Delete the link. | 411 // Delete the link. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 526 |
| 525 | 527 |
| 526 void GlobalHandles::RemoveObjectGroups() { | 528 void GlobalHandles::RemoveObjectGroups() { |
| 527 for (int i = 0; i< object_groups_.length(); i++) { | 529 for (int i = 0; i< object_groups_.length(); i++) { |
| 528 delete object_groups_.at(i); | 530 delete object_groups_.at(i); |
| 529 } | 531 } |
| 530 object_groups_.Clear(); | 532 object_groups_.Clear(); |
| 531 } | 533 } |
| 532 | 534 |
| 533 } } // namespace v8::internal | 535 } } // namespace v8::internal |
| OLD | NEW |