diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 03a8cc370dc..e79a7327c72 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -5950,6 +5950,23 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { compiler->GenerateStaticCall(deopt_id(), source(), function(), args_info, locs(), *call_ic_data, rebind_rule_, entry_kind()); + if (function().IsFactory()) { + TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info(); + if (type_usage_info != nullptr) { + const Class& klass = Class::Handle(function().Owner()); + if (klass.NumTypeArguments() > 0) { + if (type_args_len() > 0) { + RegisterTypeArgumentsUse(compiler->function(), type_usage_info, klass, + ArgumentAt(0), + /*convert_to_instance_type_arguments=*/true); + } else { + type_usage_info->UseTypeArgumentsInInstanceCreation( + klass, TypeArguments::Handle( + zone, klass.GetDeclarationInstanceTypeArguments())); + } + } + } + } } CachableIdempotentCallInstr::CachableIdempotentCallInstr( diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc index 4f06aa30c64..2920428918c 100644 --- a/runtime/vm/type_testing_stubs.cc +++ b/runtime/vm/type_testing_stubs.cc @@ -1262,7 +1262,8 @@ void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck( void RegisterTypeArgumentsUse(const Function& function, TypeUsageInfo* type_usage_info, const Class& klass, - Definition* type_arguments) { + Definition* type_arguments, + bool convert_to_instance_type_arguments) { // The [type_arguments] can, in the general case, be any kind of [Definition] // but generally (in order of expected frequency) // @@ -1286,15 +1287,28 @@ void RegisterTypeArgumentsUse(const Function& function, if (ConstantInstr* constant = type_arguments->AsConstant()) { const Object& object = constant->value(); ASSERT(object.IsNull() || object.IsTypeArguments()); - const TypeArguments& type_arguments = - TypeArguments::Handle(TypeArguments::RawCast(object.ptr())); - type_usage_info->UseTypeArgumentsInInstanceCreation(klass, type_arguments); + auto& ta = TypeArguments::Handle(TypeArguments::RawCast(object.ptr())); + if (convert_to_instance_type_arguments) { + if (!ta.IsNull() && (ta.Length() > klass.NumTypeParameters())) { + // Account for sharing of larger type arguments vectors. + ta = ta.TruncatedTo(klass.NumTypeParameters()); + } + ta = klass.GetInstanceTypeArguments(Thread::Current(), ta); + } + type_usage_info->UseTypeArgumentsInInstanceCreation(klass, ta); } else if (InstantiateTypeArgumentsInstr* instantiate = type_arguments->AsInstantiateTypeArguments()) { if (instantiate->type_arguments()->BindsToConstant() && !instantiate->type_arguments()->BoundConstant().IsNull()) { - const auto& ta = - TypeArguments::Cast(instantiate->type_arguments()->BoundConstant()); + auto& ta = TypeArguments::Handle(TypeArguments::RawCast( + instantiate->type_arguments()->BoundConstant().ptr())); + if (convert_to_instance_type_arguments) { + if (!ta.IsNull() && (ta.Length() > klass.NumTypeParameters())) { + // Account for sharing of larger type arguments vectors. + ta = ta.TruncatedTo(klass.NumTypeParameters()); + } + ta = klass.GetInstanceTypeArguments(Thread::Current(), ta); + } type_usage_info->UseTypeArgumentsInInstanceCreation(klass, ta); } } else if (LoadFieldInstr* load_field = type_arguments->AsLoadField()) { @@ -1362,7 +1376,8 @@ void RegisterTypeArgumentsUse(const Function& function, void RegisterTypeArgumentsUse(const Function& function, TypeUsageInfo* type_usage_info, const Class& klass, - Definition* type_arguments) { + Definition* type_arguments, + bool convert_to_instance_type_arguments) { // We only have a [TypeUsageInfo] object available durin AOT compilation. UNREACHABLE(); } diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h index 3ccf78c2d4b..c1e43ed7396 100644 --- a/runtime/vm/type_testing_stubs.h +++ b/runtime/vm/type_testing_stubs.h @@ -264,7 +264,8 @@ class TypeUsageInfo : public ThreadStackResource { void RegisterTypeArgumentsUse(const Function& function, TypeUsageInfo* type_usage_info, const Class& klass, - Definition* type_arguments); + Definition* type_arguments, + bool convert_to_instance_type_arguments = false); #endif #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)