The last of the V8 binding optimizations.
authorsnej@chromium.org <snej@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Nov 2009 00:17:26 +0000 (00:17 +0000)
committersnej@chromium.org <snej@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Nov 2009 00:17:26 +0000 (00:17 +0000)
- Replace string-valued element accessors with a shared getter/setter function.
- Change error handling flow of control to avoid extra branches and function calls.
https://bugs.webkit.org/show_bug.cgi?id=31443

Reviewed by Dimitri Glazkov.

* bindings/scripts/CodeGeneratorV8.pm:
* bindings/v8/V8Binding.cpp:
(WebCore::getElementStringAttr):  Body of string-valued Element getter function.
(WebCore::setElementStringAttr):  Body of string-valued Element setter function.
* bindings/v8/V8Binding.h:

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

WebCore/ChangeLog
WebCore/bindings/scripts/CodeGeneratorV8.pm
WebCore/bindings/v8/V8Binding.cpp
WebCore/bindings/v8/V8Binding.h

index 889af0bf0fd334ff795273a6712ca1b25d9da3b6..3f69169220abcf8935932a7c47eaef742bcf6411 100644 (file)
@@ -1,3 +1,18 @@
+2009-11-12  Jens Alfke  <snej@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        The last of the V8 binding optimizations.
+        - Replace string-valued element accessors with a shared getter/setter function.
+        - Change error handling flow of control to avoid extra branches and function calls.
+        https://bugs.webkit.org/show_bug.cgi?id=31443
+        
+        * bindings/scripts/CodeGeneratorV8.pm:
+        * bindings/v8/V8Binding.cpp:
+        (WebCore::getElementStringAttr):  Body of string-valued Element getter function.
+        (WebCore::setElementStringAttr):  Body of string-valued Element setter function.
+        * bindings/v8/V8Binding.h:
+
 2009-11-12  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Oliver Hunt.
index bd609714f9ccc1ea82ef1e0f02b586501c8fa41a..18141d6e07a6f017d87f23c2da6f991558b8b842 100644 (file)
@@ -528,6 +528,18 @@ END
       }
         HolderToNative($dataNode, $implClassName, $classIndex, "info");
     } else {
+        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
+        if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
+            # Generate super-compact call for regular attribute getter:
+            my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
+            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
+            $implIncludes{"${namespace}.h"} = 1;
+            push(@implContentDecls, "    return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
+            push(@implContentDecls, "  }\n\n");
+            return;
+            # Skip the rest of the function!
+        }
+        
         push(@implContentDecls, <<END);
     v8::Handle<v8::Object> holder = info.Holder();
 END
@@ -709,6 +721,20 @@ END
       }
         HolderToNative($dataNode, $implClassName, $classIndex, "info");
     } else {
+        my $attrType = GetTypeFromSignature($attribute->signature);
+        my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
+        my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
+        if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
+            # Generate super-compact call for regular attribute setter:
+            my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
+            my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
+            $implIncludes{"${namespace}.h"} = 1;
+            push(@implContentDecls, "    setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
+            push(@implContentDecls, "  }\n\n");
+            return;
+            # Skip the rest of the function!
+        }
+
         push(@implContentDecls, <<END);
     v8::Handle<v8::Object> holder = info.Holder();
 END
@@ -871,11 +897,23 @@ END
 "      return v8::Handle<v8::Value>();\n" .
 "    }\n");
     }
+    
+    my $raisesExceptions = @{$function->raisesExceptions};
+    if (!$raisesExceptions) {
+        foreach my $parameter (@{$function->parameters}) {
+            if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
+                $raisesExceptions = 1;
+            }
+        }
+    }
 
-
-    if (@{$function->raisesExceptions}) {
+    if ($raisesExceptions) {
         $implIncludes{"ExceptionCode.h"} = 1;
         push(@implContentDecls, "    ExceptionCode ec = 0;\n");
+        push(@implContentDecls, "    {\n");
+        # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
+        # of objects (like Strings) declared later, causing compile errors. The block scope ends
+        # right before the label 'fail:'.
     }
 
     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
@@ -917,8 +955,8 @@ END
             $implIncludes{"ExceptionCode.h"} = 1;
             push(@implContentDecls,
 "    if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
-"      V8Proxy::setDOMException(TYPE_MISMATCH_ERR);\n" .
-"      return v8::Handle<v8::Value>();\n" .
+"      ec = TYPE_MISMATCH_ERR;\n" .
+"      goto fail;\n" .
 "    }\n");
         }
 
