Optimize C++/WinRT implementation signatures (#512)

This commit is contained in:
Kenny Kerr 2019-07-11 16:23:43 -07:00 коммит произвёл GitHub
Родитель 46b872f40f
Коммит 8d849c1045
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 74 добавлений и 60 удалений

Просмотреть файл

@ -899,7 +899,8 @@ namespace xlang
auto param_type = std::get_if<ElementType>(&param_signature->Type().Type());
if (w.async_types || (param_type && *param_type != ElementType::String && *param_type != ElementType::Object))
if ((!is_put_overload(method_signature.method()) && w.async_types) ||
(param_type && *param_type != ElementType::String && *param_type != ElementType::Object))
{
w.write("%", param_signature->Type());
}
@ -924,7 +925,7 @@ namespace xlang
static void write_consume_declaration(writer& w, MethodDef const& method)
{
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
auto method_name = get_name(method);
auto type = method.Parent();
@ -1060,7 +1061,7 @@ namespace xlang
{
auto method_name = get_name(method);
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
std::string_view format;
@ -1120,7 +1121,7 @@ namespace xlang
{
auto method_name = get_name(method);
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
//
// Note: this use of a lambda is a workaround for a Visual C++ compiler bug:
@ -1737,7 +1738,7 @@ namespace xlang
}
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
std::string upcall = "this->shim().";
upcall += get_name(method);
@ -2805,7 +2806,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable<T, D, %>
{
method_signature signature{ method };
auto method_name = get_name(method);
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
if (settings.component_opt && settings.component_filter.includes(type))
{
@ -2845,7 +2846,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable<T, D, %>
{
method_signature signature{ method };
auto method_name = get_name(method);
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
{
auto format = R"( inline auto %::%(%)

Просмотреть файл

@ -474,7 +474,7 @@ catch (...) { return winrt::to_hresult(); }
{
method_signature signature{ method };
auto method_name = get_name(method);
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
if (is_add_overload(method) || is_remove_overload(method))
{
@ -950,7 +950,7 @@ namespace winrt::@::implementation
for (auto&& method : factory.type.MethodList())
{
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
auto method_name = get_name(method);
w.write(" static % %(%)%;\n",
@ -974,7 +974,7 @@ namespace winrt::@::implementation
for (auto&& method : info.type.MethodList())
{
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
auto method_name = get_name(method);
w.write(" % %(%)%;\n",
@ -1105,7 +1105,7 @@ namespace winrt::@::implementation
for (auto&& method : factory.type.MethodList())
{
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
auto method_name = get_name(method);
w.write(format,
@ -1136,7 +1136,7 @@ namespace winrt::@::implementation
)";
method_signature signature{ method };
w.async_types = is_async(method, signature);
w.async_types = signature.is_async();
auto method_name = get_name(method);
w.write(format,

Просмотреть файл

@ -12,22 +12,28 @@ namespace xlang
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
}
static bool is_put_overload(MethodDef const& method)
{
return method.SpecialName() && starts_with(method.Name(), "put_");
}
struct method_signature
{
explicit method_signature(MethodDef const& method) :
m_method(method.Signature())
m_method(method),
m_signature(method.Signature())
{
auto params = method.ParamList();
if (m_method.ReturnType() && params.first != params.second && params.first.Sequence() == 0)
if (m_signature.ReturnType() && params.first != params.second && params.first.Sequence() == 0)
{
m_return = params.first;
++params.first;
}
for (uint32_t i{}; i != size(m_method.Params()); ++i)
for (uint32_t i{}; i != size(m_signature.Params()); ++i)
{
m_params.emplace_back(params.first + i, &m_method.Params().first[i]);
m_params.emplace_back(params.first + i, &m_signature.Params().first[i]);
}
}
@ -43,7 +49,7 @@ namespace xlang
auto const& return_signature() const
{
return m_method.ReturnType();
return m_signature.ReturnType();
}
auto return_param_name() const
@ -62,9 +68,58 @@ namespace xlang
return name;
}
MethodDef const& method() const
{
return m_method;
}
bool is_async() const
{
// WinRT parameter passing conventions include the notion that input parameters of collection types may be read
// or copied but should not be stored directly since this would lead to instability as the collection is shared
// by the caller and callee. The exception to this rule is property setters where the callee may simply store a
// reference to the collection. The collection thus becomes async in the sense that it is expected to remain
// valid beyond the duration of the call.
if (is_put_overload(m_method))
{
return true;
}
if (!m_signature.ReturnType())
{
return false;
}
bool async{};
call(m_signature.ReturnType().Type().Type(),
[&](coded_index<TypeDefOrRef> const& type)
{
auto const& [type_namespace, type_name] = get_type_namespace_and_name(type);
async = type_namespace == "Windows.Foundation" && type_name == "IAsyncAction";
},
[&](GenericTypeInstSig const& type)
{
auto const& [type_namespace, type_name] = get_type_namespace_and_name(type.GenericType());
if (type_namespace == "Windows.Foundation")
{
async =
type_name == "IAsyncOperation`1" ||
type_name == "IAsyncActionWithProgress`1" ||
type_name == "IAsyncOperationWithProgress`2";
}
},
[](auto&&) {});
return async;
}
private:
MethodDefSig m_method;
MethodDef m_method;
MethodDefSig m_signature;
std::vector<std::pair<Param, ParamSig const*>> m_params;
Param m_return;
};
@ -133,11 +188,6 @@ namespace xlang
return method.SpecialName() && starts_with(method.Name(), "add_");
}
static bool is_put_overload(MethodDef const& method)
{
return method.SpecialName() && starts_with(method.Name(), "put_");
}
static bool is_get_overload(MethodDef const& method)
{
return method.SpecialName() && starts_with(method.Name(), "get_");
@ -204,43 +254,6 @@ namespace xlang
return {};
}
static bool is_async(MethodDef const& method, method_signature const& method_signature)
{
if (is_put_overload(method))
{
return true;
}
if (!method_signature.return_signature())
{
return false;
}
bool async{};
call(method_signature.return_signature().Type().Type(),
[&](coded_index<TypeDefOrRef> const& type)
{
auto const& [type_namespace, type_name] = get_type_namespace_and_name(type);
async = type_namespace == "Windows.Foundation" && type_name == "IAsyncAction";
},
[&](GenericTypeInstSig const& type)
{
auto const& [type_namespace, type_name] = get_type_namespace_and_name(type.GenericType());
if (type_namespace == "Windows.Foundation")
{
async =
type_name == "IAsyncOperation`1" ||
type_name == "IAsyncActionWithProgress`1" ||
type_name == "IAsyncOperationWithProgress`2";
}
},
[](auto&&) {});
return async;
}
static TypeDef get_base_class(TypeDef const& derived)
{
auto extends = derived.Extends();