Commit 93cab873 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Implement a binary size reduction hack of [Reflect]

Implements/ports tkent[1]'s binary size optimization of
[CEReafctions, Reflect] attribute set callback in the new
binding generator.

The APK size reduces by about 52 KB.

[1] https://crrev.com/c/1732676

Bug: 839389
Change-Id: If485747158ffb4307d5f20e21a1aba807af45ba1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2291820
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#787670}
parent 866f2c43
......@@ -344,6 +344,82 @@ v8::Local<v8::Array> EnumerateIndexedProperties(v8::Isolate* isolate,
return v8::Array::New(isolate, elements.data(), elements.size());
}
#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
template <typename IDLType,
typename ArgType,
void (Element::*MemFunc)(const QualifiedName&, ArgType)>
void PerformAttributeSetCEReactionsReflect(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
v8::Isolate* isolate = info.GetIsolate();
ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
interface_name, attribute_name);
if (UNLIKELY(info.Length() < 1)) {
exception_state.ThrowTypeError(
ExceptionMessages::NotEnoughArguments(1, info.Length()));
return;
}
// [Reflect]
V0CustomElementProcessingStack::CallbackDeliveryScope v0_custom_element_scope;
// [CEReactions]
CEReactionsScope ce_reactions_scope;
Element* blink_receiver = V8Element::ToWrappableUnsafe(info.This());
auto&& arg_value = NativeValueTraits<IDLType>::NativeValue(isolate, info[0],
exception_state);
if (exception_state.HadException())
return;
(blink_receiver->*MemFunc)(content_attribute, arg_value);
}
void PerformAttributeSetCEReactionsReflectTypeBoolean(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
PerformAttributeSetCEReactionsReflect<IDLBoolean, bool,
&Element::SetBooleanAttribute>(
info, content_attribute, interface_name, attribute_name);
}
void PerformAttributeSetCEReactionsReflectTypeString(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
PerformAttributeSetCEReactionsReflect<IDLStringV2, const AtomicString&,
&Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
}
void PerformAttributeSetCEReactionsReflectTypeStringLegacyNullToEmptyString(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
PerformAttributeSetCEReactionsReflect<IDLStringTreatNullAsEmptyStringV2,
const AtomicString&,
&Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
}
void PerformAttributeSetCEReactionsReflectTypeStringOrNull(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name) {
PerformAttributeSetCEReactionsReflect<
IDLNullable<IDLStringV2>, const AtomicString&, &Element::setAttribute>(
info, content_attribute, interface_name, attribute_name);
}
#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
} // namespace bindings
} // namespace blink
......@@ -228,6 +228,29 @@ bool ConvertDictionaryMember(v8::Isolate* isolate,
return true;
}
// Common implementation to reduce the binary size of attribute set callbacks.
CORE_EXPORT void PerformAttributeSetCEReactionsReflectTypeBoolean(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name);
CORE_EXPORT void PerformAttributeSetCEReactionsReflectTypeString(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name);
CORE_EXPORT void
PerformAttributeSetCEReactionsReflectTypeStringLegacyNullToEmptyString(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name);
CORE_EXPORT void PerformAttributeSetCEReactionsReflectTypeStringOrNull(
const v8::FunctionCallbackInfo<v8::Value>& info,
const QualifiedName& content_attribute,
const char* interface_name,
const char* attribute_name);
} // namespace bindings
} // namespace blink
......
......@@ -1729,6 +1729,59 @@ EventListener* event_handler = JSEventHandler::CreateOrNull(
body.append(TextNode(text))
return func_def
# Binary size reduction hack
# When the following conditions are met, the implementation is shared.
# 1. The attribute is annotated with [CEReactions, Reflect] and not
# annotated with other extended attributes having side effect.
# 2. The interface is implementing Element.
def optimize_element_cereactions_reflect():
has_cereactions = False
has_reflect = False
for key in ext_attrs.keys():
if key == "CEReactions":
has_cereactions = True
elif key == "Reflect":
has_reflect = True
elif key in ("Affects", "CustomElementCallbacks", "DeprecateAs",
"Exposed", "LogActivity", "LogAllWorlds", "Measure",
"MeasureAs", "ReflectEmpty", "ReflectInvalid",
"ReflectMissing", "ReflectOnly",
"RuntimeCallStatsCounter", "RuntimeEnabled",
"SecureContext", "URL", "Unscopable"):
pass
else:
return None
if not (has_cereactions and has_reflect):
return None
if not cg_context.interface.does_implement("Element"):
return None
content_attribute = _make_reflect_content_attribute_key(
body, cg_context)
idl_type = cg_context.attribute.idl_type.unwrap(typedef=True)
if idl_type.is_boolean:
func_name = "PerformAttributeSetCEReactionsReflectTypeBoolean"
elif idl_type.type_name == "String":
func_name = "PerformAttributeSetCEReactionsReflectTypeString"
elif idl_type.type_name == "StringTreatNullAs":
func_name = ("PerformAttributeSetCEReactionsReflect"
"TypeStringLegacyNullToEmptyString")
elif idl_type.type_name == "StringOrNull":
func_name = "PerformAttributeSetCEReactionsReflectTypeStringOrNull"
else:
return None
text = _format(
"bindings::{func_name}"
"(${info}, {content_attribute}, "
"${class_like_name}, ${property_name});",
func_name=func_name,
content_attribute=content_attribute)
return TextNode(text)
node = optimize_element_cereactions_reflect()
if node:
body.append(node)
return func_def
body.extend([
make_check_receiver(cg_context),
make_check_argument_length(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