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

Unified Diff: tools/dom/scripts/generate_blink_file.py

Issue 1832713002: Optimize dartium dart:html bindings so real world application performance is acceptable. Improves d… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: update cached patches Created 4 years, 9 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 | « tools/dom/scripts/css_code_generator.py ('k') | tools/dom/scripts/generator.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/dom/scripts/generate_blink_file.py
diff --git a/tools/dom/scripts/generate_blink_file.py b/tools/dom/scripts/generate_blink_file.py
index 6f274da35b6ae30b6cf35c5375cb3db6e271a321..4beb0a56fa4ce7635874a88d5b07860222268252 100644
--- a/tools/dom/scripts/generate_blink_file.py
+++ b/tools/dom/scripts/generate_blink_file.py
@@ -7,9 +7,85 @@
"""Generates sdk/lib/_blink/dartium/_blink_dartium.dart file."""
import os
-
+from sets import Set
from generator import AnalyzeOperation, AnalyzeConstructor
+# This is list of all methods with native c++ implementations
+# If performing a dartium merge, the best practice is to comment out this list,
+# ensure everything runs, and then uncomment this list which might possibly
+# introduce breaking changes due to changes to these method signatures.
+_js_custom_members = Set([
+ 'Document.createElement',
+ 'Element.id',
+ 'Element.tagName',
+ 'Element.className',
+ 'Element.setAttribute',
+ 'Element.getAttribute',
+ # Consider adding this method so there is a fast path to access only
+ # element children.
+ # 'NonDocumentTypeChildNode.nextElementSibling',
+ 'Node.appendChild', # actually not removed, just native implementation.
+ 'Node.cloneNode',
+ 'Node.insertBefore',
+ 'Node.lastChild',
+ 'Node.firstChild',
+ 'Node.parentElement',
+ 'Node.parentNode',
+ 'Node.childNodes',
+ 'Node.removeChild',
+ 'Node.contains',
+ 'Node.nextSibling',
+ 'Node.previousSibling',
+ 'ChildNode.remove',
+ 'Document.createTextNode',
+ 'Window.location',
+ 'Location.href',
+ 'Node.querySelector',
+
+ 'HTMLElement.hidden',
+ 'HTMLElement.style',
+ 'Element.attributes',
+ 'Window.innerWidth',
+
+ 'NodeList.length',
+ 'NodeList.item',
+ 'ParentNode.children',
+ 'ParentNode.firstElementChild',
+ 'ParentNode.lastElementChild',
+ 'Event.target',
+ 'MouseEvent.clientY',
+ 'MouseEvent.clientX',
+
+ 'Node.nodeType',
+ 'Node.textContent',
+
+ 'HTMLCollection.length',
+ 'HTMLCollection.item',
+ 'Node.lastElementChild',
+ 'Node.firstElementChild',
+ 'HTMLElement_tabIndex',
+
+ 'Element.clientWidth',
+ 'Element.clientHeight',
+ 'Document.body',
+ 'Element.removeAttribute',
+ 'Element.getBoundingClientRect',
+ 'CSSStyleDeclaration.getPropertyValue',
+ 'CSSStyleDeclaration.setProperty',
+ 'CSSStyleDeclaration.__propertyQuery__',
+
+ # TODO(jacobr): consider implementing these methods as well as they show
+ # up in benchmarks for some sample applications.
+ #'Document.createEvent',
+ #'Document.initEvent',
+ #'EventTarget.dispatchEvent',
+ ])
+
+# Uncomment out this line to short circuited native methods and run all of
+# dart:html through JS interop except for createElement which is slightly more
+# tightly natively wired.
+# _js_custom_members = Set([])
+
HEADER = """/* Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
@@ -50,13 +126,14 @@ class Blink_Utils {
static register(document, tag, customType, extendsTagName) native "Utils_register";
- static createElement(document, tagName) native "Utils_createElement";
-
- static constructElement(element_type, jsObject) native "Utils_constructor_create";
+ // Defines an interceptor if there is an appropriate JavaScript prototype to define it on.
+ // In any case, returns a typed JS wrapper compatibile with dart:html and the new
+ // typed JS Interop.
+ static defineInterceptorCustomElement(jsObject, Type type) native "Utils_defineInterceptorCustomElement";
+ static setInstanceInterceptor(o, Type type, {bool customElement: false}) native "Utils_setInstanceInterceptor";
+ // This method will throw if the element isn't actually a real Element.
static initializeCustomElement(element) native "Utils_initializeCustomElement";
-
- static changeElementWrapper(element, type) native "Utils_changeElementWrapper";
}
class Blink_DOMWindowCrossFrame {
@@ -106,9 +183,63 @@ class Blink_DOMStringMap {
}
// Calls through JsNative but returns DomException instead of error strings.
+class Stats {
+ Stats(this.name) {
+ counts = new Map<String, int>();
+ }
+
+ String name;
+ Map<String, int> counts;
+ clear() {
+ counts.clear();
+ }
+
+ track(String v) {
+ counts[v] = counts.putIfAbsent(v, ()=> 0) + 1;
+ }
+ toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('================');
+ sb.write('$name ${counts.length}');
+ var keys = counts.keys.toList();
+ keys.sort((a,b) => counts[b].compareTo(counts[a]));
+ for (var key in keys) {
+ print("$key => ${counts[key]}");
+ }
+ sb.write('---------------');
+ sb.write('================');
+ return sb;
+ }
+}
+
+bool TRACK_STATS = true;
+dumpStats() {
+ print("------------ STATS ----------------");
+ print(Blink_JsNative_DomException.getPropertyStats.toString());
+ print(Blink_JsNative_DomException.setPropertyStats.toString());
+ print(Blink_JsNative_DomException.callMethodStats.toString());
+ print(Blink_JsNative_DomException.constructorStats.toString());
+ print("-----------------------------------");
+}
+
+clearStats() {
+ Blink_JsNative_DomException.getPropertyStats.clear();
+ Blink_JsNative_DomException.setPropertyStats.clear();
+ Blink_JsNative_DomException.callMethodStats.clear();
+ Blink_JsNative_DomException.constructorStats.clear();
+}
+
class Blink_JsNative_DomException {
- static getProperty(js.JsObject o, name) {
+ static var getPropertyStats = new Stats('get property');
+ static var setPropertyStats = new Stats('set property');
+ static var callMethodStats = new Stats('call method');
+ static var constructorStats = new Stats('constructor');
+
+ static var constructors = new Map<String, dynamic>();
+
+ static getProperty(o, String name) {
try {
+ if (TRACK_STATS) getPropertyStats.track(name);
return js.JsNative.getProperty(o, name);
} catch (e) {
// Re-throw any errors (returned as a string) as a DomException.
@@ -116,8 +247,51 @@ class Blink_JsNative_DomException {
}
}
- static callMethod(js.JsObject o, String method, List args) {
+ static propertyQuery(o, String name) {
try {
+ if (TRACK_STATS) getPropertyStats.track('__propertyQuery__');
+ return js.JsNative.getProperty(o, name);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+
+ static callConstructor0(String name) {
+ try {
+ if (TRACK_STATS) constructorStats.track(name);
+ var constructor = constructors.putIfAbsent(name, () => js.context[name]);
+ return js.JsNative.callConstructor0(constructor);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+
+ static callConstructor(String name, List args) {
+ try {
+ if (TRACK_STATS) constructorStats.track(name);
+ var constructor = constructors.putIfAbsent(name, () => js.context[name]);
+ return js.JsNative.callConstructor(constructor, args);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+
+ static setProperty(o, String name, value) {
+ try {
+ if (TRACK_STATS) setPropertyStats.track(name);
+ return js.JsNative.setProperty(o, name, value);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+
+ static callMethod(o, String method, List args) {
+ try {
+ if (TRACK_STATS) callMethodStats.track(method);
return js.JsNative.callMethod(o, method, args);
} catch (e) {
// Re-throw any errors (returned as a string) as a DomException.
@@ -137,38 +311,73 @@ CLASS_DEFINITION_EXTENDS = """class Blink%s extends Blink%s {
"""
#(interface_name)
-CONSTRUCTOR_0 = ' constructorCallback_0_() => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), []);\n\n'
+
+#
+CONSTRUCTOR_0 = [' constructorCallback_0_()',
+ ' => Blink_JsNative_DomException.callConstructor0("%s");\n\n',
+ ' native "Blink_Constructor_%s";\n\n']
#(argument_count, arguments, interface_name, arguments)
-CONSTRUCTOR_ARGS = ' constructorCallback_%s_(%s) => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), [%s]);\n\n'
+CONSTRUCTOR_ARGS = [' constructorCallback_%s_(%s)',
+ ' => Blink_JsNative_DomException.callConstructor("%s", [%s]);\n\n',
+ ' native "Blink_Constructor_Args_%s" /* %s */;\n\n']
#(attribute_name, attribute_name)
-ATTRIBUTE_GETTER = ' %s_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis, "%s");\n\n'
-ATTRIBUTE_SETTER = ' %s_Setter_(mthis, __arg_0) => mthis["%s"] = __arg_0;\n\n'
+ATTRIBUTE_GETTER = [' %s_Getter_(mthis)',
+ ' => Blink_JsNative_DomException.getProperty(mthis /* %s */, "%s");\n\n',
+ ' native "Blink_Getter_%s_%s";\n\n'
+ ]
+
+ATTRIBUTE_SETTER = [' %s_Setter_(mthis, __arg_0)',
+ ' => Blink_JsNative_DomException.setProperty(mthis /* %s */, "%s", __arg_0);\n\n',
+ ' native "Blink_Setter_%s_%s";\n\n'
+ ]
#(operation_name, operationName)
-OPERATION_0 = ' %s_Callback_0_(mthis) => Blink_JsNative_DomException.callMethod(mthis, "%s", []);\n\n'
+OPERATION_0 = [' %s_Callback_0_(mthis)',
+ ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", []);\n\n',
+ ' native "Blink_Operation_0_%s_%s";\n\n'
+ ]
# getter, setter, deleter and propertyQuery code
-OPERATION_1 = ' $%s_Callback_1_(mthis, __arg_0) => Blink_JsNative_DomException.callMethod(mthis, "%s", [__arg_0]);\n\n'
-OPERATION_2 = ' $%s_Callback_2_(mthis, __arg_0, __arg_1) => Blink_JsNative_DomException.callMethod(mthis, "%s", [__arg_0, __arg_1]);\n\n'
-OPERATION_PQ = ' $%s_Callback_1_(mthis, __arg_0) => mthis[__arg_0];\n\n'
+OPERATION_1 = [' $%s_Callback_1_(mthis, __arg_0)',
+ ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [__arg_0]);\n\n',
+ ' native "Blink_Operation_1_%s_%s";\n\n'
+ ]
+
+OPERATION_2 = [' $%s_Callback_2_(mthis, __arg_0, __arg_1)',
+ ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [__arg_0, __arg_1]);\n\n',
+ ' native "Blink_Operation_2_%s_%s";\n\n']
+
+OPERATION_PQ = [' $%s_Callback_1_(mthis, __arg_0)',
+ ' => Blink_JsNative_DomException.propertyQuery(mthis, __arg_0); /* %s */ \n\n',
+ ' native "Blink_Operation_PQ_%s";\n\n']
#(operation_name, argument_count, arguments, operation_name, arguments)
ARGUMENT_NUM = "__arg_%s"
-OPERATION_ARGS = ' %s_Callback_%s_(mthis, %s) => Blink_JsNative_DomException.callMethod(mthis, "%s", [%s]);\n\n'
+OPERATION_ARGS = [' %s_Callback_%s_(mthis, %s)',
+ ' => Blink_JsNative_DomException.callMethod(mthis /* %s */, "%s", [%s]);\n\n',
+ ' native "Blink_Operation_%s_%s"; /* %s */\n\n']
+
+
# get class property to make static call.
CLASS_STATIC = 'Blink_JsNative_DomException.getProperty(js.context, "%s")'
# name, classname_getproperty, name
-STATIC_ATTRIBUTE_GETTER = ' %s_Getter_() => Blink_JsNative_DomException.getProperty(%s, "%s");\n\n'
+STATIC_ATTRIBUTE_GETTER = [' %s_Getter_()',
+ ' => Blink_JsNative_DomException.getProperty(%s /* %s */, "%s");\n\n',
+ ' /* %s */ native "Blink_Static_getter_%s_%s"']
# name, classname_getproperty, name
-STATIC_OPERATION_0 = ' %s_Callback_0_() => Blink_JsNative_DomException.callMethod(%s, "%s", []);\n\n'
+STATIC_OPERATION_0 = [' %s_Callback_0_()',
+ ' => Blink_JsNative_DomException.callMethod(%s /* %s */, "%s", []);\n\n',
+ ' /* %s */ native "Blink_Static_Operation_0_%s_%s']
# name, argsCount, args, classname_getproperty, name, args
-STATIC_OPERATION_ARGS = ' %s_Callback_%s_(%s) => Blink_JsNative_DomException.callMethod(%s, "%s", [%s]);\n\n'
+STATIC_OPERATION_ARGS = [' %s_Callback_%s_(%s)',
+ ' => Blink_JsNative_DomException.callMethod(%s /* %s */, "%s", [%s]);\n\n',
+ ' /* %s */ native "Blink_Static_Operations_%s_%s" /* %s */ \n\n']
CLASS_DEFINITION_END = """}
@@ -197,6 +406,27 @@ constructor_renames = {
def rename_constructor(name):
return constructor_renames[name] if name in constructor_renames else name
+
+def _Find_Match(interface_id, member, member_prefix, candidates):
+ member_name = interface_id + '.' + member
+ if member_name in candidates:
+ return member_name
+ member_name = interface_id + '.' + member_prefix + member
+ if member_name in candidates:
+ return member_name
+ member_name = interface_id + '.*'
+ if member_name in candidates:
+ return member_name
+
+def _Is_Native(interface, member):
+ return _Find_Match(interface, member, '', _js_custom_members)
+
+def Select_Stub(template, is_native):
+ if is_native:
+ return template[0] + template[2]
+ else:
+ return template[0] + template[1]
+
def Generate_Blink(output_dir, database, type_registry):
blink_filename = os.path.join(output_dir, '_blink_dartium.dart')
blink_file = open(blink_filename, 'w')
@@ -226,7 +456,7 @@ def Generate_Blink(output_dir, database, type_registry):
_Emit_Blink_Constructors(blink_file, analyzed_constructors)
elif 'Constructor' in interface.ext_attrs:
# Zero parameter constructor.
- blink_file.write(CONSTRUCTOR_0 % rename_constructor(name))
+ blink_file.write(Select_Stub(CONSTRUCTOR_0, _Is_Native(name, 'constructor')) % rename_constructor(name))
_Process_Attributes(blink_file, interface, interface.attributes)
_Process_Operations(blink_file, interface, interface.operations)
@@ -250,27 +480,29 @@ def _Emit_Blink_Constructors(blink_file, analyzed_constructors):
for callback_index in range(arg_min_count, arg_max_count):
if callback_index == 0:
- blink_file.write(CONSTRUCTOR_0 % (rename_constructor(name)))
+ blink_file.write(Select_Stub(CONSTRUCTOR_0, _Is_Native(name, 'constructor')) % (rename_constructor(name)))
else:
arguments = []
for i in range(0, callback_index):
arguments.append(ARGUMENT_NUM % i)
argument_list = ', '.join(arguments)
- blink_file.write(CONSTRUCTOR_ARGS % (callback_index, argument_list, rename_constructor(name), argument_list))
+ blink_file.write(
+ Select_Stub(CONSTRUCTOR_ARGS, _Is_Native(name, 'constructor')) % (callback_index, argument_list, rename_constructor(name), argument_list))
def _Process_Attributes(blink_file, interface, attributes):
# Emit an interface's attributes and operations.
for attribute in sorted(attributes, ConstantOutputOrder):
name = attribute.id
+ is_native = _Is_Native(interface.id, name)
if attribute.is_read_only:
if attribute.is_static:
class_property = CLASS_STATIC % interface.id
- blink_file.write(STATIC_ATTRIBUTE_GETTER % (name, class_property, name))
+ blink_file.write(Select_Stub(STATIC_ATTRIBUTE_GETTER, is_native) % (name, class_property, interface.id, name))
else:
- blink_file.write(ATTRIBUTE_GETTER % (name, name))
+ blink_file.write(Select_Stub(ATTRIBUTE_GETTER, is_native) % (name, interface.id, name))
else:
- blink_file.write(ATTRIBUTE_GETTER % (name, name))
- blink_file.write(ATTRIBUTE_SETTER % (name, name))
+ blink_file.write(Select_Stub(ATTRIBUTE_GETTER, is_native) % (name, interface.id, name))
+ blink_file.write(Select_Stub(ATTRIBUTE_SETTER, is_native) % (name, interface.id, name))
def _Process_Operations(blink_file, interface, operations):
analyzeOperations = []
@@ -292,6 +524,7 @@ def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
analyzed = AnalyzeOperation(interface, analyzeOperations)
(arg_min_count, arg_max_count) = generate_parameter_entries(analyzed.param_infos)
name = analyzed.js_name
+ is_native = _Is_Native(interface.id, name)
operation = analyzeOperations[0]
if (name.startswith('__') and \
@@ -299,13 +532,13 @@ def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
'setter' in operation.specials or \
'deleter' in operation.specials)):
if name == '__propertyQuery__':
- blink_file.write(OPERATION_PQ % (name))
+ blink_file.write(Select_Stub(OPERATION_PQ, is_native) % (name, interface.id))
else:
arg_min_count = arg_max_count
if arg_max_count == 2:
- blink_file.write(OPERATION_1 % (name, name))
+ blink_file.write(Select_Stub(OPERATION_1, is_native) % (name, interface.id, name))
elif arg_max_count == 3:
- blink_file.write(OPERATION_2 % (name, name))
+ blink_file.write(Select_Stub(OPERATION_2, is_native) % (name, interface.id, name))
else:
print "FATAL ERROR: _blink emitter operator %s.%s" % (interface.id, name)
exit
@@ -316,9 +549,9 @@ def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
if callback_index == 0:
if operation.is_static:
class_property = CLASS_STATIC % interface.id
- blink_file.write(STATIC_OPERATION_0 % (name, class_property, name))
+ blink_file.write(Select_Stub(STATIC_OPERATION_0, is_native) % (name, class_property, interface.id, name))
else:
- blink_file.write(OPERATION_0 % (name, name))
+ blink_file.write(Select_Stub(OPERATION_0, is_native) % (name, interface.id, name))
else:
arguments = []
for i in range(0, callback_index):
@@ -326,6 +559,6 @@ def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
argument_list = ', '.join(arguments)
if operation.is_static:
class_property = CLASS_STATIC % interface.id
- blink_file.write(STATIC_OPERATION_ARGS % (name, callback_index, argument_list, class_property, name, argument_list))
+ blink_file.write(Select_Stub(STATIC_OPERATION_ARGS, is_native) % (name, callback_index, argument_list, class_property, interface.id, name, argument_list))
else:
- blink_file.write(OPERATION_ARGS % (name, callback_index, argument_list, name, argument_list))
+ blink_file.write(Select_Stub(OPERATION_ARGS, is_native) % (name, callback_index, argument_list, interface.id, name, argument_list))
« no previous file with comments | « tools/dom/scripts/css_code_generator.py ('k') | tools/dom/scripts/generator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698