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