global-handles.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockObjectGroup::~ObjectGroup() { 4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (info_ != NULL) info_->Dispose(); 4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass GlobalHandles::Node : public Malloced { 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Initialize(Object* object) { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the initial value of the handle. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_ = object; 5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NORMAL; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.parameter = NULL; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block callback_ = NULL; 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node() { 57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block state_ = DESTROYED; 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Node(Object* object) { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Initialize(object); 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize link structure. 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_ = NULL; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Node() { 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (state_ != DESTROYED) Destroy(Isolate::Current()->global_handles()); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Zap the values for eager trapping. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_ = NULL; 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_ = NULL; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.next_free = NULL; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Destroy(GlobalHandles* global_handles) { 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ == WEAK || IsNearDeath()) { 7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_weak_handles_--; 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_global_object_weak_handles_--; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = DESTROYED; 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for next_. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next() { return next_; } 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_next(Node* value) { next_ = value; } 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node** next_addr() { return &next_; } 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for next free node in the free list. 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_free() { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == DESTROYED); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return parameter_or_next_free_.next_free; 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_next_free(Node* value) { 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == DESTROYED); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.next_free = value; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns a link from the handle. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Node* FromLocation(Object** location) { 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(OFFSET_OF(Node, object_) == 0); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<Node*>(location); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the handle. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> handle() { return Handle<Object>(&object_); } 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make this handle weak. 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void MakeWeak(GlobalHandles* global_handles, void* parameter, 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block WeakReferenceCallback callback) { 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(global_handles->isolate(), 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleEvent("GlobalHandle::MakeWeak", handle().location())); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ != WEAK && !IsNearDeath()) { 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_weak_handles_++; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_global_object_weak_handles_++; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = WEAK; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(parameter); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block callback_ = callback; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ClearWeakness(GlobalHandles* global_handles) { 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(global_handles->isolate(), 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleEvent("GlobalHandle::ClearWeakness", handle().location())); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ == WEAK || IsNearDeath()) { 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_weak_handles_--; 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->number_of_global_object_weak_handles_--; 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NORMAL; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(NULL); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsNearDeath() { 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for PENDING to ensure correct answer when processing callbacks. 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return state_ == PENDING || state_ == NEAR_DEATH; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsWeak() { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return state_ == WEAK; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool CanBeRetainer() { 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return state_ != DESTROYED && state_ != NEAR_DEATH; 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SetWrapperClassId(uint16_t class_id) { 15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block class_id_ = class_id; 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the id for this weak handle. 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_parameter(void* parameter) { 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.parameter = parameter; 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* parameter() { 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return parameter_or_next_free_.parameter; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the callback for this weak handle. 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback() { return callback_; } 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool PostGarbageCollectionProcessing(Isolate* isolate, 17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GlobalHandles* global_handles) { 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ != Node::PENDING) return false; 17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate, HandleEvent("GlobalHandle::Processing", handle().location())); 17550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen WeakReferenceCallback func = callback(); 17650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (func == NULL) { 17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Destroy(global_handles); 17850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return false; 17950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* par = parameter(); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NEAR_DEATH; 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(NULL); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Forbid reuse of destroyed nodes as they might be already deallocated. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It's fine though to reuse nodes that were destroyed in weak callback 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as those cannot be deallocated until we are back from the callback. 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->set_first_free(NULL); 19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (global_handles->first_deallocated()) { 19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->first_deallocated()->set_next(global_handles->head()); 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that we are not passing a finalized external string to 194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // the callback. 195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!object_->IsExternalAsciiString() || 196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalAsciiString::cast(object_)->resource() != NULL); 197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!object_->IsExternalTwoByteString() || 198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalTwoByteString::cast(object_)->resource() != NULL); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leaving V8. 20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block VMState state(isolate, EXTERNAL); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block func(object, par); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 20350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Absense of explicit cleanup or revival of weak handle 20450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // in most of the cases would lead to memory leak. 20550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(state_ != NEAR_DEATH); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Place the handle address first to avoid offset computation. 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* object_; // Storage for object pointer. 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t class_id_; 21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Transition diagram: 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum State { 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NORMAL, // Normal global handle. 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WEAK, // Flagged as weak but not yet finalized. 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PENDING, // Has been recognized as only reachable by weak handles. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NEAR_DEATH, // Callback has informed the handle is near death. 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DESTROYED 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block State state_ : 4; // Need one more bit for MSVC as it treats enums as signed. 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle specific callback. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback_; 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Provided data for callback. In DESTROYED state, this is used for 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the free list link. 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block union { 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* parameter; 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_free; 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } parameter_or_next_free_; 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Linkage for the list. 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_; 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TRACK_MEMORY("GlobalHandles::Node") 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass GlobalHandles::Pool { 244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Pool() { 246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = new Chunk(); 247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_->previous = NULL; 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = current_->nodes; 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block limit_ = current_->nodes + kNodesPerChunk; 250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 252bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ~Pool() { 253bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (current_ != NULL) { 254bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Release(); 255bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 256bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 257bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* Allocate() { 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (next_ < limit_) { 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return next_++; 261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return SlowAllocate(); 263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Release() { 266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* current = current_; 267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(current != NULL); // At least a single block must by allocated 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block do { 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* previous = current->previous; 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delete current; 271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current = previous; 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } while (current != NULL); 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = NULL; 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = limit_ = NULL; 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kNodesPerChunk = (1 << 12) - 1; 279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct Chunk : public Malloced { 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* previous; 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node nodes[kNodesPerChunk]; 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* SlowAllocate() { 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* chunk = new Chunk(); 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block chunk->previous = current_; 287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = chunk; 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* new_nodes = current_->nodes; 290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = new_nodes + 1; 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block limit_ = new_nodes + kNodesPerChunk; 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new_nodes; 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* current_; 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* next_; 297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* limit_; 298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 30144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::GlobalHandles(Isolate* isolate) 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block number_of_weak_handles_(0), 30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block number_of_global_object_weak_handles_(0), 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block head_(NULL), 30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block first_free_(NULL), 30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block first_deallocated_(NULL), 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block pool_(new Pool()), 30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block post_gc_processing_count_(0), 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block object_groups_(4) { 31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 31444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockGlobalHandles::~GlobalHandles() { 31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete pool_; 31644f0eee88ff00398ff7f715fab053374d808c90dSteve Block pool_ = 0; 31744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> GlobalHandles::Create(Object* value) { 32144f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->counters()->global_handles()->Increment(); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* result; 323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_free()) { 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Take the first node in the free list. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = first_free(); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(result->next_free()); 327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (first_deallocated()) { 328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Next try deallocated list 329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = first_deallocated(); 330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(result->next_free()); 331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result->next() == head()); 332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_head(result); 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a new node. 33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = pool_->Allocate(); 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result->set_next(head()); 337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_head(result); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result->Initialize(value); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result->handle(); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Destroy(Object** location) { 34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->counters()->global_handles()->Decrement(); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (location == NULL) return; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* node = Node::FromLocation(location); 34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block node->Destroy(this); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link the destroyed. 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block node->set_next_free(first_free()); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(node); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::MakeWeak(Object** location, void* parameter, 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback) { 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(callback != NULL); 35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Node::FromLocation(location)->MakeWeak(this, parameter, callback); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::ClearWeakness(Object** location) { 36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Node::FromLocation(location)->ClearWeakness(this); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsNearDeath(Object** location) { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Node::FromLocation(location)->IsNearDeath(); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsWeak(Object** location) { 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Node::FromLocation(location)->IsWeak(); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) { 37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Node::FromLocation(location)->SetWrapperClassId(class_id); 37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Traversal of GC roots in the global handle list that are marked as 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // WEAK or PENDING. 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || current->state_ == Node::PENDING 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || current->state_ == Node::NEAR_DEATH) { 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointer(¤t->object_); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, 3963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block WeakReferenceCallback callback) { 3973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 3983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (current->IsWeak() && current->callback() == callback) { 3993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block f(current->object_, current->parameter()); 4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK) { 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f(¤t->object_)) { 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current->state_ = Node::PENDING; 41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate_, 41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleEvent("GlobalHandle::Pending", current->handle().location())); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool GlobalHandles::PostGarbageCollectionProcessing() { 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Process weak global handle callbacks. This must be done after the 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC is completely done, because the callbacks may invoke arbitrary 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // API functions. 422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // At the same time deallocate all DESTROYED nodes. 42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); 42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int initial_post_gc_processing_count = ++post_gc_processing_count_; 4253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu bool next_gc_likely_to_collect_more = false; 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node** p = &head_; 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (*p != NULL) { 42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) { 42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (initial_post_gc_processing_count != post_gc_processing_count_) { 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Weak callback triggered another GC and another round of 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // PostGarbageCollection processing. The current node might 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // have been deleted in that round, so we need to bail out (or 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // restart the processing). 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((*p)->state_ == Node::DESTROYED) { 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Delete the link. 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* node = *p; 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *p = node->next(); // Update the link. 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_deallocated()) { 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block first_deallocated()->set_next(node); 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block node->set_next_free(first_deallocated()); 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(node); 4463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu next_gc_likely_to_collect_more = true; 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p = (*p)->next_addr(); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(NULL); 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_deallocated()) { 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block first_deallocated()->set_next(head()); 454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 4563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu return next_gc_likely_to_collect_more; 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateStrongRoots(ObjectVisitor* v) { 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Traversal of global handles marked as NORMAL. 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::NORMAL) { 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointer(¤t->object_); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateAllRoots(ObjectVisitor* v) { 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (current->state_ != Node::DESTROYED) { 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v->VisitPointer(¤t->object_); 474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) { 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId && 48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block current->CanBeRetainer()) { 48344f0eee88ff00398ff7f715fab053374d808c90dSteve Block v->VisitEmbedderReference(¤t->object_, current->class_id_); 48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 48844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::TearDown() { 490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reset all the lists. 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_head(NULL); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(NULL); 493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(NULL); 49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pool_->Release(); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::RecordStats(HeapStats* stats) { 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->global_handle_count = 0; 500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->weak_global_handle_count = 0; 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->pending_global_handle_count = 0; 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->near_death_global_handle_count = 0; 503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->destroyed_global_handle_count = 0; 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->global_handle_count += 1; 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (current->state_ == Node::WEAK) { 507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->weak_global_handle_count += 1; 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::PENDING) { 509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->pending_global_handle_count += 1; 510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::NEAR_DEATH) { 511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->near_death_global_handle_count += 1; 512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::DESTROYED) { 513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->destroyed_global_handle_count += 1; 514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::PrintStats() { 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total = 0; 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int weak = 0; 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pending = 0; 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int near_death = 0; 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int destroyed = 0; 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block total++; 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK) weak++; 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::PENDING) pending++; 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::NEAR_DEATH) near_death++; 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::DESTROYED) destroyed++; 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Global Handle Statistics:\n"); 536f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch PrintF(" allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # weak = %d\n", weak); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # pending = %d\n", pending); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # near_death = %d\n", near_death); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # destroyed = %d\n", destroyed); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # total = %d\n", total); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Print() { 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Global handles:\n"); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch PrintF(" handle %p to %p (weak=%d)\n", 548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reinterpret_cast<void*>(current->handle().location()), 549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reinterpret_cast<void*>(*current->handle()), 550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch current->state_ == Node::WEAK); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 55844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::AddObjectGroup(Object*** handles, 55944f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_t length, 56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::RetainedObjectInfo* info) { 56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ObjectGroup* new_entry = new ObjectGroup(length, info); 56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (size_t i = 0; i < length; ++i) { 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new_entry->objects_.Add(handles[i]); 56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block object_groups_.Add(new_entry); 56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 56944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::AddImplicitReferences(HeapObject* parent, 57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Object*** children, 57144f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_t length) { 57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ImplicitRefGroup* new_entry = new ImplicitRefGroup(parent, length); 57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (size_t i = 0; i < length; ++i) { 57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block new_entry->children_.Add(children[i]); 57544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block implicit_ref_groups_.Add(new_entry); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::RemoveObjectGroups() { 58144f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < object_groups_.length(); i++) { 58244f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete object_groups_.at(i); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block object_groups_.Clear(); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid GlobalHandles::RemoveImplicitRefGroups() { 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < implicit_ref_groups_.length(); i++) { 59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete implicit_ref_groups_.at(i); 59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block implicit_ref_groups_.Clear(); 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 597