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> vmstate(isolate); |
244 HandleScope handle_scope(isolate); | 253 HandleScope handle_scope(isolate); |
245 Handle<Object> handle(*object, isolate); | 254 if (is_zapped_during_weak_callback()) { |
246 v8::WeakCallbackData<v8::Value, void> data( | 255 // Phantom weak pointer case. |
247 reinterpret_cast<v8::Isolate*>(isolate), | 256 DCHECK(*object == Smi::FromInt(kPhantomReferenceZap)); |
248 v8::Utils::ToLocal(handle), | 257 // Make data with a null handle. |
249 par); | 258 v8::WeakCallbackData<v8::Value, void> data( |
250 weak_callback_(data); | 259 reinterpret_cast<v8::Isolate*>(isolate), v8::Local<v8::Object>(), |
| 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 } |
251 } | 274 } |
252 // Absence of explicit cleanup or revival of weak handle | 275 // Absence of explicit cleanup or revival of weak handle |
253 // in most of the cases would lead to memory leak. | 276 // in most of the cases would lead to memory leak. |
254 CHECK(state() != NEAR_DEATH); | 277 CHECK(state() != NEAR_DEATH); |
255 return true; | 278 return true; |
256 } | 279 } |
257 | 280 |
258 inline GlobalHandles* GetGlobalHandles(); | 281 inline GlobalHandles* GetGlobalHandles(); |
259 | 282 |
260 private: | 283 private: |
261 inline NodeBlock* FindBlock(); | 284 inline NodeBlock* FindBlock(); |
262 inline void IncreaseBlockUses(); | 285 inline void IncreaseBlockUses(); |
263 inline void DecreaseBlockUses(); | 286 inline void DecreaseBlockUses(); |
264 | 287 |
265 // Storage for object pointer. | 288 // Storage for object pointer. |
266 // Placed first to avoid offset computation. | 289 // Placed first to avoid offset computation. |
267 Object* object_; | 290 Object* object_; |
268 | 291 |
269 // Next word stores class_id, index, state, and independent. | 292 // Next word stores class_id, index, state, and independent. |
270 // Note: the most aligned fields should go first. | 293 // Note: the most aligned fields should go first. |
271 | 294 |
272 // Wrapper class ID. | 295 // Wrapper class ID. |
273 uint16_t class_id_; | 296 uint16_t class_id_; |
274 | 297 |
275 // Index in the containing handle block. | 298 // Index in the containing handle block. |
276 uint8_t index_; | 299 uint8_t index_; |
277 | 300 |
278 // This stores three flags (independent, partially_dependent and | 301 // This stores three flags (independent, partially_dependent and |
279 // in_new_space_list) and a State. | 302 // in_new_space_list) and a State. |
280 class NodeState: public BitField<State, 0, 4> {}; | 303 class NodeState : public BitField<State, 0, 4> {}; |
281 class IsIndependent: public BitField<bool, 4, 1> {}; | 304 class IsIndependent : public BitField<bool, 4, 1> {}; |
282 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 305 class IsPartiallyDependent : public BitField<bool, 5, 1> {}; |
283 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 306 class IsInNewSpaceList : public BitField<bool, 6, 1> {}; |
| 307 class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {}; |
284 | 308 |
285 uint8_t flags_; | 309 uint8_t flags_; |
286 | 310 |
287 // Handle specific callback - might be a weak reference in disguise. | 311 // Handle specific callback - might be a weak reference in disguise. |
288 WeakCallback weak_callback_; | 312 WeakCallback weak_callback_; |
289 | 313 |
290 // Provided data for callback. In FREE state, this is used for | 314 // Provided data for callback. In FREE state, this is used for |
291 // the free list link. | 315 // the free list link. |
292 union { | 316 union { |
293 void* parameter; | 317 void* parameter; |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 DCHECK(location != NULL); | 492 DCHECK(location != NULL); |
469 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 493 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
470 } | 494 } |
471 | 495 |
472 | 496 |
473 void GlobalHandles::Destroy(Object** location) { | 497 void GlobalHandles::Destroy(Object** location) { |
474 if (location != NULL) Node::FromLocation(location)->Release(); | 498 if (location != NULL) Node::FromLocation(location)->Release(); |
475 } | 499 } |
476 | 500 |
477 | 501 |
478 void GlobalHandles::MakeWeak(Object** location, | 502 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
479 void* parameter, | 503 WeakCallback weak_callback, PhantomState phantom) { |
480 WeakCallback weak_callback) { | 504 Node::FromLocation(location) |
481 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); | 505 ->MakeWeak(parameter, weak_callback, phantom == Phantom); |
482 } | 506 } |
483 | 507 |
484 | 508 |
485 void* GlobalHandles::ClearWeakness(Object** location) { | 509 void* GlobalHandles::ClearWeakness(Object** location) { |
486 return Node::FromLocation(location)->ClearWeakness(); | 510 return Node::FromLocation(location)->ClearWeakness(); |
487 } | 511 } |
488 | 512 |
489 | 513 |
490 void GlobalHandles::MarkIndependent(Object** location) { | 514 void GlobalHandles::MarkIndependent(Object** location) { |
491 Node::FromLocation(location)->MarkIndependent(); | 515 Node::FromLocation(location)->MarkIndependent(); |
(...skipping 15 matching lines...) Expand all Loading... |
507 } | 531 } |
508 | 532 |
509 | 533 |
510 bool GlobalHandles::IsWeak(Object** location) { | 534 bool GlobalHandles::IsWeak(Object** location) { |
511 return Node::FromLocation(location)->IsWeak(); | 535 return Node::FromLocation(location)->IsWeak(); |
512 } | 536 } |
513 | 537 |
514 | 538 |
515 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 539 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
516 for (NodeIterator it(this); !it.done(); it.Advance()) { | 540 for (NodeIterator it(this); !it.done(); it.Advance()) { |
517 if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location()); | 541 Node* node = it.node(); |
| 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 } |
518 } | 550 } |
519 } | 551 } |
520 | 552 |
521 | 553 |
522 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 554 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
523 for (NodeIterator it(this); !it.done(); it.Advance()) { | 555 for (NodeIterator it(this); !it.done(); it.Advance()) { |
524 if (it.node()->IsWeak() && f(it.node()->location())) { | 556 if (it.node()->IsWeak() && f(it.node()->location())) { |
525 it.node()->MarkPending(); | 557 it.node()->MarkPending(); |
526 } | 558 } |
527 } | 559 } |
(...skipping 24 matching lines...) Expand all Loading... |
552 } | 584 } |
553 } | 585 } |
554 | 586 |
555 | 587 |
556 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 588 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
557 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 589 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
558 Node* node = new_space_nodes_[i]; | 590 Node* node = new_space_nodes_[i]; |
559 DCHECK(node->is_in_new_space_list()); | 591 DCHECK(node->is_in_new_space_list()); |
560 if ((node->is_independent() || node->is_partially_dependent()) && | 592 if ((node->is_independent() || node->is_partially_dependent()) && |
561 node->IsWeakRetainer()) { | 593 node->IsWeakRetainer()) { |
562 v->VisitPointer(node->location()); | 594 if (node->is_zapped_during_weak_callback()) { |
| 595 *(node->location()) = Smi::FromInt(kPhantomReferenceZap); |
| 596 } else { |
| 597 v->VisitPointer(node->location()); |
| 598 } |
563 } | 599 } |
564 } | 600 } |
565 } | 601 } |
566 | 602 |
567 | 603 |
568 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 604 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
569 WeakSlotCallbackWithHeap can_skip) { | 605 WeakSlotCallbackWithHeap can_skip) { |
570 ComputeObjectGroupsAndImplicitReferences(); | 606 ComputeObjectGroupsAndImplicitReferences(); |
571 int last = 0; | 607 int last = 0; |
572 bool any_group_was_visited = false; | 608 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]); | 1083 DCHECK_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
1048 blocks_[block][offset] = object; | 1084 blocks_[block][offset] = object; |
1049 if (isolate->heap()->InNewSpace(object)) { | 1085 if (isolate->heap()->InNewSpace(object)) { |
1050 new_space_indices_.Add(size_); | 1086 new_space_indices_.Add(size_); |
1051 } | 1087 } |
1052 *index = size_++; | 1088 *index = size_++; |
1053 } | 1089 } |
1054 | 1090 |
1055 | 1091 |
1056 } } // namespace v8::internal | 1092 } } // namespace v8::internal |
OLD | NEW |