| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/global-handles.h" | 8 #include "src/global-handles.h" |
| 9 | 9 |
| 10 #include "src/vm-state-inl.h" | 10 #include "src/vm-state-inl.h" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 flags_ = IsPartiallyDependent::update(flags_, v); | 139 flags_ = IsPartiallyDependent::update(flags_, v); |
| 140 } | 140 } |
| 141 | 141 |
| 142 bool is_in_new_space_list() { | 142 bool is_in_new_space_list() { |
| 143 return IsInNewSpaceList::decode(flags_); | 143 return IsInNewSpaceList::decode(flags_); |
| 144 } | 144 } |
| 145 void set_in_new_space_list(bool v) { | 145 void set_in_new_space_list(bool v) { |
| 146 flags_ = IsInNewSpaceList::update(flags_, v); | 146 flags_ = IsInNewSpaceList::update(flags_, v); |
| 147 } | 147 } |
| 148 | 148 |
| 149 bool is_zapped_during_weak_callback() { | |
| 150 return IsZappedDuringWeakCallback::decode(flags_); | |
| 151 } | |
| 152 void set_is_zapped_during_weak_callback(bool v) { | |
| 153 flags_ = IsZappedDuringWeakCallback::update(flags_, v); | |
| 154 } | |
| 155 | |
| 156 bool IsNearDeath() const { | 149 bool IsNearDeath() const { |
| 157 // Check for PENDING to ensure correct answer when processing callbacks. | 150 // Check for PENDING to ensure correct answer when processing callbacks. |
| 158 return state() == PENDING || state() == NEAR_DEATH; | 151 return state() == PENDING || state() == NEAR_DEATH; |
| 159 } | 152 } |
| 160 | 153 |
| 161 bool IsWeak() const { return state() == WEAK; } | 154 bool IsWeak() const { return state() == WEAK; } |
| 162 | 155 |
| 163 bool IsRetainer() const { return state() != FREE; } | 156 bool IsRetainer() const { return state() != FREE; } |
| 164 | 157 |
| 165 bool IsStrongRetainer() const { return state() == NORMAL; } | 158 bool IsStrongRetainer() const { return state() == NORMAL; } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // Accessors for next free node in the free list. | 197 // Accessors for next free node in the free list. |
| 205 Node* next_free() { | 198 Node* next_free() { |
| 206 DCHECK(state() == FREE); | 199 DCHECK(state() == FREE); |
| 207 return parameter_or_next_free_.next_free; | 200 return parameter_or_next_free_.next_free; |
| 208 } | 201 } |
| 209 void set_next_free(Node* value) { | 202 void set_next_free(Node* value) { |
| 210 DCHECK(state() == FREE); | 203 DCHECK(state() == FREE); |
| 211 parameter_or_next_free_.next_free = value; | 204 parameter_or_next_free_.next_free = value; |
| 212 } | 205 } |
| 213 | 206 |
| 214 void MakeWeak(void* parameter, WeakCallback weak_callback, | 207 void MakeWeak(void* parameter, WeakCallback weak_callback) { |
| 215 bool is_zapped_during_weak_callback = false) { | |
| 216 DCHECK(weak_callback != NULL); | 208 DCHECK(weak_callback != NULL); |
| 217 DCHECK(state() != FREE); | 209 DCHECK(state() != FREE); |
| 218 CHECK(object_ != NULL); | 210 CHECK(object_ != NULL); |
| 219 set_state(WEAK); | 211 set_state(WEAK); |
| 220 set_parameter(parameter); | 212 set_parameter(parameter); |
| 221 set_is_zapped_during_weak_callback(is_zapped_during_weak_callback); | |
| 222 weak_callback_ = weak_callback; | 213 weak_callback_ = weak_callback; |
| 223 } | 214 } |
| 224 | 215 |
| 225 void* ClearWeakness() { | 216 void* ClearWeakness() { |
| 226 DCHECK(state() != FREE); | 217 DCHECK(state() != FREE); |
| 227 void* p = parameter(); | 218 void* p = parameter(); |
| 228 set_state(NORMAL); | 219 set_state(NORMAL); |
| 229 set_parameter(NULL); | 220 set_parameter(NULL); |
| 230 return p; | 221 return p; |
| 231 } | 222 } |
| 232 | 223 |
| 233 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 224 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
| 234 if (state() != Node::PENDING) return false; | 225 if (state() != Node::PENDING) return false; |
| 235 if (weak_callback_ == NULL) { | 226 if (weak_callback_ == NULL) { |
| 236 Release(); | 227 Release(); |
| 237 return false; | 228 return false; |
| 238 } | 229 } |
| 239 void* param = parameter(); | 230 void* par = parameter(); |
| 240 set_state(NEAR_DEATH); | 231 set_state(NEAR_DEATH); |
| 241 set_parameter(NULL); | 232 set_parameter(NULL); |
| 242 | 233 |
| 243 Object** object = location(); | 234 Object** object = location(); |
| 244 { | 235 { |
| 245 // Check that we are not passing a finalized external string to | 236 // Check that we are not passing a finalized external string to |
| 246 // the callback. | 237 // the callback. |
| 247 DCHECK(!object_->IsExternalOneByteString() || | 238 DCHECK(!object_->IsExternalOneByteString() || |
| 248 ExternalOneByteString::cast(object_)->resource() != NULL); | 239 ExternalOneByteString::cast(object_)->resource() != NULL); |
| 249 DCHECK(!object_->IsExternalTwoByteString() || | 240 DCHECK(!object_->IsExternalTwoByteString() || |
| 250 ExternalTwoByteString::cast(object_)->resource() != NULL); | 241 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 251 // Leaving V8. | 242 // Leaving V8. |
| 252 VMState<EXTERNAL> vmstate(isolate); | 243 VMState<EXTERNAL> state(isolate); |
| 253 HandleScope handle_scope(isolate); | 244 HandleScope handle_scope(isolate); |
| 254 if (is_zapped_during_weak_callback()) { | 245 Handle<Object> handle(*object, isolate); |
| 255 // Phantom weak pointer case. | 246 v8::WeakCallbackData<v8::Value, void> data( |
| 256 DCHECK(*object == Smi::FromInt(kPhantomReferenceZap)); | 247 reinterpret_cast<v8::Isolate*>(isolate), |
| 257 // Make data with a null handle. | 248 v8::Utils::ToLocal(handle), |
| 258 v8::WeakCallbackData<v8::Value, void> data( | 249 par); |
| 259 reinterpret_cast<v8::Isolate*>(isolate), v8::Local<v8::Object>(), | 250 weak_callback_(data); |
| 260 param); | |
| 261 weak_callback_(data); | |
| 262 if (state() != FREE) { | |
| 263 // Callback does not have to clear the global handle if it is a | |
| 264 // phantom handle. | |
| 265 Release(); | |
| 266 } | |
| 267 } else { | |
| 268 Handle<Object> handle(object); | |
| 269 v8::WeakCallbackData<v8::Value, void> data( | |
| 270 reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle), | |
| 271 param); | |
| 272 weak_callback_(data); | |
| 273 } | |
| 274 } | 251 } |
| 275 // Absence of explicit cleanup or revival of weak handle | 252 // Absence of explicit cleanup or revival of weak handle |
| 276 // in most of the cases would lead to memory leak. | 253 // in most of the cases would lead to memory leak. |
| 277 CHECK(state() != NEAR_DEATH); | 254 CHECK(state() != NEAR_DEATH); |
| 278 return true; | 255 return true; |
| 279 } | 256 } |
| 280 | 257 |
| 281 inline GlobalHandles* GetGlobalHandles(); | 258 inline GlobalHandles* GetGlobalHandles(); |
| 282 | 259 |
| 283 private: | 260 private: |
| 284 inline NodeBlock* FindBlock(); | 261 inline NodeBlock* FindBlock(); |
| 285 inline void IncreaseBlockUses(); | 262 inline void IncreaseBlockUses(); |
| 286 inline void DecreaseBlockUses(); | 263 inline void DecreaseBlockUses(); |
| 287 | 264 |
| 288 // Storage for object pointer. | 265 // Storage for object pointer. |
| 289 // Placed first to avoid offset computation. | 266 // Placed first to avoid offset computation. |
| 290 Object* object_; | 267 Object* object_; |
| 291 | 268 |
| 292 // Next word stores class_id, index, state, and independent. | 269 // Next word stores class_id, index, state, and independent. |
| 293 // Note: the most aligned fields should go first. | 270 // Note: the most aligned fields should go first. |
| 294 | 271 |
| 295 // Wrapper class ID. | 272 // Wrapper class ID. |
| 296 uint16_t class_id_; | 273 uint16_t class_id_; |
| 297 | 274 |
| 298 // Index in the containing handle block. | 275 // Index in the containing handle block. |
| 299 uint8_t index_; | 276 uint8_t index_; |
| 300 | 277 |
| 301 // This stores three flags (independent, partially_dependent and | 278 // This stores three flags (independent, partially_dependent and |
| 302 // in_new_space_list) and a State. | 279 // in_new_space_list) and a State. |
| 303 class NodeState : public BitField<State, 0, 4> {}; | 280 class NodeState: public BitField<State, 0, 4> {}; |
| 304 class IsIndependent : public BitField<bool, 4, 1> {}; | 281 class IsIndependent: public BitField<bool, 4, 1> {}; |
| 305 class IsPartiallyDependent : public BitField<bool, 5, 1> {}; | 282 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
| 306 class IsInNewSpaceList : public BitField<bool, 6, 1> {}; | 283 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
| 307 class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {}; | |
| 308 | 284 |
| 309 uint8_t flags_; | 285 uint8_t flags_; |
| 310 | 286 |
| 311 // Handle specific callback - might be a weak reference in disguise. | 287 // Handle specific callback - might be a weak reference in disguise. |
| 312 WeakCallback weak_callback_; | 288 WeakCallback weak_callback_; |
| 313 | 289 |
| 314 // Provided data for callback. In FREE state, this is used for | 290 // Provided data for callback. In FREE state, this is used for |
| 315 // the free list link. | 291 // the free list link. |
| 316 union { | 292 union { |
| 317 void* parameter; | 293 void* parameter; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 DCHECK(location != NULL); | 468 DCHECK(location != NULL); |
| 493 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 469 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
| 494 } | 470 } |
| 495 | 471 |
| 496 | 472 |
| 497 void GlobalHandles::Destroy(Object** location) { | 473 void GlobalHandles::Destroy(Object** location) { |
| 498 if (location != NULL) Node::FromLocation(location)->Release(); | 474 if (location != NULL) Node::FromLocation(location)->Release(); |
| 499 } | 475 } |
| 500 | 476 |
| 501 | 477 |
| 502 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 478 void GlobalHandles::MakeWeak(Object** location, |
| 503 WeakCallback weak_callback, PhantomState phantom) { | 479 void* parameter, |
| 504 Node::FromLocation(location) | 480 WeakCallback weak_callback) { |
| 505 ->MakeWeak(parameter, weak_callback, phantom == Phantom); | 481 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); |
| 506 } | 482 } |
| 507 | 483 |
| 508 | 484 |
| 509 void* GlobalHandles::ClearWeakness(Object** location) { | 485 void* GlobalHandles::ClearWeakness(Object** location) { |
| 510 return Node::FromLocation(location)->ClearWeakness(); | 486 return Node::FromLocation(location)->ClearWeakness(); |
| 511 } | 487 } |
| 512 | 488 |
| 513 | 489 |
| 514 void GlobalHandles::MarkIndependent(Object** location) { | 490 void GlobalHandles::MarkIndependent(Object** location) { |
| 515 Node::FromLocation(location)->MarkIndependent(); | 491 Node::FromLocation(location)->MarkIndependent(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 531 } | 507 } |
| 532 | 508 |
| 533 | 509 |
| 534 bool GlobalHandles::IsWeak(Object** location) { | 510 bool GlobalHandles::IsWeak(Object** location) { |
| 535 return Node::FromLocation(location)->IsWeak(); | 511 return Node::FromLocation(location)->IsWeak(); |
| 536 } | 512 } |
| 537 | 513 |
| 538 | 514 |
| 539 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 515 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| 540 for (NodeIterator it(this); !it.done(); it.Advance()) { | 516 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 541 Node* node = it.node(); | 517 if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location()); |
| 542 if (node->IsWeakRetainer()) { | |
| 543 if (node->state() == Node::PENDING && | |
| 544 node->is_zapped_during_weak_callback()) { | |
| 545 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | |
| 546 } else { | |
| 547 v->VisitPointer(node->location()); | |
| 548 } | |
| 549 } | |
| 550 } | 518 } |
| 551 } | 519 } |
| 552 | 520 |
| 553 | 521 |
| 554 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 522 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
| 555 for (NodeIterator it(this); !it.done(); it.Advance()) { | 523 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 556 if (it.node()->IsWeak() && f(it.node()->location())) { | 524 if (it.node()->IsWeak() && f(it.node()->location())) { |
| 557 it.node()->MarkPending(); | 525 it.node()->MarkPending(); |
| 558 } | 526 } |
| 559 } | 527 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 584 } | 552 } |
| 585 } | 553 } |
| 586 | 554 |
| 587 | 555 |
| 588 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 556 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
| 589 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 557 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 590 Node* node = new_space_nodes_[i]; | 558 Node* node = new_space_nodes_[i]; |
| 591 DCHECK(node->is_in_new_space_list()); | 559 DCHECK(node->is_in_new_space_list()); |
| 592 if ((node->is_independent() || node->is_partially_dependent()) && | 560 if ((node->is_independent() || node->is_partially_dependent()) && |
| 593 node->IsWeakRetainer()) { | 561 node->IsWeakRetainer()) { |
| 594 if (node->is_zapped_during_weak_callback()) { | 562 v->VisitPointer(node->location()); |
| 595 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | |
| 596 } else { | |
| 597 v->VisitPointer(node->location()); | |
| 598 } | |
| 599 } | 563 } |
| 600 } | 564 } |
| 601 } | 565 } |
| 602 | 566 |
| 603 | 567 |
| 604 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 568 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| 605 WeakSlotCallbackWithHeap can_skip) { | 569 WeakSlotCallbackWithHeap can_skip) { |
| 606 ComputeObjectGroupsAndImplicitReferences(); | 570 ComputeObjectGroupsAndImplicitReferences(); |
| 607 int last = 0; | 571 int last = 0; |
| 608 bool any_group_was_visited = false; | 572 bool any_group_was_visited = false; |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1047 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
| 1084 blocks_[block][offset] = object; | 1048 blocks_[block][offset] = object; |
| 1085 if (isolate->heap()->InNewSpace(object)) { | 1049 if (isolate->heap()->InNewSpace(object)) { |
| 1086 new_space_indices_.Add(size_); | 1050 new_space_indices_.Add(size_); |
| 1087 } | 1051 } |
| 1088 *index = size_++; | 1052 *index = size_++; |
| 1089 } | 1053 } |
| 1090 | 1054 |
| 1091 | 1055 |
| 1092 } } // namespace v8::internal | 1056 } } // namespace v8::internal |
| OLD | NEW |