@@ -926,8 +964,8 @@ END
             $implIncludes{"ExceptionCode.h"} = 1;
             push(@implContentDecls,
 "    if (UNLIKELY($parameterName < 0)) {\n" .
-"      V8Proxy::setDOMException(INDEX_SIZE_ERR);\n" .
-"      return v8::Handle<v8::Value>();\n" .
+"      ec = INDEX_SIZE_ERR;\n" .
+"      goto fail;\n" .
 "    }\n");
         }
 
@@ -937,6 +975,14 @@ END
     # Build the function call string.
     my $callString = GenerateFunctionCallString($function, $paramIndex, "    ", $implClassName);
     push(@implContentDecls, "$callString");
+
+    if ($raisesExceptions) {
+        push(@implContentDecls, "    }\n");
+        push(@implContentDecls, "  fail:\n");
+        push(@implContentDecls, "    V8Proxy::setDOMException(ec);\n");
+        push(@implContentDecls, "    return v8::Handle<v8::Value>();\n");
+    }
+    
     push(@implContentDecls, "  }\n\n");
 }
 
@@ -1591,7 +1637,7 @@ sub GenerateFunctionCallString()
         # appendChild functions from Node.
         $result .= $indent . "bool success = $functionString;\n";
         if (@{$function->raisesExceptions}) {
-            $result .= GenerateSetDOMException($indent);
+            $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
         }
         $result .= $indent . "if (success)\n";
         $result .= $indent . "    " .
@@ -1615,7 +1661,7 @@ sub GenerateFunctionCallString()
     }
 
     if (@{$function->raisesExceptions}) {
-        $result .= GenerateSetDOMException($indent);
+        $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
     }
 
     # If the return type is a POD type, separate out the wrapper generation
index ede85a493604d1e7e5cab6df648ab64c0369fc84..f069c03fae0c803f213f1040039fbb66d2dd9024 100644 (file)
 
 #include "AtomicString.h"
 #include "CString.h"
+#include "Element.h"
 #include "MathExtras.h"
 #include "PlatformString.h"
+#include "QualifiedName.h"
 #include "StdLibExtras.h"
 #include "StringBuffer.h"
 #include "StringHash.h"
@@ -423,5 +425,21 @@ void createCallback(v8::Local<v8::ObjectTemplate> proto,
                v8::FunctionTemplate::New(callback, v8::Handle<v8::Value>(), signature),
                attribute);
 }
+    
+v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo& info,
+                                           const QualifiedName& name) 
+{
+    Element *imp = v8DOMWrapperToNode<Element>(info);
+    return v8ExternalString(imp->getAttribute(name));
+}
+
+void setElementStringAttr(const v8::AccessorInfo& info,
+                          const QualifiedName& name,
+                          v8::Local<v8::Value> value)
+{
+    Element* imp = v8DOMWrapperToNode<Element>(info);
+    AtomicString v = toAtomicWebCoreStringWithNullCheck(value);
+    imp->setAttribute(name, v);
+}
 
 } // namespace WebCore
index 3ce0526b906e819b5ce5324042313f147d4b3a5a..7bf5d9437917c985d5007a3a07a7d32913879a5f 100644 (file)
@@ -221,6 +221,15 @@ namespace WebCore {
                         v8::Handle<v8::Signature>,
                         v8::PropertyAttribute attributes = v8::DontDelete);
     
+    v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&,
+                                               const QualifiedName&);
+    void setElementStringAttr(const v8::AccessorInfo&,
+                              const QualifiedName&,
+                              v8::Local<v8::Value>);
+
+    v8::Handle<v8::Value> getElementEventHandlerAttr(const v8::AccessorInfo&,
+                                                     const AtomicString&);
+
 } // namespace WebCore
 
 #endif // V8Binding_h