[V8] toV8(Node*, ...) does more work than needed (6% faster on dom-traverse)
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Oct 2012 02:08:50 +0000 (02:08 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Oct 2012 02:08:50 +0000 (02:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=98567

Reviewed by Kentaro Hara.

This patch introduces toV8Fast for Node*. This function works a
differently from the existing toV8 function in two ways:

1) It uses the inline wrapper cache in Node to determine if we're
   executing in the main world. This is faster both in the case when
   isolated worlds exist because we don't need to retrieve any state
   for the current context.

2) It doesn't attempt to inline the hash table lookup used to find the
   wrapper in the isolated world. There isn't a big need to inline this
   code since performance in the isolated world case is dominated by
   the hash table lookup.

Because of these two changes, toV8Fast is small enough to inline into
each attribute getter profitably. Over time, I would like to convert
all the performance critical uses of toV8(Node*) to toV8Fast. At that
point, we can delete toV8 and rename toV8Slow to toV8.

* bindings/scripts/CodeGeneratorV8.pm:
(GenerateHeader):
(GenerateNormalAttrGetter):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@130574 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/bindings/scripts/CodeGeneratorV8.pm

index 420e1d6..74ed80d 100644 (file)
@@ -1,3 +1,32 @@
+2012-10-05  Adam Barth  <abarth@webkit.org>
+
+        [V8] toV8(Node*, ...) does more work than needed (6% faster on dom-traverse)
+        https://bugs.webkit.org/show_bug.cgi?id=98567
+
+        Reviewed by Kentaro Hara.
+
+        This patch introduces toV8Fast for Node*. This function works a
+        differently from the existing toV8 function in two ways:
+
+        1) It uses the inline wrapper cache in Node to determine if we're
+           executing in the main world. This is faster both in the case when
+           isolated worlds exist because we don't need to retrieve any state
+           for the current context.
+
+        2) It doesn't attempt to inline the hash table lookup used to find the
+           wrapper in the isolated world. There isn't a big need to inline this
+           code since performance in the isolated world case is dominated by
+           the hash table lookup.
+
+        Because of these two changes, toV8Fast is small enough to inline into
+        each attribute getter profitably. Over time, I would like to convert
+        all the performance critical uses of toV8(Node*) to toV8Fast. At that
+        point, we can delete toV8 and rename toV8Slow to toV8.
+
+        * bindings/scripts/CodeGeneratorV8.pm:
+        (GenerateHeader):
+        (GenerateNormalAttrGetter):
+
 2012-10-05  Huang Dongsung  <luxtella@company100.net>
 
         [mac] REGRESSION (r122215): Animated GIF outside the viewport doesn't play when scrolled into view.
index 551258c..3066596 100644 (file)
@@ -525,6 +525,20 @@ inline v8::Handle<v8::Value> toV8(Node* impl, v8::Handle<v8::Object> creationCon
         return wrapper;
     return toV8Slow(impl, creationContext, isolate);
 }
+
+inline v8::Handle<v8::Value> toV8Fast(Node* node, const v8::AccessorInfo& info, Node* holder)
+{
+    if (UNLIKELY(!node))
+        return v8::Null(info.GetIsolate());
+    // What we'd really like to check here is whether we're in the main world or
+    // in an isolated world. The fastest way we know how to do that is to check
+    // whether the holder's inline wrapper is the same wrapper we see in the
+    // v8::AccessorInfo.
+    v8::Handle<v8::Object> holderWrapper = info.Holder();
+    if (holder->wrapper() && *holder->wrapper() == holderWrapper && node->wrapper())
+        return *node->wrapper();
+    return toV8Slow(node, holderWrapper, info.GetIsolate());
+}
 END
     }
 
@@ -1062,18 +1076,19 @@ END
         portArray->Set(v8Integer(i, info.GetIsolate()), toV8(portsCopy[i].get(), info.Holder(), info.GetIsolate()));
     return portArray;
 END
-    } else {
-        if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
-            my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
-            push(@implContentDecls, <<END);
+    } elsif ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
+        my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
+        push(@implContentDecls, <<END);
     SerializedScriptValue* serialized = imp->${getterFunc}();
     value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));
     info.Holder()->SetHiddenValue(propertyName, value);
     return value;
 END
-        } else {
-            push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "info.Holder()", "info.GetIsolate()").";\n");
-        }
+    } elsif (IsDOMNodeType(GetTypeFromSignature($attribute->signature)) && $implClassName eq "Node") {
+        # FIXME: We would like to use toV8Fast in more situations.
+        push(@implContentDecls, "    return toV8Fast($result, info, imp);\n");
+    } else {
+        push(@implContentDecls, "    " . ReturnNativeToJSValue($attribute->signature, $result, "info.Holder()", "info.GetIsolate()").";\n");
     }
 
     push(@implContentDecls, "}\n\n");  # end of getter