global-handles.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
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 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass GlobalHandles::Node : public Malloced { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Initialize(Object* object) { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the initial value of the handle. 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_ = object; 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NORMAL; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.parameter = NULL; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block callback_ = NULL; 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node() { 48d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block state_ = DESTROYED; 49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 50d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Node(Object* object) { 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Initialize(object); 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize link structure. 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_ = NULL; 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Node() { 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ != DESTROYED) Destroy(); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Zap the values for eager trapping. 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_ = NULL; 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_ = NULL; 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.next_free = NULL; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Destroy() { 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ == WEAK || IsNearDeath()) { 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_weak_handles_--; 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_global_object_weak_handles_--; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = DESTROYED; 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for next_. 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next() { return next_; } 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_next(Node* value) { next_ = value; } 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node** next_addr() { return &next_; } 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for next free node in the free list. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_free() { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == DESTROYED); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return parameter_or_next_free_.next_free; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_next_free(Node* value) { 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ == DESTROYED); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.next_free = value; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns a link from the handle. 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Node* FromLocation(Object** location) { 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(OFFSET_OF(Node, object_) == 0); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<Node*>(location); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the handle. 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> handle() { return Handle<Object>(&object_); } 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make this handle weak. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void MakeWeak(void* parameter, WeakReferenceCallback callback) { 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location())); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ != WEAK && !IsNearDeath()) { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_weak_handles_++; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_global_object_weak_handles_++; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = WEAK; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(parameter); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block callback_ = callback; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ClearWeakness() { 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location())); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ == WEAK || IsNearDeath()) { 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_weak_handles_--; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object_->IsJSGlobalObject()) { 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalHandles::number_of_global_object_weak_handles_--; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NORMAL; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(NULL); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsNearDeath() { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for PENDING to ensure correct answer when processing callbacks. 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return state_ == PENDING || state_ == NEAR_DEATH; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsWeak() { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return state_ == WEAK; 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the id for this weak handle. 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_parameter(void* parameter) { 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parameter_or_next_free_.parameter = parameter; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* parameter() { 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(state_ != DESTROYED); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return parameter_or_next_free_.parameter; 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the callback for this weak handle. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback() { return callback_; } 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool PostGarbageCollectionProcessing() { 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state_ != Node::PENDING) return false; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(HandleEvent("GlobalHandle::Processing", handle().location())); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* par = parameter(); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state_ = NEAR_DEATH; 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_parameter(NULL); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The callback function is resolved as late as possible to preserve old 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // behavior. 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback func = callback(); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (func == NULL) return false; 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Forbid reuse of destroyed nodes as they might be already deallocated. 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It's fine though to reuse nodes that were destroyed in weak callback 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // as those cannot be deallocated until we are back from the callback. 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(NULL); 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_deallocated()) { 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block first_deallocated()->set_next(head()); 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leaving V8. 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VMState state(EXTERNAL); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block func(object, par); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Place the handle address first to avoid offset computation. 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* object_; // Storage for object pointer. 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Transition diagram: 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum State { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NORMAL, // Normal global handle. 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WEAK, // Flagged as weak but not yet finalized. 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PENDING, // Has been recognized as only reachable by weak handles. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NEAR_DEATH, // Callback has informed the handle is near death. 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DESTROYED 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block State state_; 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle specific callback. 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback_; 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Provided data for callback. In DESTROYED state, this is used for 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the free list link. 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block union { 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* parameter; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_free; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } parameter_or_next_free_; 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Linkage for the list. 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* next_; 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TRACK_MEMORY("GlobalHandles::Node") 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass GlobalHandles::Pool BASE_EMBEDDED { 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Pool() { 213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = new Chunk(); 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_->previous = NULL; 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = current_->nodes; 216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block limit_ = current_->nodes + kNodesPerChunk; 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* Allocate() { 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (next_ < limit_) { 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return next_++; 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return SlowAllocate(); 224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Release() { 227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* current = current_; 228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(current != NULL); // At least a single block must by allocated 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block do { 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* previous = current->previous; 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delete current; 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current = previous; 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } while (current != NULL); 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = NULL; 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = limit_ = NULL; 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kNodesPerChunk = (1 << 12) - 1; 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct Chunk : public Malloced { 241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* previous; 242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node nodes[kNodesPerChunk]; 243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* SlowAllocate() { 246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* chunk = new Chunk(); 247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block chunk->previous = current_; 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block current_ = chunk; 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* new_nodes = current_->nodes; 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block next_ = new_nodes + 1; 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block limit_ = new_nodes + kNodesPerChunk; 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new_nodes; 254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Chunk* current_; 257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* next_; 258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Node* limit_; 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic GlobalHandles::Pool pool_; 263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> GlobalHandles::Create(Object* value) { 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::global_handles.Increment(); 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* result; 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_free()) { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Take the first node in the free list. 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = first_free(); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(result->next_free()); 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (first_deallocated()) { 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Next try deallocated list 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = first_deallocated(); 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(result->next_free()); 276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result->next() == head()); 277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_head(result); 278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Allocate a new node. 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = pool_.Allocate(); 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result->set_next(head()); 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_head(result); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result->Initialize(value); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result->handle(); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Destroy(Object** location) { 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::global_handles.Decrement(); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (location == NULL) return; 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* node = Node::FromLocation(location); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block node->Destroy(); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Link the destroyed. 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block node->set_next_free(first_free()); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(node); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::MakeWeak(Object** location, void* parameter, 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WeakReferenceCallback callback) { 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(callback != NULL); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node::FromLocation(location)->MakeWeak(parameter, callback); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::ClearWeakness(Object** location) { 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node::FromLocation(location)->ClearWeakness(); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsNearDeath(Object** location) { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Node::FromLocation(location)->IsNearDeath(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool GlobalHandles::IsWeak(Object** location) { 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Node::FromLocation(location)->IsWeak(); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Traversal of GC roots in the global handle list that are marked as 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // WEAK or PENDING. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || current->state_ == Node::PENDING 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || current->state_ == Node::NEAR_DEATH) { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointer(¤t->object_); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, 3363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block WeakReferenceCallback callback) { 3373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 3383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (current->IsWeak() && current->callback() == callback) { 3393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block f(current->object_, current->parameter()); 3403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 3433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK) { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f(¤t->object_)) { 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current->state_ = Node::PENDING; 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(HandleEvent("GlobalHandle::Pending", current->handle().location())); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint post_gc_processing_count = 0; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::PostGarbageCollectionProcessing() { 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Process weak global handle callbacks. This must be done after the 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC is completely done, because the callbacks may invoke arbitrary 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // API functions. 363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // At the same time deallocate all DESTROYED nodes. 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int initial_post_gc_processing_count = ++post_gc_processing_count; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node** p = &head_; 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (*p != NULL) { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((*p)->PostGarbageCollectionProcessing()) { 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (initial_post_gc_processing_count != post_gc_processing_count) { 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Weak callback triggered another GC and another round of 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // PostGarbageCollection processing. The current node might 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // have been deleted in that round, so we need to bail out (or 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // restart the processing). 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((*p)->state_ == Node::DESTROYED) { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Delete the link. 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Node* node = *p; 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *p = node->next(); // Update the link. 381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_deallocated()) { 382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block first_deallocated()->set_next(node); 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block node->set_next_free(first_deallocated()); 385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(node); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block p = (*p)->next_addr(); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(NULL); 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (first_deallocated()) { 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block first_deallocated()->set_next(head()); 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateStrongRoots(ObjectVisitor* v) { 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Traversal of global handles marked as NORMAL. 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::NORMAL) { 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointer(¤t->object_); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::IterateAllRoots(ObjectVisitor* v) { 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (current->state_ != Node::DESTROYED) { 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v->VisitPointer(¤t->object_); 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::TearDown() { 417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reset all the lists. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_head(NULL); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_first_free(NULL); 420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_first_deallocated(NULL); 421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pool_.Release(); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint GlobalHandles::number_of_weak_handles_ = 0; 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint GlobalHandles::number_of_global_object_weak_handles_ = 0; 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGlobalHandles::Node* GlobalHandles::head_ = NULL; 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGlobalHandles::Node* GlobalHandles::first_free_ = NULL; 430d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockGlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL; 431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid GlobalHandles::RecordStats(HeapStats* stats) { 433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->global_handle_count = 0; 434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->weak_global_handle_count = 0; 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->pending_global_handle_count = 0; 436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->near_death_global_handle_count = 0; 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->destroyed_global_handle_count = 0; 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (Node* current = head_; current != NULL; current = current->next()) { 439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->global_handle_count += 1; 440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (current->state_ == Node::WEAK) { 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->weak_global_handle_count += 1; 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::PENDING) { 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->pending_global_handle_count += 1; 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::NEAR_DEATH) { 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->near_death_global_handle_count += 1; 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (current->state_ == Node::DESTROYED) { 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *stats->destroyed_global_handle_count += 1; 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::PrintStats() { 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int total = 0; 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int weak = 0; 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pending = 0; 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int near_death = 0; 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int destroyed = 0; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block total++; 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::WEAK) weak++; 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::PENDING) pending++; 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::NEAR_DEATH) near_death++; 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->state_ == Node::DESTROYED) destroyed++; 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Global Handle Statistics:\n"); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" allocated memory = %dB\n", sizeof(Node) * total); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # weak = %d\n", weak); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # pending = %d\n", pending); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # near_death = %d\n", near_death); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # destroyed = %d\n", destroyed); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" # total = %d\n", total); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::Print() { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Global handles:\n"); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (Node* current = head_; current != NULL; current = current->next()) { 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF(" handle %p to %p (weak=%d)\n", current->handle().location(), 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *current->handle(), current->state_ == Node::WEAK); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockList<ObjectGroup*>* GlobalHandles::ObjectGroups() { 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Lazily initialize the list to avoid startup time static constructors. 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static List<ObjectGroup*> groups(4); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return &groups; 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::AddGroup(Object*** handles, size_t length) { 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ObjectGroup* new_entry = new ObjectGroup(length); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (size_t i = 0; i < length; ++i) 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new_entry->objects_.Add(handles[i]); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ObjectGroups()->Add(new_entry); 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid GlobalHandles::RemoveObjectGroups() { 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block List<ObjectGroup*>* object_groups = ObjectGroups(); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i< object_groups->length(); i++) { 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete object_groups->at(i); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object_groups->Clear(); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 512