Chromium Code Reviews| 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 | |
| 149 bool IsNearDeath() const { | 156 bool IsNearDeath() const { |
| 150 // Check for PENDING to ensure correct answer when processing callbacks. | 157 // Check for PENDING to ensure correct answer when processing callbacks. |
| 151 return state() == PENDING || state() == NEAR_DEATH; | 158 return state() == PENDING || state() == NEAR_DEATH; |
| 152 } | 159 } |
| 153 | 160 |
| 154 bool IsWeak() const { return state() == WEAK; } | 161 bool IsWeak() const { return state() == WEAK; } |
| 155 | 162 |
| 156 bool IsRetainer() const { return state() != FREE; } | 163 bool IsRetainer() const { return state() != FREE; } |
| 157 | 164 |
| 158 bool IsStrongRetainer() const { return state() == NORMAL; } | 165 bool IsStrongRetainer() const { return state() == NORMAL; } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 // Accessors for next free node in the free list. | 204 // Accessors for next free node in the free list. |
| 198 Node* next_free() { | 205 Node* next_free() { |
| 199 DCHECK(state() == FREE); | 206 DCHECK(state() == FREE); |
| 200 return parameter_or_next_free_.next_free; | 207 return parameter_or_next_free_.next_free; |
| 201 } | 208 } |
| 202 void set_next_free(Node* value) { | 209 void set_next_free(Node* value) { |
| 203 DCHECK(state() == FREE); | 210 DCHECK(state() == FREE); |
| 204 parameter_or_next_free_.next_free = value; | 211 parameter_or_next_free_.next_free = value; |
| 205 } | 212 } |
| 206 | 213 |
| 207 void MakeWeak(void* parameter, WeakCallback weak_callback) { | 214 void MakeWeak(void* parameter, WeakCallback weak_callback, |
| 215 bool is_zapped_during_weak_callback = false) { | |
| 208 DCHECK(weak_callback != NULL); | 216 DCHECK(weak_callback != NULL); |
| 209 DCHECK(state() != FREE); | 217 DCHECK(state() != FREE); |
| 210 CHECK(object_ != NULL); | 218 CHECK(object_ != NULL); |
| 211 set_state(WEAK); | 219 set_state(WEAK); |
| 212 set_parameter(parameter); | 220 set_parameter(parameter); |
| 221 set_is_zapped_during_weak_callback(is_zapped_during_weak_callback); | |
| 213 weak_callback_ = weak_callback; | 222 weak_callback_ = weak_callback; |
| 214 } | 223 } |
| 215 | 224 |
| 216 void* ClearWeakness() { | 225 void* ClearWeakness() { |
| 217 DCHECK(state() != FREE); | 226 DCHECK(state() != FREE); |
| 218 void* p = parameter(); | 227 void* p = parameter(); |
| 219 set_state(NORMAL); | 228 set_state(NORMAL); |
| 220 set_parameter(NULL); | 229 set_parameter(NULL); |
| 221 return p; | 230 return p; |
| 222 } | 231 } |
| 223 | 232 |
| 224 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 233 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
| 225 if (state() != Node::PENDING) return false; | 234 if (state() != Node::PENDING) return false; |
| 226 if (weak_callback_ == NULL) { | 235 if (weak_callback_ == NULL) { |
| 227 Release(); | 236 Release(); |
| 228 return false; | 237 return false; |
| 229 } | 238 } |
| 230 void* par = parameter(); | 239 void* param = parameter(); |
| 231 set_state(NEAR_DEATH); | 240 set_state(NEAR_DEATH); |
| 232 set_parameter(NULL); | 241 set_parameter(NULL); |
| 233 | 242 |
| 234 Object** object = location(); | 243 Object** object = location(); |
| 235 { | 244 { |
| 236 // Check that we are not passing a finalized external string to | 245 // Check that we are not passing a finalized external string to |
| 237 // the callback. | 246 // the callback. |
| 238 DCHECK(!object_->IsExternalOneByteString() || | 247 DCHECK(!object_->IsExternalOneByteString() || |
| 239 ExternalOneByteString::cast(object_)->resource() != NULL); | 248 ExternalOneByteString::cast(object_)->resource() != NULL); |
| 240 DCHECK(!object_->IsExternalTwoByteString() || | 249 DCHECK(!object_->IsExternalTwoByteString() || |
| 241 ExternalTwoByteString::cast(object_)->resource() != NULL); | 250 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 242 // Leaving V8. | 251 // Leaving V8. |
| 243 VMState<EXTERNAL> state(isolate); | 252 VMState<EXTERNAL> state(isolate); |
| 244 HandleScope handle_scope(isolate); | 253 HandleScope handle_scope(isolate); |
| 245 Handle<Object> handle(*object, isolate); | 254 Handle<Object> handle(*object, isolate); |
| 255 if (is_zapped_during_weak_callback()) { | |
| 256 DCHECK(*handle == Smi::FromInt(kPhantomReferenceZap)); | |
|
jochen (gone - plz use gerrit)
2014/10/20 14:11:46
should we set handle to a null-handle here?
Erik Corry
2014/10/20 14:25:32
I think that's not so useful. The callback then d
jochen (gone - plz use gerrit)
2014/10/20 14:29:03
but the address of the handle is completely new, i
Erik Corry
2014/10/22 13:21:00
We could replace
Handle<Object> handle(*object, i
| |
| 257 } | |
| 246 v8::WeakCallbackData<v8::Value, void> data( | 258 v8::WeakCallbackData<v8::Value, void> data( |
| 247 reinterpret_cast<v8::Isolate*>(isolate), | 259 reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle), |
| 248 v8::Utils::ToLocal(handle), | 260 param); |
| 249 par); | |
| 250 weak_callback_(data); | 261 weak_callback_(data); |
| 251 } | 262 } |
| 252 // Absence of explicit cleanup or revival of weak handle | 263 // Absence of explicit cleanup or revival of weak handle |
| 253 // in most of the cases would lead to memory leak. | 264 // in most of the cases would lead to memory leak. |
| 254 CHECK(state() != NEAR_DEATH); | 265 CHECK(state() != NEAR_DEATH); |
| 255 return true; | 266 return true; |
| 256 } | 267 } |
| 257 | 268 |
| 258 inline GlobalHandles* GetGlobalHandles(); | 269 inline GlobalHandles* GetGlobalHandles(); |
| 259 | 270 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 270 // Note: the most aligned fields should go first. | 281 // Note: the most aligned fields should go first. |
| 271 | 282 |
| 272 // Wrapper class ID. | 283 // Wrapper class ID. |
| 273 uint16_t class_id_; | 284 uint16_t class_id_; |
| 274 | 285 |
| 275 // Index in the containing handle block. | 286 // Index in the containing handle block. |
| 276 uint8_t index_; | 287 uint8_t index_; |
| 277 | 288 |
| 278 // This stores three flags (independent, partially_dependent and | 289 // This stores three flags (independent, partially_dependent and |
| 279 // in_new_space_list) and a State. | 290 // in_new_space_list) and a State. |
| 280 class NodeState: public BitField<State, 0, 4> {}; | 291 class NodeState : public BitField<State, 0, 4> {}; |
| 281 class IsIndependent: public BitField<bool, 4, 1> {}; | 292 class IsIndependent : public BitField<bool, 4, 1> {}; |
| 282 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 293 class IsPartiallyDependent : public BitField<bool, 5, 1> {}; |
| 283 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 294 class IsInNewSpaceList : public BitField<bool, 6, 1> {}; |
| 295 class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {}; | |
| 284 | 296 |
| 285 uint8_t flags_; | 297 uint8_t flags_; |
| 286 | 298 |
| 287 // Handle specific callback - might be a weak reference in disguise. | 299 // Handle specific callback - might be a weak reference in disguise. |
| 288 WeakCallback weak_callback_; | 300 WeakCallback weak_callback_; |
| 289 | 301 |
| 290 // Provided data for callback. In FREE state, this is used for | 302 // Provided data for callback. In FREE state, this is used for |
| 291 // the free list link. | 303 // the free list link. |
| 292 union { | 304 union { |
| 293 void* parameter; | 305 void* parameter; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 DCHECK(location != NULL); | 480 DCHECK(location != NULL); |
| 469 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 481 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
| 470 } | 482 } |
| 471 | 483 |
| 472 | 484 |
| 473 void GlobalHandles::Destroy(Object** location) { | 485 void GlobalHandles::Destroy(Object** location) { |
| 474 if (location != NULL) Node::FromLocation(location)->Release(); | 486 if (location != NULL) Node::FromLocation(location)->Release(); |
| 475 } | 487 } |
| 476 | 488 |
| 477 | 489 |
| 478 void GlobalHandles::MakeWeak(Object** location, | 490 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| 479 void* parameter, | 491 WeakCallback weak_callback, PhantomState phantom) { |
| 480 WeakCallback weak_callback) { | 492 Node::FromLocation(location) |
| 481 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); | 493 ->MakeWeak(parameter, weak_callback, phantom == Phantom); |
| 482 } | 494 } |
| 483 | 495 |
| 484 | 496 |
| 485 void* GlobalHandles::ClearWeakness(Object** location) { | 497 void* GlobalHandles::ClearWeakness(Object** location) { |
| 486 return Node::FromLocation(location)->ClearWeakness(); | 498 return Node::FromLocation(location)->ClearWeakness(); |
| 487 } | 499 } |
| 488 | 500 |
| 489 | 501 |
| 490 void GlobalHandles::MarkIndependent(Object** location) { | 502 void GlobalHandles::MarkIndependent(Object** location) { |
| 491 Node::FromLocation(location)->MarkIndependent(); | 503 Node::FromLocation(location)->MarkIndependent(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 507 } | 519 } |
| 508 | 520 |
| 509 | 521 |
| 510 bool GlobalHandles::IsWeak(Object** location) { | 522 bool GlobalHandles::IsWeak(Object** location) { |
| 511 return Node::FromLocation(location)->IsWeak(); | 523 return Node::FromLocation(location)->IsWeak(); |
| 512 } | 524 } |
| 513 | 525 |
| 514 | 526 |
| 515 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 527 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| 516 for (NodeIterator it(this); !it.done(); it.Advance()) { | 528 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 517 if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location()); | 529 Node* node = it.node(); |
| 530 if (node->IsWeakRetainer()) { | |
| 531 if (node->state() == Node::PENDING && | |
| 532 node->is_zapped_during_weak_callback()) { | |
| 533 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | |
| 534 } else { | |
| 535 v->VisitPointer(node->location()); | |
| 536 } | |
| 537 } | |
| 518 } | 538 } |
| 519 } | 539 } |
| 520 | 540 |
| 521 | 541 |
| 522 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 542 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
| 523 for (NodeIterator it(this); !it.done(); it.Advance()) { | 543 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 524 if (it.node()->IsWeak() && f(it.node()->location())) { | 544 if (it.node()->IsWeak() && f(it.node()->location())) { |
| 525 it.node()->MarkPending(); | 545 it.node()->MarkPending(); |
| 526 } | 546 } |
| 527 } | 547 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 552 } | 572 } |
| 553 } | 573 } |
| 554 | 574 |
| 555 | 575 |
| 556 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 576 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
| 557 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 577 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 558 Node* node = new_space_nodes_[i]; | 578 Node* node = new_space_nodes_[i]; |
| 559 DCHECK(node->is_in_new_space_list()); | 579 DCHECK(node->is_in_new_space_list()); |
| 560 if ((node->is_independent() || node->is_partially_dependent()) && | 580 if ((node->is_independent() || node->is_partially_dependent()) && |
| 561 node->IsWeakRetainer()) { | 581 node->IsWeakRetainer()) { |
| 562 v->VisitPointer(node->location()); | 582 if (node->is_zapped_during_weak_callback()) { |
| 583 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); | |
| 584 } else { | |
| 585 v->VisitPointer(node->location()); | |
| 586 } | |
| 563 } | 587 } |
| 564 } | 588 } |
| 565 } | 589 } |
| 566 | 590 |
| 567 | 591 |
| 568 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 592 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| 569 WeakSlotCallbackWithHeap can_skip) { | 593 WeakSlotCallbackWithHeap can_skip) { |
| 570 ComputeObjectGroupsAndImplicitReferences(); | 594 ComputeObjectGroupsAndImplicitReferences(); |
| 571 int last = 0; | 595 int last = 0; |
| 572 bool any_group_was_visited = false; | 596 bool any_group_was_visited = false; |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1071 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
| 1048 blocks_[block][offset] = object; | 1072 blocks_[block][offset] = object; |
| 1049 if (isolate->heap()->InNewSpace(object)) { | 1073 if (isolate->heap()->InNewSpace(object)) { |
| 1050 new_space_indices_.Add(size_); | 1074 new_space_indices_.Add(size_); |
| 1051 } | 1075 } |
| 1052 *index = size_++; | 1076 *index = size_++; |
| 1053 } | 1077 } |
| 1054 | 1078 |
| 1055 | 1079 |
| 1056 } } // namespace v8::internal | 1080 } } // namespace v8::internal |
| OLD | NEW |