@@ -4387,6 +4387,11 @@ FunctionPtr Function::CreateDynamicInvocationForwarder(
43874387 // blocks inlining and can't take Function-s only Code objects.
43884388 forwarder.set_is_visible(false);
43894389
4390+ #if defined(DART_DYNAMIC_MODULES)
4391+ if (HasBytecode()) {
4392+ forwarder.ClearBytecode();
4393+ }
4394+ #endif
43904395 forwarder.ClearICDataArray();
43914396 forwarder.ClearCode();
43924397 forwarder.set_usage_counter(0);
@@ -4428,13 +4433,7 @@ FunctionPtr Function::GetDynamicInvocationForwarder(
44284433 /*create_if_absent=*/false);
44294434 if (!result.IsNull()) return result.ptr();
44304435
4431- const bool needs_dyn_forwarder =
4432- #if defined(DART_DYNAMIC_MODULES) && defined(DART_PRECOMPILED_RUNTIME)
4433- // TODO(alexmarkov)
4434- false;
4435- #else
4436- kernel::NeedsDynamicInvocationForwarder(*this);
4437- #endif
4436+ const bool needs_dyn_forwarder = NeedsDynamicInvocationForwarder();
44384437 if (!needs_dyn_forwarder) {
44394438 return ptr();
44404439 }
@@ -4455,6 +4454,90 @@ FunctionPtr Function::GetDynamicInvocationForwarder(
44554454 return result.ptr();
44564455}
44574456
4457+ bool Function::NeedsDynamicInvocationForwarder() const {
4458+ Zone* zone = Thread::Current()->zone();
4459+
4460+ // Right now closures do not need a dyn:* forwarder.
4461+ // See https://github.com/dart-lang/sdk/issues/40813
4462+ if (IsClosureFunction()) return false;
4463+
4464+ // Method extractors have no parameters to check and return value is a closure
4465+ // and therefore not an unboxed primitive type.
4466+ if (IsMethodExtractor()) {
4467+ return false;
4468+ }
4469+
4470+ // Record field getters have no parameters to check and 'dynamic' return type.
4471+ if (IsRecordFieldGetter()) {
4472+ return false;
4473+ }
4474+
4475+ // Invoke field dispatchers are dynamically generated, will invoke a getter to
4476+ // obtain the field value and then invoke ".call()" on the result.
4477+ // Those dynamically generated dispathers don't have proper kernel metadata
4478+ // associated with them - we can therefore not query if there are dynamic
4479+ // calls to them or not and are therefore conservative.
4480+ if (IsInvokeFieldDispatcher()) {
4481+ return true;
4482+ }
4483+
4484+ #if !defined(DART_PRECOMPILED_RUNTIME)
4485+ // The dyn:* forwarders perform unboxing of parameters before calling the
4486+ // actual target (which accepts unboxed parameters) and boxes return values
4487+ // of the return value.
4488+ if (HasUnboxedParameters() || HasUnboxedReturnValue()) {
4489+ return true;
4490+ }
4491+
4492+ if (MaxNumberOfParametersInRegisters(zone) > 0) {
4493+ return true;
4494+ }
4495+ #endif
4496+
4497+ // There are no parameters to type check for getters and if the return value
4498+ // is boxed, then the dyn:* forwarder is not needed.
4499+ if (IsImplicitGetterFunction()) {
4500+ return false;
4501+ }
4502+
4503+ // Covariant parameters (both explicitly covariant and generic-covariant-impl)
4504+ // are checked in the body of a function and therefore don't need checks in a
4505+ // dynamic invocation forwarder. So dynamic invocation forwarder is only
4506+ // needed if there are non-covariant parameters of non-top type.
4507+ if (IsImplicitSetterFunction()) {
4508+ const auto& field = Field::Handle(zone, accessor_field());
4509+ return !(field.is_covariant() || field.is_generic_covariant_impl());
4510+ }
4511+
4512+ const auto& type_params = TypeParameters::Handle(zone, type_parameters());
4513+ if (!type_params.IsNull()) {
4514+ auto& bound = AbstractType::Handle(zone);
4515+ for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
4516+ bound = type_params.BoundAt(i);
4517+ if (!bound.IsTopTypeForSubtyping() &&
4518+ !type_params.IsGenericCovariantImplAt(i)) {
4519+ return true;
4520+ }
4521+ }
4522+ }
4523+
4524+ const intptr_t num_params = NumParameters();
4525+ BitVector is_covariant(zone, num_params);
4526+ BitVector is_generic_covariant_impl(zone, num_params);
4527+ ReadParameterCovariance(&is_covariant, &is_generic_covariant_impl);
4528+
4529+ auto& type = AbstractType::Handle(zone);
4530+ for (intptr_t i = NumImplicitParameters(); i < num_params; ++i) {
4531+ type = ParameterTypeAt(i);
4532+ if (!type.IsTopTypeForSubtyping() &&
4533+ !is_generic_covariant_impl.Contains(i) && !is_covariant.Contains(i)) {
4534+ return true;
4535+ }
4536+ }
4537+
4538+ return false;
4539+ }
4540+
44584541void Function::ReadParameterCovariance(
44594542 BitVector* is_covariant,
44604543 BitVector* is_generic_covariant_impl) const {
@@ -8393,6 +8476,12 @@ void Function::AttachBytecode(const Bytecode& value) const {
83938476 SetInstructions(StubCode::InterpretCall());
83948477}
83958478
8479+ void Function::ClearBytecode() const {
8480+ ASSERT(HasBytecode());
8481+ untag()->set_ic_data_array_or_bytecode(Object::null());
8482+ ClearCode();
8483+ }
8484+
83968485#endif // defined(DART_DYNAMIC_MODULES)
83978486
83988487bool Function::HasCode(FunctionPtr function) {
@@ -11916,8 +12005,7 @@ bool Function::NeedsMonomorphicCheckedEntry(Zone* zone) const {
1191612005
1191712006 // Only if there are dynamic callers and if we didn't create a dyn:* forwarder
1191812007 // for it do we need the monomorphic checked entry.
11919- return HasDynamicCallers(zone) &&
11920- !kernel::NeedsDynamicInvocationForwarder(*this);
12008+ return HasDynamicCallers(zone) && !NeedsDynamicInvocationForwarder();
1192112009#else
1192212010 UNREACHABLE();
1192312011 return true;
0 commit comments