| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 ~Node() { | 83 ~Node() { |
| 84 // TODO(1428): if it's a weak handle we should have invoked its callback. | 84 // TODO(1428): if it's a weak handle we should have invoked its callback. |
| 85 // Zap the values for eager trapping. | 85 // Zap the values for eager trapping. |
| 86 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 86 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 88 index_ = 0; | 88 index_ = 0; |
| 89 set_independent(false); | 89 set_independent(false); |
| 90 set_partially_dependent(false); | 90 set_partially_dependent(false); |
| 91 set_in_new_space_list(false); | 91 set_in_new_space_list(false); |
| 92 parameter_or_next_free_.next_free = NULL; | 92 parameter_or_next_free_.next_free = NULL; |
| 93 weak_reference_callback_ = NULL; | 93 weak_callback_ = NULL; |
| 94 } | 94 } |
| 95 #endif | 95 #endif |
| 96 | 96 |
| 97 void Initialize(int index, Node** first_free) { | 97 void Initialize(int index, Node** first_free) { |
| 98 index_ = static_cast<uint8_t>(index); | 98 index_ = static_cast<uint8_t>(index); |
| 99 ASSERT(static_cast<int>(index_) == index); | 99 ASSERT(static_cast<int>(index_) == index); |
| 100 set_state(FREE); | 100 set_state(FREE); |
| 101 set_in_new_space_list(false); | 101 set_in_new_space_list(false); |
| 102 parameter_or_next_free_.next_free = *first_free; | 102 parameter_or_next_free_.next_free = *first_free; |
| 103 *first_free = this; | 103 *first_free = this; |
| 104 } | 104 } |
| 105 | 105 |
| 106 void Acquire(Object* object) { | 106 void Acquire(Object* object) { |
| 107 ASSERT(state() == FREE); | 107 ASSERT(state() == FREE); |
| 108 object_ = object; | 108 object_ = object; |
| 109 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 109 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 110 set_independent(false); | 110 set_independent(false); |
| 111 set_partially_dependent(false); | 111 set_partially_dependent(false); |
| 112 set_state(NORMAL); | 112 set_state(NORMAL); |
| 113 parameter_or_next_free_.parameter = NULL; | 113 parameter_or_next_free_.parameter = NULL; |
| 114 weak_reference_callback_ = NULL; | 114 weak_callback_ = NULL; |
| 115 IncreaseBlockUses(); | 115 IncreaseBlockUses(); |
| 116 } | 116 } |
| 117 | 117 |
| 118 void Release() { | 118 void Release() { |
| 119 ASSERT(state() != FREE); | 119 ASSERT(state() != FREE); |
| 120 set_state(FREE); | 120 set_state(FREE); |
| 121 // Zap the values for eager trapping. | 121 // Zap the values for eager trapping. |
| 122 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 122 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 123 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 123 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 124 set_independent(false); | 124 set_independent(false); |
| 125 set_partially_dependent(false); | 125 set_partially_dependent(false); |
| 126 weak_reference_callback_ = NULL; | 126 weak_callback_ = NULL; |
| 127 DecreaseBlockUses(); | 127 DecreaseBlockUses(); |
| 128 } | 128 } |
| 129 | 129 |
| 130 // Object slot accessors. | 130 // Object slot accessors. |
| 131 Object* object() const { return object_; } | 131 Object* object() const { return object_; } |
| 132 Object** location() { return &object_; } | 132 Object** location() { return &object_; } |
| 133 Handle<Object> handle() { return Handle<Object>(location()); } | 133 Handle<Object> handle() { return Handle<Object>(location()); } |
| 134 | 134 |
| 135 // Wrapper class ID accessors. | 135 // Wrapper class ID accessors. |
| 136 bool has_wrapper_class_id() const { | 136 bool has_wrapper_class_id() const { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 162 flags_ = IsPartiallyDependent::update(flags_, v); | 162 flags_ = IsPartiallyDependent::update(flags_, v); |
| 163 } | 163 } |
| 164 | 164 |
| 165 bool is_in_new_space_list() { | 165 bool is_in_new_space_list() { |
| 166 return IsInNewSpaceList::decode(flags_); | 166 return IsInNewSpaceList::decode(flags_); |
| 167 } | 167 } |
| 168 void set_in_new_space_list(bool v) { | 168 void set_in_new_space_list(bool v) { |
| 169 flags_ = IsInNewSpaceList::update(flags_, v); | 169 flags_ = IsInNewSpaceList::update(flags_, v); |
| 170 } | 170 } |
| 171 | 171 |
| 172 bool is_revivable_callback() { |
| 173 return IsRevivableCallback::decode(flags_); |
| 174 } |
| 175 void set_revivable_callback(bool v) { |
| 176 flags_ = IsRevivableCallback::update(flags_, v); |
| 177 } |
| 178 |
| 172 bool IsNearDeath() const { | 179 bool IsNearDeath() const { |
| 173 // Check for PENDING to ensure correct answer when processing callbacks. | 180 // Check for PENDING to ensure correct answer when processing callbacks. |
| 174 return state() == PENDING || state() == NEAR_DEATH; | 181 return state() == PENDING || state() == NEAR_DEATH; |
| 175 } | 182 } |
| 176 | 183 |
| 177 bool IsWeak() const { return state() == WEAK; } | 184 bool IsWeak() const { return state() == WEAK; } |
| 178 | 185 |
| 179 bool IsRetainer() const { return state() != FREE; } | 186 bool IsRetainer() const { return state() != FREE; } |
| 180 | 187 |
| 181 bool IsStrongRetainer() const { return state() == NORMAL; } | 188 bool IsStrongRetainer() const { return state() == NORMAL; } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 Node* next_free() { | 228 Node* next_free() { |
| 222 ASSERT(state() == FREE); | 229 ASSERT(state() == FREE); |
| 223 return parameter_or_next_free_.next_free; | 230 return parameter_or_next_free_.next_free; |
| 224 } | 231 } |
| 225 void set_next_free(Node* value) { | 232 void set_next_free(Node* value) { |
| 226 ASSERT(state() == FREE); | 233 ASSERT(state() == FREE); |
| 227 parameter_or_next_free_.next_free = value; | 234 parameter_or_next_free_.next_free = value; |
| 228 } | 235 } |
| 229 | 236 |
| 230 void MakeWeak(void* parameter, | 237 void MakeWeak(void* parameter, |
| 231 RevivableCallback weak_reference_callback) { | 238 WeakCallback weak_callback, |
| 239 RevivableCallback revivable_callback) { |
| 240 ASSERT((weak_callback == NULL) != (revivable_callback == NULL)); |
| 232 ASSERT(state() != FREE); | 241 ASSERT(state() != FREE); |
| 233 set_state(WEAK); | 242 set_state(WEAK); |
| 234 set_parameter(parameter); | 243 set_parameter(parameter); |
| 235 weak_reference_callback_ = weak_reference_callback; | 244 if (weak_callback != NULL) { |
| 245 weak_callback_ = weak_callback; |
| 246 set_revivable_callback(false); |
| 247 } else { |
| 248 weak_callback_ = |
| 249 reinterpret_cast<WeakCallback>(revivable_callback); |
| 250 set_revivable_callback(true); |
| 251 } |
| 236 } | 252 } |
| 237 | 253 |
| 238 void ClearWeakness() { | 254 void ClearWeakness() { |
| 239 ASSERT(state() != FREE); | 255 ASSERT(state() != FREE); |
| 240 set_state(NORMAL); | 256 set_state(NORMAL); |
| 241 set_parameter(NULL); | 257 set_parameter(NULL); |
| 242 } | 258 } |
| 243 | 259 |
| 244 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 260 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
| 245 if (state() != Node::PENDING) return false; | 261 if (state() != Node::PENDING) return false; |
| 246 if (weak_reference_callback_ == NULL) { | 262 if (weak_callback_ == NULL) { |
| 247 Release(); | 263 Release(); |
| 248 return false; | 264 return false; |
| 249 } | 265 } |
| 250 void* par = parameter(); | 266 void* par = parameter(); |
| 251 set_state(NEAR_DEATH); | 267 set_state(NEAR_DEATH); |
| 252 set_parameter(NULL); | 268 set_parameter(NULL); |
| 253 | 269 |
| 254 Object** object = location(); | 270 Object** object = location(); |
| 255 { | 271 { |
| 256 // Check that we are not passing a finalized external string to | 272 // Check that we are not passing a finalized external string to |
| 257 // the callback. | 273 // the callback. |
| 258 ASSERT(!object_->IsExternalAsciiString() || | 274 ASSERT(!object_->IsExternalAsciiString() || |
| 259 ExternalAsciiString::cast(object_)->resource() != NULL); | 275 ExternalAsciiString::cast(object_)->resource() != NULL); |
| 260 ASSERT(!object_->IsExternalTwoByteString() || | 276 ASSERT(!object_->IsExternalTwoByteString() || |
| 261 ExternalTwoByteString::cast(object_)->resource() != NULL); | 277 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 262 // Leaving V8. | 278 // Leaving V8. |
| 263 VMState<EXTERNAL> state(isolate); | 279 VMState<EXTERNAL> state(isolate); |
| 264 HandleScope handle_scope(isolate); | 280 HandleScope handle_scope(isolate); |
| 265 weak_reference_callback_(reinterpret_cast<v8::Isolate*>(isolate), | 281 if (is_revivable_callback()) { |
| 266 reinterpret_cast<Persistent<Value>*>(&object), | 282 RevivableCallback revivable = |
| 267 par); | 283 reinterpret_cast<RevivableCallback>(weak_callback_); |
| 284 revivable(reinterpret_cast<v8::Isolate*>(isolate), |
| 285 reinterpret_cast<Persistent<Value>*>(&object), |
| 286 par); |
| 287 } else { |
| 288 Handle<Object> handle(*object, isolate); |
| 289 v8::WeakCallbackData<v8::Value, void> data( |
| 290 reinterpret_cast<v8::Isolate*>(isolate), |
| 291 v8::Utils::ToLocal(handle), |
| 292 par); |
| 293 weak_callback_(data); |
| 294 } |
| 268 } | 295 } |
| 269 // Absence of explicit cleanup or revival of weak handle | 296 // Absence of explicit cleanup or revival of weak handle |
| 270 // in most of the cases would lead to memory leak. | 297 // in most of the cases would lead to memory leak. |
| 271 ASSERT(state() != NEAR_DEATH); | 298 ASSERT(state() != NEAR_DEATH); |
| 272 return true; | 299 return true; |
| 273 } | 300 } |
| 274 | 301 |
| 302 inline GlobalHandles* GetGlobalHandles(); |
| 303 |
| 275 private: | 304 private: |
| 276 inline NodeBlock* FindBlock(); | 305 inline NodeBlock* FindBlock(); |
| 277 inline GlobalHandles* GetGlobalHandles(); | |
| 278 inline void IncreaseBlockUses(); | 306 inline void IncreaseBlockUses(); |
| 279 inline void DecreaseBlockUses(); | 307 inline void DecreaseBlockUses(); |
| 280 | 308 |
| 281 // Storage for object pointer. | 309 // Storage for object pointer. |
| 282 // Placed first to avoid offset computation. | 310 // Placed first to avoid offset computation. |
| 283 Object* object_; | 311 Object* object_; |
| 284 | 312 |
| 285 // Next word stores class_id, index, state, and independent. | 313 // Next word stores class_id, index, state, and independent. |
| 286 // Note: the most aligned fields should go first. | 314 // Note: the most aligned fields should go first. |
| 287 | 315 |
| 288 // Wrapper class ID. | 316 // Wrapper class ID. |
| 289 uint16_t class_id_; | 317 uint16_t class_id_; |
| 290 | 318 |
| 291 // Index in the containing handle block. | 319 // Index in the containing handle block. |
| 292 uint8_t index_; | 320 uint8_t index_; |
| 293 | 321 |
| 294 // This stores three flags (independent, partially_dependent and | 322 // This stores three flags (independent, partially_dependent and |
| 295 // in_new_space_list) and a State. | 323 // in_new_space_list) and a State. |
| 296 class NodeState: public BitField<State, 0, 4> {}; | 324 class NodeState: public BitField<State, 0, 4> {}; |
| 297 class IsIndependent: public BitField<bool, 4, 1> {}; | 325 class IsIndependent: public BitField<bool, 4, 1> {}; |
| 298 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 326 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
| 299 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 327 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
| 328 class IsRevivableCallback: public BitField<bool, 7, 1> {}; |
| 300 | 329 |
| 301 uint8_t flags_; | 330 uint8_t flags_; |
| 302 | 331 |
| 303 // Handle specific callback - might be a weak reference in disguise. | 332 // Handle specific callback - might be a weak reference in disguise. |
| 304 RevivableCallback weak_reference_callback_; | 333 WeakCallback weak_callback_; |
| 305 | 334 |
| 306 // Provided data for callback. In FREE state, this is used for | 335 // Provided data for callback. In FREE state, this is used for |
| 307 // the free list link. | 336 // the free list link. |
| 308 union { | 337 union { |
| 309 void* parameter; | 338 void* parameter; |
| 310 Node* next_free; | 339 Node* next_free; |
| 311 } parameter_or_next_free_; | 340 } parameter_or_next_free_; |
| 312 | 341 |
| 313 DISALLOW_COPY_AND_ASSIGN(Node); | 342 DISALLOW_COPY_AND_ASSIGN(Node); |
| 314 }; | 343 }; |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 result->Acquire(value); | 502 result->Acquire(value); |
| 474 if (isolate_->heap()->InNewSpace(value) && | 503 if (isolate_->heap()->InNewSpace(value) && |
| 475 !result->is_in_new_space_list()) { | 504 !result->is_in_new_space_list()) { |
| 476 new_space_nodes_.Add(result); | 505 new_space_nodes_.Add(result); |
| 477 result->set_in_new_space_list(true); | 506 result->set_in_new_space_list(true); |
| 478 } | 507 } |
| 479 return result->handle(); | 508 return result->handle(); |
| 480 } | 509 } |
| 481 | 510 |
| 482 | 511 |
| 512 Handle<Object> GlobalHandles::CopyGlobal(Object** location) { |
| 513 ASSERT(location != NULL); |
| 514 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
| 515 } |
| 516 |
| 517 |
| 483 void GlobalHandles::Destroy(Object** location) { | 518 void GlobalHandles::Destroy(Object** location) { |
| 484 if (location != NULL) Node::FromLocation(location)->Release(); | 519 if (location != NULL) Node::FromLocation(location)->Release(); |
| 485 } | 520 } |
| 486 | 521 |
| 487 | 522 |
| 488 void GlobalHandles::MakeWeak(Object** location, | 523 void GlobalHandles::MakeWeak(Object** location, |
| 489 void* parameter, | 524 void* parameter, |
| 490 RevivableCallback weak_reference_callback) { | 525 WeakCallback weak_callback, |
| 491 ASSERT(weak_reference_callback != NULL); | 526 RevivableCallback revivable_callback) { |
| 492 Node::FromLocation(location)->MakeWeak(parameter, weak_reference_callback); | 527 Node::FromLocation(location)->MakeWeak( |
| 528 parameter, weak_callback, revivable_callback); |
| 493 } | 529 } |
| 494 | 530 |
| 495 | 531 |
| 496 void GlobalHandles::ClearWeakness(Object** location) { | 532 void GlobalHandles::ClearWeakness(Object** location) { |
| 497 Node::FromLocation(location)->ClearWeakness(); | 533 Node::FromLocation(location)->ClearWeakness(); |
| 498 } | 534 } |
| 499 | 535 |
| 500 | 536 |
| 501 void GlobalHandles::MarkIndependent(Object** location) { | 537 void GlobalHandles::MarkIndependent(Object** location) { |
| 502 Node::FromLocation(location)->MarkIndependent(); | 538 Node::FromLocation(location)->MarkIndependent(); |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1111 ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
| 1076 blocks_[block][offset] = object; | 1112 blocks_[block][offset] = object; |
| 1077 if (isolate->heap()->InNewSpace(object)) { | 1113 if (isolate->heap()->InNewSpace(object)) { |
| 1078 new_space_indices_.Add(size_); | 1114 new_space_indices_.Add(size_); |
| 1079 } | 1115 } |
| 1080 *index = size_++; | 1116 *index = size_++; |
| 1081 } | 1117 } |
| 1082 | 1118 |
| 1083 | 1119 |
| 1084 } } // namespace v8::internal | 1120 } } // namespace v8::internal |
| OLD | NEW |