Remove HandleCell and use GlobalHandle and HandleScope::Escape instead.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 1 Mar 2011 14:00:55 +0000 (14:00 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 1 Mar 2011 14:00:55 +0000 (14:00 +0000)
Added HandleScope::Escape to HandleScope to allow exiting a value
from a scope.

Review URL: http://codereview.chromium.org/6594075

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/handles-inl.h
src/handles.h
src/runtime.cc

index 1811023..c0f2fda 100644 (file)
@@ -51,16 +51,6 @@ inline T* Handle<T>::operator*() const {
 }
 
 
-template <typename T>
-HandleCell<T>::HandleCell(T* value)
-    : location_(HandleScope::CreateHandle(value)) { }
-
-
-template <typename T>
-HandleCell<T>::HandleCell(Handle<T> value)
-    : location_(HandleScope::CreateHandle(*value)) { }
-
-
 #ifdef DEBUG
 inline NoHandleAllocation::NoHandleAllocation() {
   v8::ImplementationUtilities::HandleScopeData* current =
index 8f1664b..50b2d3f 100644 (file)
@@ -93,55 +93,6 @@ class Handle {
 };
 
 
-// A handle-scope based variable. The value stored in the variable can change
-// over time. The value stored in the variable at any time is a root
-// for garbage collection.
-// The variable is backed by the current HandleScope.
-template <typename T>
-class HandleCell {
- public:
-  // Create a new HandleCell holding the given value.
-  explicit HandleCell(Handle<T> value);
-  explicit HandleCell(T* value);
-
-  // Create an alias of an existing HandleCell.
-  explicit HandleCell(const HandleCell<T>& value)
-      : location_(value.location_) { }
-
-  INLINE(T* operator->() const) { return operator*(); }
-  INLINE(T* operator*() const) {
-    return *location_;
-  }
-  INLINE(void operator=(T* value)) {
-    *location_ = value;
-  }
-  INLINE(void operator=(Handle<T> value)) {
-    *location_ = *value;
-  }
-  INLINE(void operator=(const HandleCell<T>& value)) {
-    *location_ = *value.location_;
-  }
-
-  // Extract the value of the variable and cast it to a give type.
-  // This is typically used for calling methods on a more specialized type.
-  template <typename S>
-  inline S* cast() {
-    S::cast(*location_);
-    return *reinterpret_cast<S**>(location_);
-  }
-
-  Handle<T> ToHandle() const {
-    return Handle<T>(*location_);
-  }
-
- private:
-  // Prevent implicit constructor from being created.
-  HandleCell();
-
-  T** location_;
-};
-
-
 // A stack-allocated class that governs a number of local handles.
 // After a handle scope has been created, all local handles will be
 // allocated within that handle scope until either the handle scope is
@@ -161,15 +112,7 @@ class HandleScope {
   }
 
   ~HandleScope() {
-    current_.next = prev_next_;
-    current_.level--;
-    if (current_.limit != prev_limit_) {
-      current_.limit = prev_limit_;
-      DeleteExtensions();
-    }
-#ifdef DEBUG
-    ZapRange(prev_next_, prev_limit_);
-#endif
+    CloseScope();
   }
 
   // Counts the number of allocated handles.
@@ -197,6 +140,26 @@ class HandleScope {
   static Address current_limit_address();
   static Address current_level_address();
 
+  // Closes the HandleScope (invalidating all handles
+  // created in the scope of the HandleScope) and returns
+  // a Handle backed by the parent scope holding the
+  // value of the argument handle.
+  template <typename T>
+  Handle<T> CloseAndEscape(Handle<T> handle_value) {
+    T* value = *handle_value;
+    // Throw away all handles in the current scope.
+    CloseScope();
+    // Allocate one handle in the parent scope.
+    ASSERT(current_.level > 0);
+    Handle<T> result(CreateHandle<T>(value));
+    // Reinitialize the current scope (so that it's ready
+    // to be used or closed again).
+    prev_next_ = current_.next;
+    prev_limit_ = current_.limit;
+    current_.level++;
+    return result;
+  }
+
  private:
   // Prevent heap allocation or illegal handle scopes.
   HandleScope(const HandleScope&);
@@ -204,9 +167,23 @@ class HandleScope {
   void* operator new(size_t size);
   void operator delete(void* size_t);
 
+  inline void CloseScope() {
+    current_.next = prev_next_;
+    current_.level--;
+    if (current_.limit != prev_limit_) {
+      current_.limit = prev_limit_;
+      DeleteExtensions();
+    }
+#ifdef DEBUG
+    ZapRange(prev_next_, prev_limit_);
+#endif
+  }
+
   static v8::ImplementationUtilities::HandleScopeData current_;
-  Object** const prev_next_;
-  Object** const prev_limit_;
+  // Holds values on entry. The prev_next_ value is never NULL
+  // on_entry, but is set to NULL when this scope is closed.
+  Object** prev_next_;
+  Object** prev_limit_;
 
   // Extend the handle scope making room for more handles.
   static internal::Object** Extend();
index 1412389..fdbd5af 100644 (file)
@@ -40,6 +40,7 @@
 #include "debug.h"
 #include "deoptimizer.h"
 #include "execution.h"
+#include "global-handles.h"
 #include "jsregexp.h"
 #include "liveedit.h"
 #include "parser.h"
@@ -8041,10 +8042,14 @@ class ArrayConcatVisitor {
  public:
   ArrayConcatVisitor(Handle<FixedArray> storage,
                      bool fast_elements) :
-      storage_(storage),
+    storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))),
       index_offset_(0u),
       fast_elements_(fast_elements) { }
 
+  ~ArrayConcatVisitor() {
+    clear_storage();
+  }
+
   void visit(uint32_t i, Handle<Object> elm) {
     if (i >= JSObject::kMaxElementCount - index_offset_) return;
     uint32_t index = index_offset_ + i;
@@ -8062,11 +8067,13 @@ class ArrayConcatVisitor {
       // Fall-through to dictionary mode.
     }
     ASSERT(!fast_elements_);
-    Handle<NumberDictionary> dict(storage_.cast<NumberDictionary>());
+    Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_));
     Handle<NumberDictionary> result =
         Factory::DictionaryAtNumberPut(dict, index, elm);
     if (!result.is_identical_to(dict)) {
-      storage_ = Handle<FixedArray>::cast(result);
+      // Dictionary needed to grow.
+      clear_storage();
+      set_storage(*result);
     }
 }
 
