| 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 | 
|---|