diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc index f57a6c4839e..370b9d72a41 100644 --- a/runtime/lib/isolate.cc +++ b/runtime/lib/isolate.cc @@ -330,7 +330,6 @@ class IsolateSpawnState { IsolateSpawnState(Dart_Port parent_port, Dart_Port origin_id, const char* script_url, - const Function& func, PersistentHandle* closure_tuple_handle, SerializedObjectBuffer* message_buffer, const char* package_config, @@ -415,7 +414,6 @@ static const char* NewConstChar(const char* chars) { IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, Dart_Port origin_id, const char* script_url, - const Function& func, PersistentHandle* closure_tuple_handle, SerializedObjectBuffer* message_buffer, const char* package_config, @@ -438,30 +436,11 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, serialized_message_(message_buffer->StealMessage()), paused_(paused), errors_are_fatal_(errors_are_fatal) { - // Either we have a top-level function or we have a closure. - ASSERT((closure_tuple_handle_ != nullptr) == func.IsNull()); + ASSERT(closure_tuple_handle_ != nullptr); auto thread = Thread::Current(); auto isolate = thread->isolate(); - if (!func.IsNull()) { - auto zone = thread->zone(); - const auto& cls = Class::Handle(zone, func.Owner()); - const auto& lib = Library::Handle(zone, cls.library()); - const auto& lib_url = String::Handle(zone, lib.url()); - library_url_ = NewConstChar(lib_url.ToCString()); - - String& func_name = String::Handle(zone); - func_name = func.name(); - function_name_ = NewConstChar(String::ScrubName(func_name)); - if (!cls.IsTopLevel()) { - const auto& class_name = String::Handle(zone, cls.Name()); - class_name_ = NewConstChar(class_name.ToCString()); - } - } else { - ASSERT(closure_tuple_handle != nullptr); - } - // Inherit flags from spawning isolate. isolate->FlagsCopyTo(isolate_flags()); } @@ -908,19 +887,6 @@ static const char* String2UTF8(const String& str) { return result; } -static FunctionPtr GetTopLevelFunction(Zone* zone, const Instance& closure) { - if (closure.IsClosure()) { - auto& func = Function::Handle(zone); - func = Closure::Cast(closure).function(); - if (func.IsImplicitClosureFunction() && func.is_static()) { - ASSERT(Closure::Cast(closure).context() == Context::null()); - // Get the parent function so that we get the right function name. - return func.parent_function(); - } - } - return Function::null(); -} - DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(String, script_uri, arguments->NativeArgAt(1)); @@ -933,20 +899,17 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(8)); GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(9)); - const auto& func = Function::Handle(zone, GetTopLevelFunction(zone, closure)); PersistentHandle* closure_tuple_handle = nullptr; - if (func.IsNull()) { - // We have a non-toplevel closure that we might need to copy. - // Result will be [, ] - const auto& closure_copy_tuple = Object::Handle( - zone, CopyMutableObjectGraph(closure)); // Throws if it fails. - ASSERT(closure_copy_tuple.IsArray()); - ASSERT(Object::Handle(zone, Array::Cast(closure_copy_tuple).At(0)) - .IsClosure()); - closure_tuple_handle = - isolate->group()->api_state()->AllocatePersistentHandle(); - closure_tuple_handle->set_ptr(closure_copy_tuple.ptr()); - } + // We have a non-toplevel closure that we might need to copy. + // Result will be [, ] + const auto& closure_copy_tuple = Object::Handle( + zone, CopyMutableObjectGraph(closure)); // Throws if it fails. + ASSERT(closure_copy_tuple.IsArray()); + ASSERT( + Object::Handle(zone, Array::Cast(closure_copy_tuple).At(0)).IsClosure()); + closure_tuple_handle = + isolate->group()->api_state()->AllocatePersistentHandle(); + closure_tuple_handle->set_ptr(closure_copy_tuple.ptr()); bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value(); Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); @@ -964,15 +927,13 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { const char* utf8_debug_name = debugName.IsNull() ? NULL : String2UTF8(debugName); if (closure_tuple_handle != nullptr && utf8_debug_name == nullptr) { - ASSERT(func.IsNull()); - const auto& closure_function = Function::Handle(zone, closure.function()); utf8_debug_name = NewConstChar(closure_function.QualifiedUserVisibleNameCString()); } std::unique_ptr state(new IsolateSpawnState( - port.Id(), isolate->origin_id(), String2UTF8(script_uri), func, + port.Id(), isolate->origin_id(), String2UTF8(script_uri), closure_tuple_handle, &message_buffer, utf8_package_config, paused.value(), fatal_errors, on_exit_port, on_error_port, utf8_debug_name, isolate->group())); diff --git a/runtime/tests/vm/dart/isolates/spawn_generic_function_test.dart b/runtime/tests/vm/dart/isolates/spawn_generic_function_test.dart new file mode 100644 index 00000000000..3b9831a76e1 --- /dev/null +++ b/runtime/tests/vm/dart/isolates/spawn_generic_function_test.dart @@ -0,0 +1,45 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// +// Tests that generic functions are spawned with correct type arguments + +import 'dart:isolate'; +import 'package:expect/expect.dart'; + +void func(T o) { + print("$o:$T"); + Expect.equals("int", "$T"); +} + +void call2(dynamic f) { + f(2); +} + +void call4(dynamic f) { + f(4); +} + +void main() async { + { + final rp = ReceivePort(); + Isolate.spawn(func, 1, onExit: rp.sendPort); + await rp.first; + } + { + final rp = ReceivePort(); + Isolate.spawn(call2, func, onExit: rp.sendPort); + await rp.first; + } + void Function(int) to = func; + { + final rp = ReceivePort(); + Isolate.spawn(to, 3, onExit: rp.sendPort); + await rp.first; + } + { + final rp = ReceivePort(); + Isolate.spawn(call4, to, onExit: rp.sendPort); + await rp.first; + } +} diff --git a/runtime/tests/vm/dart_2/isolates/spawn_generic_function_test.dart b/runtime/tests/vm/dart_2/isolates/spawn_generic_function_test.dart new file mode 100644 index 00000000000..85290157b71 --- /dev/null +++ b/runtime/tests/vm/dart_2/isolates/spawn_generic_function_test.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// +// Tests that generic functions are spawned with correct type arguments + +// @dart = 2.9 + +import 'dart:isolate'; +import 'package:expect/expect.dart'; + +void func(T o) { + print("$o:$T"); + Expect.equals("int", "$T"); +} + +void call4(dynamic f) { + f(4); +} + +void main() async { + void Function(int) to = func; + { + final rp = ReceivePort(); + Isolate.spawn(to, 3, onExit: rp.sendPort); + await rp.first; + } + { + final rp = ReceivePort(); + Isolate.spawn(call4, to, onExit: rp.sendPort); + await rp.first; + } +}