Author: [email protected]
Date: Wed Mar 18 11:50:35 2009
New Revision: 1539

Modified:
    branches/bleeding_edge/src/handles.cc
    branches/bleeding_edge/src/handles.h
    branches/bleeding_edge/src/stub-cache.cc

Log:
Inline the fast path for handle creation.

Simplify the interceptor IC code by using raw pointers instead of handles.
Review URL: http://codereview.chromium.org/49001

Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc       (original)
+++ branches/bleeding_edge/src/handles.cc       Wed Mar 18 11:50:35 2009
@@ -52,44 +52,39 @@
  }


-void** HandleScope::CreateHandle(void* value) {
+void** HandleScope::Extend() {
    void** result = current_.next;
-  if (result == current_.limit) {
-    // Make sure there's at least one scope on the stack and that the
-    // top of the scope stack isn't a barrier.
-    if (current_.extensions < 0) {
-      Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
-                              "Cannot create a handle without a  
HandleScope");
-      return NULL;
-    }
-    HandleScopeImplementer* impl = HandleScopeImplementer::instance();
-    // If there's more room in the last block, we use that. This is used
-    // for fast creation of scopes after scope barriers.
-    if (!impl->Blocks()->is_empty()) {
-      void** limit = &impl->Blocks()->last()[kHandleBlockSize];
-      if (current_.limit != limit) {
-        current_.limit = limit;
-      }
-    }

-    // If we still haven't found a slot for the handle, we extend the
-    // current handle scope by allocating a new handle block.
-    if (result == current_.limit) {
-      // If there's a spare block, use it for growing the current scope.
-      result = impl->GetSpareOrNewBlock();
-      // Add the extension to the global list of blocks, but count the
-      // extension as part of the current scope.
-      impl->Blocks()->Add(result);
-      current_.extensions++;
-      current_.limit = &result[kHandleBlockSize];
+  ASSERT(result == current_.limit);
+  // Make sure there's at least one scope on the stack and that the
+  // top of the scope stack isn't a barrier.
+  if (current_.extensions < 0) {
+    Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
+                            "Cannot create a handle without a  
HandleScope");
+    return NULL;
+  }
+  HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+  // If there's more room in the last block, we use that. This is used
+  // for fast creation of scopes after scope barriers.
+  if (!impl->Blocks()->is_empty()) {
+    void** limit = &impl->Blocks()->last()[kHandleBlockSize];
+    if (current_.limit != limit) {
+      current_.limit = limit;
      }
    }
+
+  // If we still haven't found a slot for the handle, we extend the
+  // current handle scope by allocating a new handle block.
+  if (result == current_.limit) {
+    // If there's a spare block, use it for growing the current scope.
+    result = impl->GetSpareOrNewBlock();
+    // Add the extension to the global list of blocks, but count the
+    // extension as part of the current scope.
+    impl->Blocks()->Add(result);
+    current_.extensions++;
+    current_.limit = &result[kHandleBlockSize];
+  }

-  // Update the current next field, set the value in the created
-  // handle, and return the result.
-  ASSERT(result < current_.limit);
-  current_.next = result + 1;
-  *result = value;
    return result;
  }


Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h        (original)
+++ branches/bleeding_edge/src/handles.h        Wed Mar 18 11:50:35 2009
@@ -118,7 +118,16 @@
    static int NumberOfHandles();

    // Creates a new handle with the given value.
-  static void** CreateHandle(void* value);
+  static inline void** CreateHandle(void* value) {
+    void** result = current_.next;
+    if (result == current_.limit) result = Extend();
+    // Update the current next field, set the value in the created
+    // handle, and return the result.
+    ASSERT(result < current_.limit);
+    current_.next = result + 1;
+    *result = value;
+    return result;
+  }

   private:
    // Prevent heap allocation or illegal handle scopes.
@@ -149,6 +158,9 @@
      ZapRange(current_.next, current_.limit);
  #endif
    }
+
+  // Extend the handle scope making room for more handles.
+  static void** Extend();

    // Deallocates any extensions used by the current scope.
    static void DeleteExtensions();

Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc    (original)
+++ branches/bleeding_edge/src/stub-cache.cc    Wed Mar 18 11:50:35 2009
@@ -656,9 +656,8 @@
  Object* LoadCallbackProperty(Arguments args) {
    Handle<JSObject> recv = args.at<JSObject>(0);
    AccessorInfo* callback = AccessorInfo::cast(args[1]);
-  v8::AccessorGetter fun =
-      FUNCTION_CAST<v8::AccessorGetter>(
-          v8::ToCData<Address>(callback->getter()));
+  Address getter_address = v8::ToCData<Address>(callback->getter());
+  v8::AccessorGetter fun =  
FUNCTION_CAST<v8::AccessorGetter>(getter_address);
    ASSERT(fun != NULL);
    Handle<String> name = args.at<String>(2);
    Handle<JSObject> holder = args.at<JSObject>(3);
@@ -669,10 +668,9 @@
    // locations of the arguments to this function maybe we don't have
    // to explicitly create the structure but can just pass a pointer
    // into the stack.
-  v8::AccessorInfo info(
-    v8::Utils::ToLocal(recv),
-    v8::Utils::ToLocal(data),
-    v8::Utils::ToLocal(holder));
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(holder));
    v8::Handle<v8::Value> result;
    {
      // Leaving JavaScript.
@@ -680,30 +678,25 @@
      result = fun(v8::Utils::ToLocal(name), info);
    }
    RETURN_IF_SCHEDULED_EXCEPTION();
-  if (result.IsEmpty()) {
-    return Heap::undefined_value();
-  } else {
-    return *v8::Utils::OpenHandle(*result);
-  }
+  if (result.IsEmpty()) return Heap::undefined_value();
+  return *v8::Utils::OpenHandle(*result);
  }


  Object* StoreCallbackProperty(Arguments args) {
    Handle<JSObject> recv = args.at<JSObject>(0);
    AccessorInfo* callback = AccessorInfo::cast(args[1]);
-  v8::AccessorSetter fun =
-      FUNCTION_CAST<v8::AccessorSetter>(
-          v8::ToCData<Address>(callback->setter()));
+  Address setter_address = v8::ToCData<Address>(callback->setter());
+  v8::AccessorSetter fun =  
FUNCTION_CAST<v8::AccessorSetter>(setter_address);
    ASSERT(fun != NULL);
    Handle<String> name = args.at<String>(2);
    Handle<Object> value = args.at<Object>(3);
    HandleScope scope;
    Handle<Object> data(callback->data());
    LOG(ApiNamedPropertyAccess("store", *recv, *name));
-  v8::AccessorInfo info(
-    v8::Utils::ToLocal(recv),
-    v8::Utils::ToLocal(data),
-    v8::Utils::ToLocal(recv));
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(recv));
    {
      // Leaving JavaScript.
      VMState state(OTHER);
@@ -715,28 +708,17 @@


  Object* LoadInterceptorProperty(Arguments args) {
-  HandleScope scope;
-  Handle<JSObject> recv = args.at<JSObject>(0);
-  Handle<JSObject> holder = args.at<JSObject>(1);
-  Handle<String> name = args.at<String>(2);
+  JSObject* recv = JSObject::cast(args[0]);
+  JSObject* holder = JSObject::cast(args[1]);
+  String* name = String::cast(args[2]);
    ASSERT(holder->HasNamedInterceptor());
    PropertyAttributes attr = NONE;
-  Handle<Object> result = GetPropertyWithInterceptor(recv, holder, name,  
&attr);
+  Object* result = holder->GetPropertyWithInterceptor(recv, name, &attr);

-  // GetPropertyWithInterceptor already converts a scheduled exception
-  // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION()  
here.
-
-  // Make sure to propagate exceptions.
-  if (result.is_null())  {
-    // Failure::Exception is converted to a null handle in the
-    // handle-based methods such as SetProperty.  We therefore need
-    // to convert null handles back to exceptions.
-    ASSERT(Top::has_pending_exception());
-    return Failure::Exception();
-  }
+  if (result->IsFailure()) return result;

    // If the property is present, return it.
-  if (attr != ABSENT) return *result;
+  if (attr != ABSENT) return result;

    // If the top frame is an internal frame, this is really a call
    // IC. In this case, we simply return the undefined result which
@@ -744,43 +726,38 @@
    // function.
    StackFrameIterator it;
    it.Advance();  // skip exit frame
-  if (it.frame()->is_internal()) return *result;
+  if (it.frame()->is_internal()) return result;

    // If the load is non-contextual, just return the undefined result.
    // Note that both keyed and non-keyed loads may end up here, so we
    // can't use either LoadIC or KeyedLoadIC constructors.
    IC ic(IC::NO_EXTRA_FRAME);
    ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
-  if (!ic.is_contextual()) return *result;
+  if (!ic.is_contextual()) return result;

    // Throw a reference error.
-  Handle<Object> error =
-      Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
-  return Top::Throw(*error);
+  {
+    HandleScope scope;
+    // We cannot use the raw name pointer here since getting the
+    // property might cause a GC.  However, we can get the name from
+    // the stack using the arguments object.
+    Handle<String> name_handle = args.at<String>(2);
+    Handle<Object> error =
+        Factory::NewReferenceError("not_defined",
+                                   HandleVector(&name_handle, 1));
+    return Top::Throw(*error);
+  }
  }


  Object* StoreInterceptorProperty(Arguments args) {
-  HandleScope scope;
-  Handle<JSObject> recv = args.at<JSObject>(0);
-  Handle<String> name = args.at<String>(1);
-  Handle<Object> value = args.at<Object>(2);
+  JSObject* recv = JSObject::cast(args[0]);
+  String* name = String::cast(args[1]);
+  Object* value = args[2];
    ASSERT(recv->HasNamedInterceptor());
    PropertyAttributes attr = NONE;
-  Handle<Object> result = SetPropertyWithInterceptor(recv, name, value,  
attr);
-
-  // SetPropertyWithInterceptor already converts a scheduled exception
-  // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION()  
here.
-
-  // Make sure to propagate exceptions.
-  if (result.is_null()) {
-    // Failure::Exception is converted to a null handle in the
-    // handle-based methods such as SetProperty.  We therefore need
-    // to convert null handles back to exceptions.
-    ASSERT(Top::has_pending_exception());
-    return Failure::Exception();
-  }
-  return *result;
+  Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
+  return result;
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to