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 {
return *this;
}
void Init(v8::Local<v8::String> value) {
DCHECK(v8_string_.IsEmpty());
DCHECK(wtf_string_.IsNull());
v8_string_ = value;
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator String() const { return ToString<String>(); }
// NOLINTNEXTLINE(google-explicit-constructor)
......
......@@ -463,7 +463,8 @@ def make_v8_to_blink_value(blink_var_name,
v8_value_expr,
idl_type,
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.
"""
......@@ -477,6 +478,25 @@ def make_v8_to_blink_value(blink_var_name,
T = TextNode
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):
if argument_index is None:
func_name = "NativeValue"
......@@ -496,48 +516,60 @@ def make_v8_to_blink_value(blink_var_name,
_1=native_value_tag(idl_type),
_2=func_name,
_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, [
F("auto&& ${{{}}} = {};", blink_var_name, blink_value_expr),
CxxUnlikelyIfNode(
cond="${exception_state}.HadException()",
body=T("return;")),
exception_exit_node,
])
nodes = []
arg_type = _format(
blink_var_type = _format(
"decltype(NativeValueTraits<{}>::NativeValue("
"std::declval<v8::Isolate*>(), "
"std::declval<v8::Local<v8::Value>>(), "
"std::declval<ExceptionState&>()))", native_value_tag(idl_type))
default_expr = make_default_value_expr(idl_type, default_value)
if default_expr.is_initialization_lightweight:
nodes.append(
F("{} ${{{}}}{{{}}};", arg_type, blink_var_name,
default_expr.initializer_expr))
if default_expr and default_expr.is_initialization_lightweight:
pattern = "{} ${{{}}}{{{}}};"
args = [
blink_var_type, blink_var_name, default_expr.initializer_expr
]
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 = [
F("${{{}}} = {};", blink_var_name, blink_value_expr),
CxxUnlikelyIfNode(
cond="${exception_state}.HadException()", body=T("return;")),
exception_exit_node,
]
if (default_expr.initializer_expr is None
if not default_expr:
pass
elif (default_expr.initializer_expr is None
or default_expr.is_initialization_lightweight):
nodes.append(
CxxLikelyIfNode(
assignment = CxxLikelyIfNode(
cond="!{}->IsUndefined()".format(v8_value_expr),
body=assignment))
body=assignment)
else:
nodes.append(
CxxIfElseNode(cond="{}->IsUndefined()".format(v8_value_expr),
assignment = CxxIfElseNode(
cond="{}->IsUndefined()".format(v8_value_expr),
then=F("${{{}}} = {};", blink_var_name,
default_expr.assignment_value),
then_likeliness=Likeliness.LIKELY,
else_=assignment,
else_likeliness=Likeliness.LIKELY))
return SymbolDefinitionNode(symbol_node, nodes)
else_likeliness=Likeliness.LIKELY)
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)
......
......@@ -250,12 +250,12 @@ const auto ${arg1_value} = arg1_value_maybe_enum.value();
else:
v8_value = "${{info}}[{}]".format(argument.index)
code_node.register_code_symbol(
make_v8_to_blink_value(
name,
make_v8_to_blink_value(name,
v8_value,
argument.idl_type,
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):
......
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