Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Unified Diff: src/global-handles.cc

Issue 155540: Fasten global handles allocation. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/global-handles.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/global-handles.cc
===================================================================
--- src/global-handles.cc (revision 2585)
+++ src/global-handles.cc (working copy)
@@ -33,186 +33,6 @@
namespace v8 {
namespace internal {
-class GlobalHandles::Node : public Malloced {
- public:
-
- void Initialize(Object* object) {
- // Set the initial value of the handle.
- object_ = object;
- state_ = NORMAL;
- parameter_or_next_free_.parameter = NULL;
- callback_ = NULL;
- }
-
- explicit Node(Object* object) {
- Initialize(object);
- // Initialize link structure.
- next_ = NULL;
- }
-
- ~Node() {
- if (state_ != DESTROYED) Destroy();
-#ifdef DEBUG
- // Zap the values for eager trapping.
- object_ = NULL;
- next_ = NULL;
- parameter_or_next_free_.next_free = NULL;
-#endif
- }
-
- void Destroy() {
- if (state_ == WEAK || IsNearDeath()) {
- GlobalHandles::number_of_weak_handles_--;
- if (object_->IsJSGlobalObject()) {
- GlobalHandles::number_of_global_object_weak_handles_--;
- }
- }
- state_ = DESTROYED;
- }
-
- // 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_ == DESTROYED);
- return parameter_or_next_free_.next_free;
- }
- void set_next_free(Node* value) {
- ASSERT(state_ == DESTROYED);
- parameter_or_next_free_.next_free = value;
- }
-
- // 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()) {
- GlobalHandles::number_of_global_object_weak_handles_++;
- }
- }
- state_ = WEAK;
- set_parameter(parameter);
- callback_ = callback;
- }
-
- void ClearWeakness() {
- LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
- ASSERT(state_ != DESTROYED);
- if (state_ == WEAK || IsNearDeath()) {
- GlobalHandles::number_of_weak_handles_--;
- if (object_->IsJSGlobalObject()) {
- GlobalHandles::number_of_global_object_weak_handles_--;
- }
- }
- state_ = NORMAL;
- set_parameter(NULL);
- }
-
- 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_; }
-
- void PostGarbageCollectionProcessing() {
- if (state_ != Node::PENDING) return;
- LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
- void* par = parameter();
- state_ = NEAR_DEATH;
- set_parameter(NULL);
- // The callback function is resolved as late as possible to preserve old
- // behavior.
- WeakReferenceCallback func = callback();
- if (func != NULL) {
- v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
- {
- // Leaving V8.
- VMState state(EXTERNAL);
- func(object, par);
- }
- }
- }
-
- // Place the handle address first to avoid offset computation.
- Object* object_; // Storage for object pointer.
-
- // 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 DESTROYED state, this is used for
- // the free list link.
- union {
- void* parameter;
- Node* next_free;
- } parameter_or_next_free_;
-
- // Linkage for the list.
- Node* next_;
-
- public:
- TRACK_MEMORY("GlobalHandles::Node")
-};
-
-
-Handle<Object> GlobalHandles::Create(Object* value) {
- Counters::global_handles.Increment();
- Node* result;
- if (first_free() == NULL) {
- // Allocate a new node.
- result = new Node(value);
- result->set_next(head());
- set_head(result);
- } else {
- // Take the first node in the free list.
- result = first_free();
- set_first_free(result->next_free());
- result->Initialize(value);
- }
- return result->handle();
-}
-
-
void GlobalHandles::Destroy(Object** location) {
Counters::global_handles.Decrement();
if (location == NULL) return;
@@ -275,7 +95,7 @@
// Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary
// API functions.
- // At the same time deallocate all DESTROYED nodes
+ // At the same time deallocate all DESTROYED nodes.
ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
Node** p = &head_;
while (*p != NULL) {
@@ -284,12 +104,19 @@
// Delete the link.
Node* node = *p;
*p = node->next(); // Update the link.
- delete node;
+ if (first_deallocated()) {
+ first_deallocated()->set_next(node);
+ }
+ node->set_next_free(first_deallocated());
+ set_first_deallocated(node);
} else {
p = (*p)->next_addr();
}
}
set_first_free(NULL);
+ if (first_deallocated()) {
+ first_deallocated()->set_next(head());
+ }
}
@@ -303,16 +130,11 @@
}
void GlobalHandles::TearDown() {
- // Delete all the nodes in the linked list.
- Node* current = head_;
- while (current != NULL) {
- Node* n = current;
- current = current->next();
- delete n;
- }
- // Reset the head and free_list.
+ // Reset all the lists.
set_head(NULL);
set_first_free(NULL);
+ set_first_deallocated(NULL);
+ pool_.Release();
}
@@ -321,7 +143,10 @@
GlobalHandles::Node* GlobalHandles::head_ = NULL;
GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
+GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL;
+GlobalHandles::Pool GlobalHandles::pool_;
+
#ifdef DEBUG
void GlobalHandles::PrintStats() {
@@ -381,4 +206,90 @@
}
+void GlobalHandles::Node::Destroy() {
+ if (state_ == WEAK || IsNearDeath()) {
+ GlobalHandles::number_of_weak_handles_--;
+ if (object_->IsJSGlobalObject()) {
+ GlobalHandles::number_of_global_object_weak_handles_--;
+ }
+ }
+ state_ = DESTROYED;
+}
+
+
+void GlobalHandles::Node::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()) {
+ GlobalHandles::number_of_global_object_weak_handles_++;
+ }
+ }
+ state_ = WEAK;
+ set_parameter(parameter);
+ callback_ = callback;
+}
+
+
+void GlobalHandles::Node::ClearWeakness() {
+ LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
+ ASSERT(state_ != DESTROYED);
+ if (state_ == WEAK || IsNearDeath()) {
+ GlobalHandles::number_of_weak_handles_--;
+ if (object_->IsJSGlobalObject()) {
+ GlobalHandles::number_of_global_object_weak_handles_--;
+ }
+ }
+ state_ = NORMAL;
+ set_parameter(NULL);
+}
+
+
+void GlobalHandles::Node::PostGarbageCollectionProcessing() {
+ if (state_ != Node::PENDING) return;
+ LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
+ void* par = parameter();
+ state_ = NEAR_DEATH;
+ set_parameter(NULL);
+ // The callback function is resolved as late as possible to preserve old
+ // behavior.
+ WeakReferenceCallback func = callback();
+ if (func != NULL) {
+ v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
+ {
+ // Leaving V8.
+ VMState state(EXTERNAL);
+ func(object, par);
+ }
+ }
+}
+
+
+GlobalHandles::Node* GlobalHandles::Pool::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;
+}
+
+
+void GlobalHandles::Pool::Release() {
+ Chunk* current = current_;
+ ASSERT(current != NULL); // At least a single block must be allocated
+ do {
+ Chunk* previous = current->previous;
+ delete current;
+ current = previous;
+ } while (current != NULL);
+ current_ = NULL;
+ next_ = limit_ = NULL;
+}
+
+
} } // namespace v8::internal
« no previous file with comments | « src/global-handles.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698