@@ -8098,23 +8105,35 @@ class ArrayConcatVisitor {
   // Convert storage to dictionary mode.
   void SetDictionaryMode(uint32_t index) {
     ASSERT(fast_elements_);
-    Handle<FixedArray> current_storage(storage_.ToHandle());
-    HandleCell<NumberDictionary> slow_storage(
+    Handle<FixedArray> current_storage(*storage_);
+    Handle<NumberDictionary> slow_storage(
         Factory::NewNumberDictionary(current_storage->length()));
     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
     for (uint32_t i = 0; i < current_length; i++) {
       HandleScope loop_scope;
       Handle<Object> element(current_storage->get(i));
       if (!element->IsTheHole()) {
-        slow_storage =
-          Factory::DictionaryAtNumberPut(slow_storage.ToHandle(), i, element);
+        Handle<NumberDictionary> new_storage =
+          Factory::DictionaryAtNumberPut(slow_storage, i, element);
+        if (!new_storage.is_identical_to(slow_storage)) {
+          slow_storage = loop_scope.CloseAndEscape(new_storage);
+        }
       }
     }
-    storage_ = slow_storage.cast<FixedArray>();
+    clear_storage();
+    set_storage(*slow_storage);
     fast_elements_ = false;
   }
 
-  HandleCell<FixedArray> storage_;
+  inline void clear_storage() {
+    GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
+  }
+
+  inline void set_storage(FixedArray* storage) {
+    storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage));
+  }
+
+  Handle<FixedArray> storage_;  // Always a global handle.
   // Index after last seen index. Always less than or equal to
   // JSObject::kMaxElementCount.
   uint32_t index_offset_;