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 |