summaryrefslogtreecommitdiff
path: root/deps/v8/src/global-handles.cc
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-07-05 14:40:13 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-07-05 14:51:29 -0700
commit149562555c9bf56457dee9a1ad70c53ed670a776 (patch)
treef6217cf3c54ddbee03f37247a3c7c75203f868fd /deps/v8/src/global-handles.cc
parentf08720606757577d95bd09b48697c7decbf17f00 (diff)
downloadnode-new-149562555c9bf56457dee9a1ad70c53ed670a776.tar.gz
Downgrade V8 to 3.1.8.25
There are serious performance regressions both in V8 and our own legacy networking stack. Until we correct our own problems we are going back to the old V8.
Diffstat (limited to 'deps/v8/src/global-handles.cc')
-rw-r--r--deps/v8/src/global-handles.cc733
1 files changed, 273 insertions, 460 deletions
diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc
index 87066faeaf..18cdc5a3af 100644
--- a/deps/v8/src/global-handles.cc
+++ b/deps/v8/src/global-handles.cc
@@ -35,160 +35,79 @@
namespace v8 {
namespace internal {
-
-ObjectGroup::~ObjectGroup() {
- if (info_ != NULL) info_->Dispose();
-}
-
-
-class GlobalHandles::Node {
+class GlobalHandles::Node : public Malloced {
public:
- // State transition diagram:
- // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
- enum State {
- FREE,
- NORMAL, // Normal global handle.
- WEAK, // Flagged as weak but not yet finalized.
- PENDING, // Has been recognized as only reachable by weak handles.
- NEAR_DEATH // Callback has informed the handle is near death.
- };
- // Maps handle location (slot) to the containing node.
- static Node* FromLocation(Object** location) {
- ASSERT(OFFSET_OF(Node, object_) == 0);
- return reinterpret_cast<Node*>(location);
+ void Initialize(Object* object) {
+ // Set the initial value of the handle.
+ object_ = object;
+ state_ = NORMAL;
+ parameter_or_next_free_.parameter = NULL;
+ callback_ = NULL;
}
- Node() {}
+ Node() {
+ state_ = DESTROYED;
+ }
+
+ explicit Node(Object* object) {
+ Initialize(object);
+ // Initialize link structure.
+ next_ = NULL;
+ }
-#ifdef DEBUG
~Node() {
- // TODO(1428): if it's a weak handle we should have invoked its callback.
+ if (state_ != DESTROYED) Destroy();
+#ifdef DEBUG
// Zap the values for eager trapping.
object_ = NULL;
- class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
- index_ = 0;
- independent_ = false;
- in_new_space_list_ = false;
+ next_ = NULL;
parameter_or_next_free_.next_free = NULL;
- callback_ = NULL;
- }
#endif
-
- void Initialize(int index, Node** first_free) {
- index_ = static_cast<uint8_t>(index);
- ASSERT(static_cast<int>(index_) == index);
- state_ = FREE;
- in_new_space_list_ = false;
- parameter_or_next_free_.next_free = *first_free;
- *first_free = this;
}
- void Acquire(Object* object, GlobalHandles* global_handles) {
- ASSERT(state_ == FREE);
- object_ = object;
- class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
- independent_ = false;
- state_ = NORMAL;
- parameter_or_next_free_.parameter = NULL;
- callback_ = NULL;
- IncreaseBlockUses(global_handles);
- }
-
- void Release(GlobalHandles* global_handles) {
- ASSERT(state_ != FREE);
- if (IsWeakRetainer()) {
- global_handles->number_of_weak_handles_--;
+ void Destroy() {
+ if (state_ == WEAK || IsNearDeath()) {
+ GlobalHandles::number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) {
- global_handles->number_of_global_object_weak_handles_--;
+ GlobalHandles::number_of_global_object_weak_handles_--;
}
}
- state_ = FREE;
- parameter_or_next_free_.next_free = global_handles->first_free_;
- global_handles->first_free_ = this;
- DecreaseBlockUses(global_handles);
- }
-
- // Object slot accessors.
- Object* object() const { return object_; }
- Object** location() { return &object_; }
- Handle<Object> handle() { return Handle<Object>(location()); }
-
- // Wrapper class ID accessors.
- bool has_wrapper_class_id() const {
- return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
- }
- uint16_t wrapper_class_id() const { return class_id_; }
- void set_wrapper_class_id(uint16_t class_id) {
- class_id_ = class_id;
- }
-
- // State accessors.
-
- State state() const { return state_; }
-
- bool IsNearDeath() const {
- // Check for PENDING to ensure correct answer when processing callbacks.
- return state_ == PENDING || state_ == NEAR_DEATH;
+ state_ = DESTROYED;
}
- bool IsWeak() const { return state_ == WEAK; }
-
- bool IsRetainer() const { return state_ != FREE; }
-
- bool IsStrongRetainer() const { return state_ == NORMAL; }
-
- bool IsWeakRetainer() const {
- return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH;
- }
-
- void MarkPending() {
- ASSERT(state_ == WEAK);
- state_ = PENDING;
- }
-
- // Independent flag accessors.
- void MarkIndependent() {
- ASSERT(state_ != FREE);
- independent_ = true;
- }
- bool is_independent() const { return independent_; }
-
- // In-new-space-list flag accessors.
- void set_in_new_space_list(bool v) { in_new_space_list_ = v; }
- bool is_in_new_space_list() const { return in_new_space_list_; }
-
- // Callback accessor.
- WeakReferenceCallback callback() { return callback_; }
-
- // Callback parameter accessors.
- void set_parameter(void* parameter) {
- ASSERT(state_ != FREE);
- parameter_or_next_free_.parameter = parameter;
- }
- void* parameter() const {
- ASSERT(state_ != FREE);
- return parameter_or_next_free_.parameter;
- }
+ // Accessors for next_.
+ Node* next() { return next_; }
+ void set_next(Node* value) { next_ = value; }
+ Node** next_addr() { return &next_; }
// Accessors for next free node in the free list.
Node* next_free() {
- ASSERT(state_ == FREE);
+ ASSERT(state_ == DESTROYED);
return parameter_or_next_free_.next_free;
}
void set_next_free(Node* value) {
- ASSERT(state_ == FREE);
+ ASSERT(state_ == DESTROYED);
parameter_or_next_free_.next_free = value;
}
- void MakeWeak(GlobalHandles* global_handles,
- void* parameter,
- WeakReferenceCallback callback) {
- ASSERT(state_ != FREE);
- if (!IsWeakRetainer()) {
- global_handles->number_of_weak_handles_++;
+ // Returns a link from the handle.
+ static Node* FromLocation(Object** location) {
+ ASSERT(OFFSET_OF(Node, object_) == 0);
+ return reinterpret_cast<Node*>(location);
+ }
+
+ // Returns the handle.
+ Handle<Object> handle() { return Handle<Object>(&object_); }
+
+ // Make this handle weak.
+ void MakeWeak(void* parameter, WeakReferenceCallback callback) {
+ LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
+ ASSERT(state_ != DESTROYED);
+ if (state_ != WEAK && !IsNearDeath()) {
+ GlobalHandles::number_of_weak_handles_++;
if (object_->IsJSGlobalObject()) {
- global_handles->number_of_global_object_weak_handles_++;
+ GlobalHandles::number_of_global_object_weak_handles_++;
}
}
state_ = WEAK;
@@ -196,24 +115,47 @@ class GlobalHandles::Node {
callback_ = callback;
}
- void ClearWeakness(GlobalHandles* global_handles) {
- ASSERT(state_ != FREE);
- if (IsWeakRetainer()) {
- global_handles->number_of_weak_handles_--;
+ void ClearWeakness() {
+ LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
+ ASSERT(state_ != DESTROYED);
+ if (state_ == WEAK || IsNearDeath()) {
+ GlobalHandles::number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) {
- global_handles->number_of_global_object_weak_handles_--;
+ GlobalHandles::number_of_global_object_weak_handles_--;
}
}
state_ = NORMAL;
set_parameter(NULL);
}
- bool PostGarbageCollectionProcessing(Isolate* isolate,
- GlobalHandles* global_handles) {
+ bool IsNearDeath() {
+ // Check for PENDING to ensure correct answer when processing callbacks.
+ return state_ == PENDING || state_ == NEAR_DEATH;
+ }
+
+ bool IsWeak() {
+ return state_ == WEAK;
+ }
+
+ // Returns the id for this weak handle.
+ void set_parameter(void* parameter) {
+ ASSERT(state_ != DESTROYED);
+ parameter_or_next_free_.parameter = parameter;
+ }
+ void* parameter() {
+ ASSERT(state_ != DESTROYED);
+ return parameter_or_next_free_.parameter;
+ }
+
+ // Returns the callback for this weak handle.
+ WeakReferenceCallback callback() { return callback_; }
+
+ bool PostGarbageCollectionProcessing() {
if (state_ != Node::PENDING) return false;
+ LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
WeakReferenceCallback func = callback();
if (func == NULL) {
- Release(global_handles);
+ Destroy();
return false;
}
void* par = parameter();
@@ -222,6 +164,13 @@ class GlobalHandles::Node {
v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
{
+ // Forbid reuse of destroyed nodes as they might be already deallocated.
+ // It's fine though to reuse nodes that were destroyed in weak callback
+ // as those cannot be deallocated until we are back from the callback.
+ set_first_free(NULL);
+ if (first_deallocated()) {
+ first_deallocated()->set_next(head());
+ }
// Check that we are not passing a finalized external string to
// the callback.
ASSERT(!object_->IsExternalAsciiString() ||
@@ -229,7 +178,7 @@ class GlobalHandles::Node {
ASSERT(!object_->IsExternalTwoByteString() ||
ExternalTwoByteString::cast(object_)->resource() != NULL);
// Leaving V8.
- VMState state(isolate, EXTERNAL);
+ VMState state(EXTERNAL);
func(object, par);
}
// Absense of explicit cleanup or revival of weak handle
@@ -238,210 +187,143 @@ class GlobalHandles::Node {
return true;
}
- private:
- inline NodeBlock* FindBlock();
- inline void IncreaseBlockUses(GlobalHandles* global_handles);
- inline void DecreaseBlockUses(GlobalHandles* global_handles);
-
- // Storage for object pointer.
- // Placed first to avoid offset computation.
- Object* object_;
-
- // Next word stores class_id, index, state, and independent.
- // Note: the most aligned fields should go first.
+ // Place the handle address first to avoid offset computation.
+ Object* object_; // Storage for object pointer.
- // Wrapper class ID.
- uint16_t class_id_;
-
- // Index in the containing handle block.
- uint8_t index_;
-
- // Need one more bit for MSVC as it treats enums as signed.
- State state_ : 4;
-
- bool independent_ : 1;
- bool in_new_space_list_ : 1;
+ // Transition diagram:
+ // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
+ enum State {
+ NORMAL, // Normal global handle.
+ WEAK, // Flagged as weak but not yet finalized.
+ PENDING, // Has been recognized as only reachable by weak handles.
+ NEAR_DEATH, // Callback has informed the handle is near death.
+ DESTROYED
+ };
+ State state_;
+ private:
// Handle specific callback.
WeakReferenceCallback callback_;
-
- // Provided data for callback. In FREE state, this is used for
+ // Provided data for callback. In DESTROYED state, this is used for
// the free list link.
union {
void* parameter;
Node* next_free;
} parameter_or_next_free_;
- DISALLOW_COPY_AND_ASSIGN(Node);
-};
-
+ // Linkage for the list.
+ Node* next_;
-class GlobalHandles::NodeBlock {
public:
- static const int kSize = 256;
+ TRACK_MEMORY("GlobalHandles::Node")
+};
- explicit NodeBlock(NodeBlock* next)
- : next_(next), used_nodes_(0), next_used_(NULL), prev_used_(NULL) {}
- void PutNodesOnFreeList(Node** first_free) {
- for (int i = kSize - 1; i >= 0; --i) {
- nodes_[i].Initialize(i, first_free);
+class GlobalHandles::Pool BASE_EMBEDDED {
+ public:
+ Pool() {
+ current_ = new Chunk();
+ current_->previous = NULL;
+ next_ = current_->nodes;
+ limit_ = current_->nodes + kNodesPerChunk;
}
- }
- Node* node_at(int index) {
- ASSERT(0 <= index && index < kSize);
- return &nodes_[index];
- }
-
- void IncreaseUses(GlobalHandles* global_handles) {
- ASSERT(used_nodes_ < kSize);
- if (used_nodes_++ == 0) {
- NodeBlock* old_first = global_handles->first_used_block_;
- global_handles->first_used_block_ = this;
- next_used_ = old_first;
- prev_used_ = NULL;
- if (old_first == NULL) return;
- old_first->prev_used_ = this;
+ ~Pool() {
+ if (current_ != NULL) {
+ Release();
+ }
}
- }
- void DecreaseUses(GlobalHandles* global_handles) {
- ASSERT(used_nodes_ > 0);
- if (--used_nodes_ == 0) {
- if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
- if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
- if (this == global_handles->first_used_block_) {
- global_handles->first_used_block_ = next_used_;
+ Node* Allocate() {
+ if (next_ < limit_) {
+ return next_++;
}
+ return SlowAllocate();
}
- }
-
- // Next block in the list of all blocks.
- NodeBlock* next() const { return next_; }
-
- // Next/previous block in the list of blocks with used nodes.
- NodeBlock* next_used() const { return next_used_; }
- NodeBlock* prev_used() const { return prev_used_; }
-
- private:
- Node nodes_[kSize];
- NodeBlock* const next_;
- int used_nodes_;
- NodeBlock* next_used_;
- NodeBlock* prev_used_;
-};
-
-
-GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
- intptr_t ptr = reinterpret_cast<intptr_t>(this);
- ptr = ptr - index_ * sizeof(Node);
- NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr);
- ASSERT(block->node_at(index_) == this);
- return block;
-}
-
-
-void GlobalHandles::Node::IncreaseBlockUses(GlobalHandles* global_handles) {
- FindBlock()->IncreaseUses(global_handles);
-}
-
-
-void GlobalHandles::Node::DecreaseBlockUses(GlobalHandles* global_handles) {
- FindBlock()->DecreaseUses(global_handles);
-}
-
-
-class GlobalHandles::NodeIterator {
- public:
- explicit NodeIterator(GlobalHandles* global_handles)
- : block_(global_handles->first_used_block_),
- index_(0) {}
- bool done() const { return block_ == NULL; }
-
- Node* node() const {
- ASSERT(!done());
- return block_->node_at(index_);
- }
-
- void Advance() {
- ASSERT(!done());
- if (++index_ < NodeBlock::kSize) return;
- index_ = 0;
- block_ = block_->next_used();
- }
+ void Release() {
+ Chunk* current = current_;
+ ASSERT(current != NULL); // At least a single block must by allocated
+ do {
+ Chunk* previous = current->previous;
+ delete current;
+ current = previous;
+ } while (current != NULL);
+ current_ = NULL;
+ next_ = limit_ = NULL;
+ }
- private:
- NodeBlock* block_;
- int index_;
+ private:
+ static const int kNodesPerChunk = (1 << 12) - 1;
+ struct Chunk : public Malloced {
+ Chunk* previous;
+ Node nodes[kNodesPerChunk];
+ };
+
+ Node* SlowAllocate() {
+ Chunk* chunk = new Chunk();
+ chunk->previous = current_;
+ current_ = chunk;
+
+ Node* new_nodes = current_->nodes;
+ next_ = new_nodes + 1;
+ limit_ = new_nodes + kNodesPerChunk;
+ return new_nodes;
+ }
- DISALLOW_COPY_AND_ASSIGN(NodeIterator);
+ Chunk* current_;
+ Node* next_;
+ Node* limit_;
};
-GlobalHandles::GlobalHandles(Isolate* isolate)
- : isolate_(isolate),
- number_of_weak_handles_(0),
- number_of_global_object_weak_handles_(0),
- first_block_(NULL),
- first_used_block_(NULL),
- first_free_(NULL),
- post_gc_processing_count_(0) {}
-
-
-GlobalHandles::~GlobalHandles() {
- NodeBlock* block = first_block_;
- while (block != NULL) {
- NodeBlock* tmp = block->next();
- delete block;
- block = tmp;
- }
- first_block_ = NULL;
-}
+static GlobalHandles::Pool pool_;
Handle<Object> GlobalHandles::Create(Object* value) {
- isolate_->counters()->global_handles()->Increment();
- if (first_free_ == NULL) {
- first_block_ = new NodeBlock(first_block_);
- first_block_->PutNodesOnFreeList(&first_free_);
- }
- ASSERT(first_free_ != NULL);
- // Take the first node in the free list.
- Node* result = first_free_;
- first_free_ = result->next_free();
- result->Acquire(value, this);
- if (isolate_->heap()->InNewSpace(value) &&
- !result->is_in_new_space_list()) {
- new_space_nodes_.Add(result);
- result->set_in_new_space_list(true);
+ Counters::global_handles.Increment();
+ Node* result;
+ if (first_free()) {
+ // Take the first node in the free list.
+ result = first_free();
+ set_first_free(result->next_free());
+ } else if (first_deallocated()) {
+ // Next try deallocated list
+ result = first_deallocated();
+ set_first_deallocated(result->next_free());
+ ASSERT(result->next() == head());
+ set_head(result);
+ } else {
+ // Allocate a new node.
+ result = pool_.Allocate();
+ result->set_next(head());
+ set_head(result);
}
+ result->Initialize(value);
return result->handle();
}
void GlobalHandles::Destroy(Object** location) {
- isolate_->counters()->global_handles()->Decrement();
+ Counters::global_handles.Decrement();
if (location == NULL) return;
- Node::FromLocation(location)->Release(this);
+ Node* node = Node::FromLocation(location);
+ node->Destroy();
+ // Link the destroyed.
+ node->set_next_free(first_free());
+ set_first_free(node);
}
void GlobalHandles::MakeWeak(Object** location, void* parameter,
WeakReferenceCallback callback) {
ASSERT(callback != NULL);
- Node::FromLocation(location)->MakeWeak(this, parameter, callback);
+ Node::FromLocation(location)->MakeWeak(parameter, callback);
}
void GlobalHandles::ClearWeakness(Object** location) {
- Node::FromLocation(location)->ClearWeakness(this);
-}
-
-
-void GlobalHandles::MarkIndependent(Object** location) {
- Node::FromLocation(location)->MarkIndependent();
+ Node::FromLocation(location)->ClearWeakness();
}
@@ -455,174 +337,136 @@ bool GlobalHandles::IsWeak(Object** location) {
}
-void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) {
- Node::FromLocation(location)->set_wrapper_class_id(class_id);
-}
-
-
void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location());
+ // Traversal of GC roots in the global handle list that are marked as
+ // WEAK or PENDING.
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ if (current->state_ == Node::WEAK
+ || current->state_ == Node::PENDING
+ || current->state_ == Node::NEAR_DEATH) {
+ v->VisitPointer(&current->object_);
+ }
}
}
void GlobalHandles::IterateWeakRoots(WeakReferenceGuest f,
WeakReferenceCallback callback) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->IsWeak() && it.node()->callback() == callback) {
- f(it.node()->object(), it.node()->parameter());
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ if (current->IsWeak() && current->callback() == callback) {
+ f(current->object_, current->parameter());
}
}
}
void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->IsWeak() && f(it.node()->location())) {
- it.node()->MarkPending();
- }
- }
-}
-
-
-void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) {
- for (int i = 0; i < new_space_nodes_.length(); ++i) {
- Node* node = new_space_nodes_[i];
- if (node->IsStrongRetainer() ||
- (node->IsWeakRetainer() && !node->is_independent())) {
- v->VisitPointer(node->location());
- }
- }
-}
-
-
-void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles(
- WeakSlotCallbackWithHeap f) {
- for (int i = 0; i < new_space_nodes_.length(); ++i) {
- Node* node = new_space_nodes_[i];
- ASSERT(node->is_in_new_space_list());
- if (node->is_independent() && node->IsWeak() &&
- f(isolate_->heap(), node->location())) {
- node->MarkPending();
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ if (current->state_ == Node::WEAK) {
+ if (f(&current->object_)) {
+ current->state_ = Node::PENDING;
+ LOG(HandleEvent("GlobalHandle::Pending", current->handle().location()));
+ }
}
}
}
-void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
- for (int i = 0; i < new_space_nodes_.length(); ++i) {
- Node* node = new_space_nodes_[i];
- ASSERT(node->is_in_new_space_list());
- if (node->is_independent() && node->IsWeakRetainer()) {
- v->VisitPointer(node->location());
- }
- }
-}
-
+int post_gc_processing_count = 0;
-bool GlobalHandles::PostGarbageCollectionProcessing(
- GarbageCollector collector) {
+bool GlobalHandles::PostGarbageCollectionProcessing() {
// Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary
// API functions.
- ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
- const int initial_post_gc_processing_count = ++post_gc_processing_count_;
+ // At the same time deallocate all DESTROYED nodes.
+ ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
+ const int initial_post_gc_processing_count = ++post_gc_processing_count;
bool next_gc_likely_to_collect_more = false;
- if (collector == SCAVENGER) {
- for (int i = 0; i < new_space_nodes_.length(); ++i) {
- Node* node = new_space_nodes_[i];
- ASSERT(node->is_in_new_space_list());
- // Skip dependent handles. Their weak callbacks might expect to be
- // called between two global garbage collection callbacks which
- // are not called for minor collections.
- if (!node->is_independent()) continue;
- if (node->PostGarbageCollectionProcessing(isolate_, this)) {
- if (initial_post_gc_processing_count != post_gc_processing_count_) {
- // Weak callback triggered another GC and another round of
- // PostGarbageCollection processing. The current node might
- // have been deleted in that round, so we need to bail out (or
- // restart the processing).
- return next_gc_likely_to_collect_more;
- }
- }
- if (!node->IsRetainer()) {
- next_gc_likely_to_collect_more = true;
+ Node** p = &head_;
+ while (*p != NULL) {
+ if ((*p)->PostGarbageCollectionProcessing()) {
+ if (initial_post_gc_processing_count != post_gc_processing_count) {
+ // Weak callback triggered another GC and another round of
+ // PostGarbageCollection processing. The current node might
+ // have been deleted in that round, so we need to bail out (or
+ // restart the processing).
+ break;
}
}
- } else {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->PostGarbageCollectionProcessing(isolate_, this)) {
- if (initial_post_gc_processing_count != post_gc_processing_count_) {
- // See the comment above.
- return next_gc_likely_to_collect_more;
- }
- }
- if (!it.node()->IsRetainer()) {
- next_gc_likely_to_collect_more = true;
+ if ((*p)->state_ == Node::DESTROYED) {
+ // Delete the link.
+ Node* node = *p;
+ *p = node->next(); // Update the link.
+ if (first_deallocated()) {
+ first_deallocated()->set_next(node);
}
- }
- }
- // Update the list of new space nodes.
- int last = 0;
- for (int i = 0; i < new_space_nodes_.length(); ++i) {
- Node* node = new_space_nodes_[i];
- ASSERT(node->is_in_new_space_list());
- if (node->IsRetainer() && isolate_->heap()->InNewSpace(node->object())) {
- new_space_nodes_[last++] = node;
+ node->set_next_free(first_deallocated());
+ set_first_deallocated(node);
+ next_gc_likely_to_collect_more = true;
} else {
- node->set_in_new_space_list(false);
+ p = (*p)->next_addr();
}
}
- new_space_nodes_.Rewind(last);
+ set_first_free(NULL);
+ if (first_deallocated()) {
+ first_deallocated()->set_next(head());
+ }
+
return next_gc_likely_to_collect_more;
}
void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->IsStrongRetainer()) {
- v->VisitPointer(it.node()->location());
+ // Traversal of global handles marked as NORMAL.
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ if (current->state_ == Node::NORMAL) {
+ v->VisitPointer(&current->object_);
}
}
}
void GlobalHandles::IterateAllRoots(ObjectVisitor* v) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->IsRetainer()) {
- v->VisitPointer(it.node()->location());
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ if (current->state_ != Node::DESTROYED) {
+ v->VisitPointer(&current->object_);
}
}
}
-void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- if (it.node()->has_wrapper_class_id() && it.node()->IsRetainer()) {
- v->VisitEmbedderReference(it.node()->location(),
- it.node()->wrapper_class_id());
- }
- }
+void GlobalHandles::TearDown() {
+ // Reset all the lists.
+ set_head(NULL);
+ set_first_free(NULL);
+ set_first_deallocated(NULL);
+ pool_.Release();
}
+int GlobalHandles::number_of_weak_handles_ = 0;
+int GlobalHandles::number_of_global_object_weak_handles_ = 0;
+
+GlobalHandles::Node* GlobalHandles::head_ = NULL;
+GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
+GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL;
+
void GlobalHandles::RecordStats(HeapStats* stats) {
*stats->global_handle_count = 0;
*stats->weak_global_handle_count = 0;
*stats->pending_global_handle_count = 0;
*stats->near_death_global_handle_count = 0;
- *stats->free_global_handle_count = 0;
- for (NodeIterator it(this); !it.done(); it.Advance()) {
+ *stats->destroyed_global_handle_count = 0;
+ for (Node* current = head_; current != NULL; current = current->next()) {
*stats->global_handle_count += 1;
- if (it.node()->state() == Node::WEAK) {
+ if (current->state_ == Node::WEAK) {
*stats->weak_global_handle_count += 1;
- } else if (it.node()->state() == Node::PENDING) {
+ } else if (current->state_ == Node::PENDING) {
*stats->pending_global_handle_count += 1;
- } else if (it.node()->state() == Node::NEAR_DEATH) {
+ } else if (current->state_ == Node::NEAR_DEATH) {
*stats->near_death_global_handle_count += 1;
- } else if (it.node()->state() == Node::FREE) {
- *stats->free_global_handle_count += 1;
+ } else if (current->state_ == Node::DESTROYED) {
+ *stats->destroyed_global_handle_count += 1;
}
}
}
@@ -636,12 +480,12 @@ void GlobalHandles::PrintStats() {
int near_death = 0;
int destroyed = 0;
- for (NodeIterator it(this); !it.done(); it.Advance()) {
+ for (Node* current = head_; current != NULL; current = current->next()) {
total++;
- if (it.node()->state() == Node::WEAK) weak++;
- if (it.node()->state() == Node::PENDING) pending++;
- if (it.node()->state() == Node::NEAR_DEATH) near_death++;
- if (it.node()->state() == Node::FREE) destroyed++;
+ if (current->state_ == Node::WEAK) weak++;
+ if (current->state_ == Node::PENDING) pending++;
+ if (current->state_ == Node::NEAR_DEATH) near_death++;
+ if (current->state_ == Node::DESTROYED) destroyed++;
}
PrintF("Global Handle Statistics:\n");
@@ -649,73 +493,42 @@ void GlobalHandles::PrintStats() {
PrintF(" # weak = %d\n", weak);
PrintF(" # pending = %d\n", pending);
PrintF(" # near_death = %d\n", near_death);
- PrintF(" # free = %d\n", destroyed);
+ PrintF(" # destroyed = %d\n", destroyed);
PrintF(" # total = %d\n", total);
}
void GlobalHandles::Print() {
PrintF("Global handles:\n");
- for (NodeIterator it(this); !it.done(); it.Advance()) {
- PrintF(" handle %p to %p%s\n",
- reinterpret_cast<void*>(it.node()->location()),
- reinterpret_cast<void*>(it.node()->object()),
- it.node()->IsWeak() ? " (weak)" : "");
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ PrintF(" handle %p to %p (weak=%d)\n",
+ reinterpret_cast<void*>(current->handle().location()),
+ reinterpret_cast<void*>(*current->handle()),
+ current->state_ == Node::WEAK);
}
}
#endif
-
-
-void GlobalHandles::AddObjectGroup(Object*** handles,
- size_t length,
- v8::RetainedObjectInfo* info) {
-#ifdef DEBUG
- for (size_t i = 0; i < length; ++i) {
- ASSERT(!Node::FromLocation(handles[i])->is_independent());
- }
-#endif
- if (length == 0) {
- if (info != NULL) info->Dispose();
- return;
- }
- object_groups_.Add(ObjectGroup::New(handles, length, info));
+List<ObjectGroup*>* GlobalHandles::ObjectGroups() {
+ // Lazily initialize the list to avoid startup time static constructors.
+ static List<ObjectGroup*> groups(4);
+ return &groups;
}
-
-void GlobalHandles::AddImplicitReferences(HeapObject** parent,
- Object*** children,
- size_t length) {
-#ifdef DEBUG
- ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent());
- for (size_t i = 0; i < length; ++i) {
- ASSERT(!Node::FromLocation(children[i])->is_independent());
- }
-#endif
- if (length == 0) return;
- implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length));
+void GlobalHandles::AddGroup(Object*** handles, size_t length) {
+ ObjectGroup* new_entry = new ObjectGroup(length);
+ for (size_t i = 0; i < length; ++i)
+ new_entry->objects_.Add(handles[i]);
+ ObjectGroups()->Add(new_entry);
}
void GlobalHandles::RemoveObjectGroups() {
- for (int i = 0; i < object_groups_.length(); i++) {
- object_groups_.at(i)->Dispose();
- }
- object_groups_.Clear();
-}
-
-
-void GlobalHandles::RemoveImplicitRefGroups() {
- for (int i = 0; i < implicit_ref_groups_.length(); i++) {
- implicit_ref_groups_.at(i)->Dispose();
+ List<ObjectGroup*>* object_groups = ObjectGroups();
+ for (int i = 0; i< object_groups->length(); i++) {
+ delete object_groups->at(i);
}
- implicit_ref_groups_.Clear();
+ object_groups->Clear();
}
-
-void GlobalHandles::TearDown() {
- // TODO(1428): invoke weak callbacks.
-}
-
-
} } // namespace v8::internal