Commit e863e239 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Improve the speed perf of IDLString conversion

Introduces a fast path for conversion from v8::String to
WTFString / AtomicString in order to mitigate perf
regressions on Android.

Bug: 839389
Change-Id: Icb0a9bf4ac756cba02d6d0e73abacfd943996606
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2333906Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797121}
parent f0f5ad44
...@@ -320,6 +320,12 @@ class CORE_EXPORT NativeValueTraitsStringAdapter { ...@@ -320,6 +320,12 @@ class CORE_EXPORT NativeValueTraitsStringAdapter {
return *this; return *this;
} }
void Init(v8::Local<v8::String> value) {
DCHECK(v8_string_.IsEmpty());
DCHECK(wtf_string_.IsNull());
v8_string_ = value;
}
// NOLINTNEXTLINE(google-explicit-constructor) // NOLINTNEXTLINE(google-explicit-constructor)
operator String() const { return ToString<String>(); } operator String() const { return ToString<String>(); }
// NOLINTNEXTLINE(google-explicit-constructor) // NOLINTNEXTLINE(google-explicit-constructor)
......
...@@ -463,7 +463,8 @@ def make_v8_to_blink_value(blink_var_name, ...@@ -463,7 +463,8 @@ def make_v8_to_blink_value(blink_var_name,
v8_value_expr, v8_value_expr,
idl_type, idl_type,
argument_index=None, argument_index=None,
default_value=None): default_value=None,
cg_context=None):
""" """
Returns a SymbolNode whose definition converts a v8::Value to a Blink value. Returns a SymbolNode whose definition converts a v8::Value to a Blink value.
""" """
...@@ -477,6 +478,25 @@ def make_v8_to_blink_value(blink_var_name, ...@@ -477,6 +478,25 @@ def make_v8_to_blink_value(blink_var_name,
T = TextNode T = TextNode
F = lambda *args, **kwargs: T(_format(*args, **kwargs)) F = lambda *args, **kwargs: T(_format(*args, **kwargs))
# Use of fast path is a trade-off between speed and binary size, so apply
# it only when it's effective. This hack is most significant on Android.
use_fast_path = (
cg_context and cg_context.operation
and not (cg_context.is_return_type_promise_type or
"RaisesException" in cg_context.operation.extended_attributes)
and all(arg.idl_type.type_name == "String"
for arg in cg_context.operation.arguments))
fast_path_cond = None
fast_path_body_text = None
if not use_fast_path:
pass
elif idl_type.type_name == "String":
# A key point of this fast path is that it doesn't require an
# ExceptionState.
fast_path_cond = "LIKELY({}->IsString())".format(v8_value_expr)
fast_path_body_text = "{}.Init({}.As<v8::String>());".format(
blink_var_name, v8_value_expr)
def create_definition(symbol_node): def create_definition(symbol_node):
if argument_index is None: if argument_index is None:
func_name = "NativeValue" func_name = "NativeValue"
...@@ -496,48 +516,60 @@ def make_v8_to_blink_value(blink_var_name, ...@@ -496,48 +516,60 @@ def make_v8_to_blink_value(blink_var_name,
_1=native_value_tag(idl_type), _1=native_value_tag(idl_type),
_2=func_name, _2=func_name,
_3=", ".join(arguments)) _3=", ".join(arguments))
default_expr = (make_default_value_expr(idl_type, default_value)
if default_value else None)
exception_exit_node = CxxUnlikelyIfNode(
cond="${exception_state}.HadException()", body=T("return;"))
if default_value is None: if not (default_expr or fast_path_cond):
return SymbolDefinitionNode(symbol_node, [ return SymbolDefinitionNode(symbol_node, [
F("auto&& ${{{}}} = {};", blink_var_name, blink_value_expr), F("auto&& ${{{}}} = {};", blink_var_name, blink_value_expr),
CxxUnlikelyIfNode( exception_exit_node,
cond="${exception_state}.HadException()",
body=T("return;")),
]) ])
nodes = [] blink_var_type = _format(
arg_type = _format(
"decltype(NativeValueTraits<{}>::NativeValue(" "decltype(NativeValueTraits<{}>::NativeValue("
"std::declval<v8::Isolate*>(), " "std::declval<v8::Isolate*>(), "
"std::declval<v8::Local<v8::Value>>(), " "std::declval<v8::Local<v8::Value>>(), "
"std::declval<ExceptionState&>()))", native_value_tag(idl_type)) "std::declval<ExceptionState&>()))", native_value_tag(idl_type))
default_expr = make_default_value_expr(idl_type, default_value) if default_expr and default_expr.is_initialization_lightweight:
if default_expr.is_initialization_lightweight: pattern = "{} ${{{}}}{{{}}};"
nodes.append( args = [
F("{} ${{{}}}{{{}}};", arg_type, blink_var_name, blink_var_type, blink_var_name, default_expr.initializer_expr
default_expr.initializer_expr)) ]
else: else:
nodes.append(F("{} ${{{}}};", arg_type, blink_var_name)) pattern = "{} ${{{}}};"
args = [blink_var_type, blink_var_name]
blink_var_def_node = F(pattern, *args)
assignment = [ assignment = [
F("${{{}}} = {};", blink_var_name, blink_value_expr), F("${{{}}} = {};", blink_var_name, blink_value_expr),
CxxUnlikelyIfNode( exception_exit_node,
cond="${exception_state}.HadException()", body=T("return;")),
] ]
if (default_expr.initializer_expr is None if not default_expr:
or default_expr.is_initialization_lightweight): pass
nodes.append( elif (default_expr.initializer_expr is None
CxxLikelyIfNode( or default_expr.is_initialization_lightweight):
cond="!{}->IsUndefined()".format(v8_value_expr), assignment = CxxLikelyIfNode(
body=assignment)) cond="!{}->IsUndefined()".format(v8_value_expr),
body=assignment)
else: else:
nodes.append( assignment = CxxIfElseNode(
CxxIfElseNode(cond="{}->IsUndefined()".format(v8_value_expr), cond="{}->IsUndefined()".format(v8_value_expr),
then=F("${{{}}} = {};", blink_var_name, then=F("${{{}}} = {};", blink_var_name,
default_expr.assignment_value), default_expr.assignment_value),
then_likeliness=Likeliness.LIKELY, then_likeliness=Likeliness.LIKELY,
else_=assignment, else_=assignment,
else_likeliness=Likeliness.LIKELY)) else_likeliness=Likeliness.LIKELY)
return SymbolDefinitionNode(symbol_node, nodes) if fast_path_cond:
assignment = CxxIfElseNode(cond=fast_path_cond,
then=T(fast_path_body_text),
then_likeliness=Likeliness.LIKELY,
else_=assignment,
else_likeliness=Likeliness.UNLIKELY)
return SymbolDefinitionNode(symbol_node, [
blink_var_def_node,
assignment,
])
return SymbolNode(blink_var_name, definition_constructor=create_definition) return SymbolNode(blink_var_name, definition_constructor=create_definition)
......
...@@ -250,12 +250,12 @@ const auto ${arg1_value} = arg1_value_maybe_enum.value(); ...@@ -250,12 +250,12 @@ const auto ${arg1_value} = arg1_value_maybe_enum.value();
else: else:
v8_value = "${{info}}[{}]".format(argument.index) v8_value = "${{info}}[{}]".format(argument.index)
code_node.register_code_symbol( code_node.register_code_symbol(
make_v8_to_blink_value( make_v8_to_blink_value(name,
name, v8_value,
v8_value, argument.idl_type,
argument.idl_type, argument_index=index,
argument_index=index, default_value=argument.default_value,
default_value=argument.default_value)) cg_context=cg_context))
def bind_callback_local_vars(code_node, cg_context): def bind_callback_local_vars(code_node, cg_context):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment