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

Unified Diff: src/global-handles.h

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 | « no previous file | src/global-handles.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/global-handles.h
===================================================================
--- src/global-handles.h (revision 2585)
+++ src/global-handles.h (working copy)
@@ -57,8 +57,29 @@
class GlobalHandles : public AllStatic {
public:
// Creates a new global handle that is alive until Destroy is called.
- static Handle<Object> Create(Object* value);
+ static Handle<Object> Create(Object* value) {
+ 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());
+ set_head(result);
+ } else {
+ // Allocate a new node.
+ result = pool_.Allocate();
+ result->set_next(head());
+ set_head(result);
+ }
+ result->Initialize(value);
+ return result->handle();
+ }
+
// Destroy a global handle.
static void Destroy(Object** location);
@@ -123,8 +144,156 @@
#endif
private:
// Internal node structure, one for each global handle.
- class Node;
+ class Node {
+ public:
+ // 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
+ };
+ Node() { state_ = DESTROYED; }
+
+ 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 Initialize(Object* object) {
+ // Set the initial value of the handle.
+ object_ = object;
+ state_ = NORMAL;
+ parameter_or_next_free_.parameter = NULL;
+ callback_ = NULL;
+ }
+
+ void Destroy();
+
+ // 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);
+ void ClearWeakness();
+
+ 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();
+
+ // Place the handle address first to avoid offset computation.
+ Object* object_; // Storage for object pointer.
+
+ 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")
+ };
+
+
+ class Pool BASE_EMBEDDED {
+ public:
+ Pool() {
+ current_ = new Chunk();
+ current_->previous = NULL;
+ next_ = current_->nodes;
+ limit_ = current_->nodes + kNodesPerChunk;
+ }
+
+ Node* Allocate() {
+ if (next_ < limit_) {
+ return next_++;
+ }
+ return SlowAllocate();
+ }
+
+ void Release();
+
+ private:
+ static const int kNodesPerChunk = 8192;
+ struct Chunk : public Malloced {
+ Chunk* previous;
+ Node nodes[kNodesPerChunk];
+ };
+
+ Node* SlowAllocate();
+
+ Chunk* current_;
+ Node* next_;
+ Node* limit_;
+ };
+
+ static Pool pool_;
+
+
// Field always containing the number of weak and near-death handles.
static int number_of_weak_handles_;
@@ -142,6 +311,15 @@
static Node* first_free_;
static Node* first_free() { return first_free_; }
static void set_first_free(Node* value) { first_free_ = value; }
+
+ // List of deallocated nodes. Even though they are deallocated,
+ // they keep correct next pointers, so allocating it back is just a matter
+ // of setting head to it (and ajusting |first_deallocated_|)
+ static Node* first_deallocated_;
+ static Node* first_deallocated() { return first_deallocated_; }
+ static void set_first_deallocated(Node* value) {
+ first_deallocated_ = value;
+ }
};
« no previous file with comments | « no previous file | src/global-handles.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698