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 // 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 NEAR_DEATH // Callback has informed the handle is near death. | 53 NEAR_DEATH // Callback has informed the handle is near death. |
| 54 }; | 54 }; |
| 55 | 55 |
| 56 // Maps handle location (slot) to the containing node. | 56 // Maps handle location (slot) to the containing node. |
| 57 static Node* FromLocation(Object** location) { | 57 static Node* FromLocation(Object** location) { |
| 58 ASSERT(OFFSET_OF(Node, object_) == 0); | 58 ASSERT(OFFSET_OF(Node, object_) == 0); |
| 59 return reinterpret_cast<Node*>(location); | 59 return reinterpret_cast<Node*>(location); |
| 60 } | 60 } |
| 61 | 61 |
| 62 Node() { | 62 Node() { |
| 63 ASSERT(OFFSET_OF(Node, flags_) == Internals::kNodeFlagsOffset); | 63 STATIC_ASSERT(offsetof(Node, class_id_) == Internals::kNodeClassIdOffset); |
| 64 ASSERT(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset); | 64 STATIC_ASSERT(offsetof(Node, flags_) == Internals::kNodeFlagsOffset); |
| 65 ASSERT(static_cast<int>(IsIndependent::kShift) == | 65 STATIC_ASSERT(static_cast<int>(NodeState::kMask) == |
| 66 Internals::kNodeIsIndependentShift); | 66 Internals::kNodeStateMask); |
| 67 ASSERT(static_cast<int>(IsPartiallyDependent::kShift) == | 67 STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue); |
| 68 Internals::kNodeIsPartiallyDependentShift); | 68 STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue); |
| 69 STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) == | |
| 70 Internals::kNodeIsIndependentShift); | |
| 71 STATIC_ASSERT(static_cast<int>(IsPartiallyDependent::kShift) == | |
| 72 Internals::kNodeIsPartiallyDependentShift); | |
| 69 } | 73 } |
| 70 | 74 |
| 71 #ifdef DEBUG | 75 #ifdef DEBUG |
| 72 ~Node() { | 76 ~Node() { |
| 73 // TODO(1428): if it's a weak handle we should have invoked its callback. | 77 // TODO(1428): if it's a weak handle we should have invoked its callback. |
| 74 // Zap the values for eager trapping. | 78 // Zap the values for eager trapping. |
| 75 object_ = NULL; | 79 object_ = NULL; |
| 76 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 80 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 77 index_ = 0; | 81 index_ = 0; |
| 78 set_independent(false); | 82 set_independent(false); |
| 79 set_partially_dependent(false); | 83 set_partially_dependent(false); |
| 80 set_in_new_space_list(false); | 84 set_in_new_space_list(false); |
| 81 parameter_or_next_free_.next_free = NULL; | 85 parameter_or_next_free_.next_free = NULL; |
| 82 callback_ = NULL; | 86 weak_reference_callback_ = NULL; |
| 87 near_death_callback_ = NULL; | |
| 83 } | 88 } |
| 84 #endif | 89 #endif |
| 85 | 90 |
| 86 void Initialize(int index, Node** first_free) { | 91 void Initialize(int index, Node** first_free) { |
| 87 index_ = static_cast<uint8_t>(index); | 92 index_ = static_cast<uint8_t>(index); |
| 88 ASSERT(static_cast<int>(index_) == index); | 93 ASSERT(static_cast<int>(index_) == index); |
| 89 set_state(FREE); | 94 set_state(FREE); |
| 90 set_in_new_space_list(false); | 95 set_in_new_space_list(false); |
| 91 parameter_or_next_free_.next_free = *first_free; | 96 parameter_or_next_free_.next_free = *first_free; |
| 92 *first_free = this; | 97 *first_free = this; |
| 93 } | 98 } |
| 94 | 99 |
| 95 void Acquire(Object* object, GlobalHandles* global_handles) { | 100 void Acquire(Object* object, GlobalHandles* global_handles) { |
| 96 ASSERT(state() == FREE); | 101 ASSERT(state() == FREE); |
| 97 object_ = object; | 102 object_ = object; |
| 98 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 103 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 99 set_independent(false); | 104 set_independent(false); |
| 100 set_partially_dependent(false); | 105 set_partially_dependent(false); |
| 101 set_state(NORMAL); | 106 set_state(NORMAL); |
| 102 parameter_or_next_free_.parameter = NULL; | 107 parameter_or_next_free_.parameter = NULL; |
| 103 callback_ = NULL; | 108 weak_reference_callback_ = NULL; |
| 109 near_death_callback_ = NULL; | |
| 104 IncreaseBlockUses(global_handles); | 110 IncreaseBlockUses(global_handles); |
| 105 } | 111 } |
| 106 | 112 |
| 107 void Release(GlobalHandles* global_handles) { | 113 void Release(GlobalHandles* global_handles) { |
| 108 ASSERT(state() != FREE); | 114 ASSERT(state() != FREE); |
| 109 set_state(FREE); | 115 set_state(FREE); |
| 110 parameter_or_next_free_.next_free = global_handles->first_free_; | 116 parameter_or_next_free_.next_free = global_handles->first_free_; |
| 111 global_handles->first_free_ = this; | 117 global_handles->first_free_ = this; |
| 112 DecreaseBlockUses(global_handles); | 118 DecreaseBlockUses(global_handles); |
| 113 } | 119 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 | 188 |
| 183 void MarkPartiallyDependent(GlobalHandles* global_handles) { | 189 void MarkPartiallyDependent(GlobalHandles* global_handles) { |
| 184 ASSERT(state() != FREE); | 190 ASSERT(state() != FREE); |
| 185 if (global_handles->isolate()->heap()->InNewSpace(object_)) { | 191 if (global_handles->isolate()->heap()->InNewSpace(object_)) { |
| 186 set_partially_dependent(true); | 192 set_partially_dependent(true); |
| 187 } | 193 } |
| 188 } | 194 } |
| 189 void clear_partially_dependent() { set_partially_dependent(false); } | 195 void clear_partially_dependent() { set_partially_dependent(false); } |
| 190 | 196 |
| 191 // Callback accessor. | 197 // Callback accessor. |
| 192 WeakReferenceCallback callback() { return callback_; } | 198 // TODO(svenpanne) Re-enable or nuke later. |
|
Michael Starzinger
2013/01/24 13:09:05
Definitely re-enable, but I am fine with this inte
| |
| 199 // WeakReferenceCallback callback() { return callback_; } | |
| 193 | 200 |
| 194 // Callback parameter accessors. | 201 // Callback parameter accessors. |
| 195 void set_parameter(void* parameter) { | 202 void set_parameter(void* parameter) { |
| 196 ASSERT(state() != FREE); | 203 ASSERT(state() != FREE); |
| 197 parameter_or_next_free_.parameter = parameter; | 204 parameter_or_next_free_.parameter = parameter; |
| 198 } | 205 } |
| 199 void* parameter() const { | 206 void* parameter() const { |
| 200 ASSERT(state() != FREE); | 207 ASSERT(state() != FREE); |
| 201 return parameter_or_next_free_.parameter; | 208 return parameter_or_next_free_.parameter; |
| 202 } | 209 } |
| 203 | 210 |
| 204 // Accessors for next free node in the free list. | 211 // Accessors for next free node in the free list. |
| 205 Node* next_free() { | 212 Node* next_free() { |
| 206 ASSERT(state() == FREE); | 213 ASSERT(state() == FREE); |
| 207 return parameter_or_next_free_.next_free; | 214 return parameter_or_next_free_.next_free; |
| 208 } | 215 } |
| 209 void set_next_free(Node* value) { | 216 void set_next_free(Node* value) { |
| 210 ASSERT(state() == FREE); | 217 ASSERT(state() == FREE); |
| 211 parameter_or_next_free_.next_free = value; | 218 parameter_or_next_free_.next_free = value; |
| 212 } | 219 } |
| 213 | 220 |
| 214 void MakeWeak(GlobalHandles* global_handles, | 221 void MakeWeak(GlobalHandles* global_handles, |
| 215 void* parameter, | 222 void* parameter, |
| 216 WeakReferenceCallback callback) { | 223 WeakReferenceCallback weak_reference_callback, |
| 224 NearDeathCallback near_death_callback) { | |
| 217 ASSERT(state() != FREE); | 225 ASSERT(state() != FREE); |
| 218 set_state(WEAK); | 226 set_state(WEAK); |
| 219 set_parameter(parameter); | 227 set_parameter(parameter); |
| 220 callback_ = callback; | 228 weak_reference_callback_ = weak_reference_callback; |
| 229 near_death_callback_ = near_death_callback; | |
| 221 } | 230 } |
| 222 | 231 |
| 223 void ClearWeakness(GlobalHandles* global_handles) { | 232 void ClearWeakness(GlobalHandles* global_handles) { |
| 224 ASSERT(state() != FREE); | 233 ASSERT(state() != FREE); |
| 225 set_state(NORMAL); | 234 set_state(NORMAL); |
| 226 set_parameter(NULL); | 235 set_parameter(NULL); |
| 227 } | 236 } |
| 228 | 237 |
| 229 bool PostGarbageCollectionProcessing(Isolate* isolate, | 238 bool PostGarbageCollectionProcessing(Isolate* isolate, |
| 230 GlobalHandles* global_handles) { | 239 GlobalHandles* global_handles) { |
| 231 if (state() != Node::PENDING) return false; | 240 if (state() != Node::PENDING) return false; |
| 232 WeakReferenceCallback func = callback(); | 241 if (weak_reference_callback_ == NULL && |
| 233 if (func == NULL) { | 242 near_death_callback_ == NULL) { |
| 234 Release(global_handles); | 243 Release(global_handles); |
| 235 return false; | 244 return false; |
| 236 } | 245 } |
| 237 void* par = parameter(); | 246 void* par = parameter(); |
| 238 set_state(NEAR_DEATH); | 247 set_state(NEAR_DEATH); |
| 239 set_parameter(NULL); | 248 set_parameter(NULL); |
| 240 | 249 |
| 241 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 250 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
| 242 { | 251 { |
| 243 // Check that we are not passing a finalized external string to | 252 // Check that we are not passing a finalized external string to |
| 244 // the callback. | 253 // the callback. |
| 245 ASSERT(!object_->IsExternalAsciiString() || | 254 ASSERT(!object_->IsExternalAsciiString() || |
| 246 ExternalAsciiString::cast(object_)->resource() != NULL); | 255 ExternalAsciiString::cast(object_)->resource() != NULL); |
| 247 ASSERT(!object_->IsExternalTwoByteString() || | 256 ASSERT(!object_->IsExternalTwoByteString() || |
| 248 ExternalTwoByteString::cast(object_)->resource() != NULL); | 257 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 249 // Leaving V8. | 258 // Leaving V8. |
| 250 VMState state(isolate, EXTERNAL); | 259 VMState state(isolate, EXTERNAL); |
| 251 func(object, par); | 260 if (weak_reference_callback_ != NULL) { |
| 261 weak_reference_callback_(object, par); | |
| 262 } | |
| 263 if (near_death_callback_ != NULL) { | |
| 264 near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate), | |
| 265 object, | |
| 266 par); | |
| 267 } | |
| 252 } | 268 } |
| 253 // Absence of explicit cleanup or revival of weak handle | 269 // Absence of explicit cleanup or revival of weak handle |
| 254 // in most of the cases would lead to memory leak. | 270 // in most of the cases would lead to memory leak. |
| 255 ASSERT(state() != NEAR_DEATH); | 271 ASSERT(state() != NEAR_DEATH); |
| 256 return true; | 272 return true; |
| 257 } | 273 } |
| 258 | 274 |
| 259 private: | 275 private: |
| 260 inline NodeBlock* FindBlock(); | 276 inline NodeBlock* FindBlock(); |
| 261 inline void IncreaseBlockUses(GlobalHandles* global_handles); | 277 inline void IncreaseBlockUses(GlobalHandles* global_handles); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 277 // This stores three flags (independent, partially_dependent and | 293 // This stores three flags (independent, partially_dependent and |
| 278 // in_new_space_list) and a State. | 294 // in_new_space_list) and a State. |
| 279 class NodeState: public BitField<State, 0, 4> {}; | 295 class NodeState: public BitField<State, 0, 4> {}; |
| 280 class IsIndependent: public BitField<bool, 4, 1> {}; | 296 class IsIndependent: public BitField<bool, 4, 1> {}; |
| 281 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 297 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
| 282 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 298 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
| 283 | 299 |
| 284 uint8_t flags_; | 300 uint8_t flags_; |
| 285 | 301 |
| 286 // Handle specific callback. | 302 // Handle specific callback. |
| 287 WeakReferenceCallback callback_; | 303 WeakReferenceCallback weak_reference_callback_; |
| 304 NearDeathCallback near_death_callback_; | |
| 288 | 305 |
| 289 // Provided data for callback. In FREE state, this is used for | 306 // Provided data for callback. In FREE state, this is used for |
| 290 // the free list link. | 307 // the free list link. |
| 291 union { | 308 union { |
| 292 void* parameter; | 309 void* parameter; |
| 293 Node* next_free; | 310 Node* next_free; |
| 294 } parameter_or_next_free_; | 311 } parameter_or_next_free_; |
| 295 | 312 |
| 296 DISALLOW_COPY_AND_ASSIGN(Node); | 313 DISALLOW_COPY_AND_ASSIGN(Node); |
| 297 }; | 314 }; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 | 460 |
| 444 | 461 |
| 445 void GlobalHandles::Destroy(Object** location) { | 462 void GlobalHandles::Destroy(Object** location) { |
| 446 isolate_->counters()->global_handles()->Decrement(); | 463 isolate_->counters()->global_handles()->Decrement(); |
| 447 number_of_global_handles_--; | 464 number_of_global_handles_--; |
| 448 if (location == NULL) return; | 465 if (location == NULL) return; |
| 449 Node::FromLocation(location)->Release(this); | 466 Node::FromLocation(location)->Release(this); |
| 450 } | 467 } |
| 451 | 468 |
| 452 | 469 |
| 453 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 470 void GlobalHandles::MakeWeak(Object** location, |
| 454 WeakReferenceCallback callback) { | 471 void* parameter, |
| 455 ASSERT(callback != NULL); | 472 WeakReferenceCallback weak_reference_callback, |
| 456 Node::FromLocation(location)->MakeWeak(this, parameter, callback); | 473 NearDeathCallback near_death_callback) { |
|
Michael Starzinger
2013/01/24 13:09:05
Add an assertion similar to the following:
ASSERT
Sven Panne
2013/01/25 08:28:40
Done.
| |
| 474 Node::FromLocation(location)->MakeWeak(this, | |
| 475 parameter, | |
| 476 weak_reference_callback, | |
| 477 near_death_callback); | |
| 457 } | 478 } |
| 458 | 479 |
| 459 | 480 |
| 460 void GlobalHandles::ClearWeakness(Object** location) { | 481 void GlobalHandles::ClearWeakness(Object** location) { |
| 461 Node::FromLocation(location)->ClearWeakness(this); | 482 Node::FromLocation(location)->ClearWeakness(this); |
| 462 } | 483 } |
| 463 | 484 |
| 464 | 485 |
| 465 void GlobalHandles::MarkIndependent(Object** location) { | 486 void GlobalHandles::MarkIndependent(Object** location) { |
| 466 Node::FromLocation(location)->MarkIndependent(); | 487 Node::FromLocation(location)->MarkIndependent(); |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 implicit_ref_groups_.Clear(); | 831 implicit_ref_groups_.Clear(); |
| 811 } | 832 } |
| 812 | 833 |
| 813 | 834 |
| 814 void GlobalHandles::TearDown() { | 835 void GlobalHandles::TearDown() { |
| 815 // TODO(1428): invoke weak callbacks. | 836 // TODO(1428): invoke weak callbacks. |
| 816 } | 837 } |
| 817 | 838 |
| 818 | 839 |
| 819 } } // namespace v8::internal | 840 } } // namespace v8::internal |
| OLD | NEW |