Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omit static constructors when not needed #1900

Draft
wants to merge 2 commits into
base: staging/2.3
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/cswinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -10133,8 +10133,20 @@ bind_list<write_parameter_name_with_modifier>(", ", signature.params())
{
auto factory_type_name = write_type_name_temp(w, type, "%ServerActivationFactory", typedef_name_type::CCW);
auto is_activatable = !is_static(type) && has_default_constructor(type);
auto should_run_class_constructor = has_static_constructor(type);
auto type_name = write_type_name_temp(w, type, "%", typedef_name_type::Projected);

// If the type doesn't have a static constructor, we can omit calling 'RuntimeHelpers.RunClassConstructor'.
// This is technically only required if the type declares any dependency properties (we think, though we're
// not 100% sure), but at least skipping this for types without a static constructor is good enough.
// In practice, it will skip the call for most types.
auto static_constructor = should_run_class_constructor
? w.write_temp(R"(static %()
{
RuntimeHelpers.RunClassConstructor(typeof(%).TypeHandle);
})", factory_type_name, type_name)
: "";

// If the type is activatable, we implement IActivationFactory by creating an
// instance and marshalling it to IntPtr. Otherwise, we just throw an exception.
auto activate_instance_body = is_activatable
Expand All @@ -10148,10 +10160,7 @@ bind_list<write_parameter_name_with_modifier>(", ", signature.params())
internal sealed class % : global::WinRT.Interop.IActivationFactory%
{

static %()
{
RuntimeHelpers.RunClassConstructor(typeof(%).TypeHandle);
}
%

public static IntPtr Make()
{
Expand All @@ -10171,8 +10180,7 @@ public IntPtr ActivateInstance()
bind<write_winrt_exposed_type_attribute>(type, true),
factory_type_name,
bind<write_factory_class_inheritance>(type),
factory_type_name,
type_name,
static_constructor,
factory_type_name,
factory_type_name,
factory_type_name,
Expand Down
32 changes: 28 additions & 4 deletions src/cswinrt/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,21 @@ namespace cswinrt
return get_category(type) == category::class_type && type.Flags().Abstract();
}

bool is_static(MethodDef const& method)
{
return method.Flags().Static();
}

bool is_constructor(MethodDef const& method)
{
return method.Flags().RTSpecialName() && method.Name() == ".ctor";
}

bool is_static_constructor(MethodDef const& method)
{
return method.Flags().RTSpecialName() && method.Name() == ".cctor";
}

bool has_default_constructor(TypeDef const& type)
{
XLANG_ASSERT(get_category(type) == category::class_type);
Expand All @@ -108,14 +118,28 @@ namespace cswinrt
return false;
}

bool is_special(MethodDef const& method)
bool has_static_constructor(TypeDef const& type)
{
return method.SpecialName() || method.Flags().RTSpecialName();
XLANG_ASSERT(get_category(type) == category::class_type);

for (auto&& method : type.MethodList())
{
if (is_static_constructor(method))
{
// Sanity check, these should always be true
XLANG_ASSERT(is_static(method));
XLANG_ASSERT(size(method.ParamList()) == 0);

return true;
}
}

return false;
}

bool is_static(MethodDef const& method)
bool is_special(MethodDef const& method)
{
return method.Flags().Static();
return method.SpecialName() || method.Flags().RTSpecialName();
}

auto get_delegate_invoke(TypeDef const& type)
Expand Down