diff --git a/CHANGELOG.md b/CHANGELOG.md index 266cce2f7403..458fe3d6d9cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ### Core library changes +#### `dart:isolate` + +* Added `debugName` property to `Isolate`. +* Added `debugName` optional parameter to `Isolate.spawn` and + `Isolate.spawnUri`. + ### Dart VM * RegExp patterns can now use lookbehind assertions. diff --git a/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart index 999f518f031c..9ccdadad495d 100644 --- a/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart +++ b/pkg/dev_compiler/tool/input_sdk/patch/isolate_patch.dart @@ -14,6 +14,9 @@ class Isolate { @patch static Isolate get current => _unsupported(); + @patch + String get debugName => _unsupported(); + @patch static Future get packageRoot => _unsupported(); diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index f572e20250d5..15f3382f2e99 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -379,7 +379,6 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate, // For now we only support the kernel isolate coming up from an // application snapshot or from a .dill file. static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, - const char* main, const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, @@ -424,9 +423,10 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, isolate_data = new IsolateData(uri, package_root, packages_config, app_snapshot); isolate = Dart_CreateIsolate( - DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data, - isolate_snapshot_instructions, app_isolate_shared_data, - app_isolate_shared_instructions, flags, isolate_data, error); + DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, + isolate_snapshot_data, isolate_snapshot_instructions, + app_isolate_shared_data, app_isolate_shared_instructions, flags, + isolate_data, error); } if (isolate == NULL) { // Clear error from app snapshot and re-trying from kernel file. @@ -443,8 +443,9 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, const_cast(kernel_service_buffer), kernel_service_buffer_size); isolate = Dart_CreateIsolateFromKernel( - DART_KERNEL_ISOLATE_NAME, main, kernel_service_buffer, - kernel_service_buffer_size, flags, isolate_data, error); + DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, + kernel_service_buffer, kernel_service_buffer_size, flags, isolate_data, + error); } if (isolate == NULL) { @@ -463,7 +464,6 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, // For now we only support the service isolate coming up from sources // which are compiled by the VM parser. static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, - const char* main, const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, @@ -480,9 +480,9 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, const uint8_t* isolate_snapshot_instructions = app_isolate_snapshot_instructions; isolate = Dart_CreateIsolate( - script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions, - app_isolate_shared_data, app_isolate_shared_instructions, flags, - isolate_data, error); + script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data, + isolate_snapshot_instructions, app_isolate_shared_data, + app_isolate_shared_instructions, flags, isolate_data, error); #else // JIT: Service isolate uses the core libraries snapshot. @@ -493,9 +493,9 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, const uint8_t* isolate_snapshot_instructions = core_isolate_snapshot_instructions; isolate = Dart_CreateIsolate( - script_uri, NULL, isolate_snapshot_data, isolate_snapshot_instructions, - app_isolate_shared_data, app_isolate_shared_instructions, flags, - isolate_data, error); + script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data, + isolate_snapshot_instructions, app_isolate_shared_data, + app_isolate_shared_instructions, flags, isolate_data, error); #endif // !defined(DART_PRECOMPILED_RUNTIME) if (isolate == NULL) { delete isolate_data; @@ -529,7 +529,7 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, // Returns newly created Isolate on success, NULL on failure. static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate, const char* script_uri, - const char* main, + const char* name, const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, @@ -626,17 +626,17 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate, // application kernel binary is self contained or an incremental binary. // Isolate should be created only if it is a self contained kernel binary. isolate = Dart_CreateIsolateFromKernel( - script_uri, main, platform_kernel_buffer, platform_kernel_buffer_size, + script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size, flags, isolate_data, error); } else { isolate = Dart_CreateIsolate( - script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions, + script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions, app_isolate_shared_data, app_isolate_shared_instructions, flags, isolate_data, error); } #else isolate = Dart_CreateIsolate( - script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions, + script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions, app_isolate_shared_data, app_isolate_shared_instructions, flags, isolate_data, error); #endif // !defined(DART_PRECOMPILED_RUNTIME) @@ -677,15 +677,13 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, int exit_code = 0; #if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) { - return CreateAndSetupKernelIsolate(script_uri, main, package_root, - package_config, flags, error, - &exit_code); + return CreateAndSetupKernelIsolate(script_uri, package_root, package_config, + flags, error, &exit_code); } #endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) { - return CreateAndSetupServiceIsolate(script_uri, main, package_root, - package_config, flags, error, - &exit_code); + return CreateAndSetupServiceIsolate( + script_uri, package_root, package_config, flags, error, &exit_code); } bool is_main_isolate = false; return CreateIsolateAndSetupHelper(is_main_isolate, script_uri, main, @@ -693,21 +691,6 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, callback_data, error, &exit_code); } -char* BuildIsolateName(const char* script_name, const char* func_name) { - // Skip past any slashes in the script name. - const char* last_slash = strrchr(script_name, '/'); - if (last_slash != NULL) { - script_name = last_slash + 1; - } - - const char* kFormat = "%s/%s"; - intptr_t len = strlen(script_name) + strlen(func_name) + 2; - char* buffer = new char[len]; - ASSERT(buffer != NULL); - snprintf(buffer, len, kFormat, script_name, func_name); - return buffer; -} - static void OnIsolateShutdown(void* callback_data) { Dart_EnterScope(); @@ -818,7 +801,6 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) { char* error = NULL; bool is_main_isolate = true; int exit_code = 0; - char* isolate_name = BuildIsolateName(script_name, "main"); Dart_IsolateFlags flags; Dart_IsolateFlagsInitialize(&flags); @@ -828,7 +810,6 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) { &exit_code); if (isolate == NULL) { - delete[] isolate_name; Log::PrintErr("%s\n", error); free(error); error = NULL; @@ -843,7 +824,6 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) { Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode); } main_isolate = isolate; - delete[] isolate_name; Dart_EnterIsolate(isolate); ASSERT(isolate == Dart_CurrentIsolate()); diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc index f024c4db8ca5..4eb653e4e6df 100644 --- a/runtime/bin/run_vm_tests.cc +++ b/runtime/bin/run_vm_tests.cc @@ -148,9 +148,10 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, &isolate_snapshot_data, &isolate_snapshot_instructions); isolate_data = new bin::IsolateData(script_uri, package_root, packages_config, app_snapshot); - isolate = Dart_CreateIsolate( - DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data, - isolate_snapshot_instructions, NULL, NULL, flags, isolate_data, error); + isolate = + Dart_CreateIsolate(DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, + isolate_snapshot_data, isolate_snapshot_instructions, + NULL, NULL, flags, isolate_data, error); if (*error != NULL) { free(*error); *error = NULL; diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 1c4c151cf229..51a1f8072806 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -836,9 +836,8 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name); * The VM will provide this URI to the Dart_IsolateCreateCallback when a child * isolate is created by Isolate.spawn. The embedder should use a URI that * allows it to load the same program into such a child isolate. - * \param main The name of the main entry point this isolate will run. Provided - * only for advisory purposes to improve debugging messages. Typically either - * 'main' or the name of the function passed to Isolate.spawn. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. * \param isolate_snapshot_data * \param isolate_snapshot_instructions Buffers containing a snapshot of the * isolate or NULL if no snapshot is provided. If provided, the buffers must @@ -855,7 +854,7 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name); */ DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri, - const char* main, + const char* name, const uint8_t* isolate_snapshot_data, const uint8_t* isolate_snapshot_instructions, const uint8_t* shared_data, @@ -876,9 +875,8 @@ Dart_CreateIsolate(const char* script_uri, * The VM will provide this URI to the Dart_IsolateCreateCallback when a child * isolate is created by Isolate.spawn. The embedder should use a URI that * allows it to load the same program into such a child isolate. - * \param main The name of the main entry point this isolate will run. Provided - * only for advisory purposes to improve debugging messages. Typically either - * 'main' or the name of the function passed to Isolate.spawn. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. * \param kernel_buffer * \param kernel_buffer_size A buffer which contains a kernel/DIL program. Must * remain valid until isolate shutdown. @@ -894,7 +892,7 @@ Dart_CreateIsolate(const char* script_uri, */ DART_EXPORT Dart_Isolate Dart_CreateIsolateFromKernel(const char* script_uri, - const char* main, + const char* name, const uint8_t* kernel_buffer, intptr_t kernel_buffer_size, Dart_IsolateFlags* flags, diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc index b92514741eb0..d0031d794c4b 100644 --- a/runtime/lib/isolate.cc +++ b/runtime/lib/isolate.cc @@ -130,9 +130,12 @@ class SpawnIsolateTask : public ThreadPool::Task { // Make a copy of the state's isolate flags and hand it to the callback. Dart_IsolateFlags api_flags = *(state_->isolate_flags()); + const char* name = (state_->debug_name() == NULL) ? state_->function_name() + : state_->debug_name(); + ASSERT(name != NULL); Isolate* isolate = reinterpret_cast((callback)( - state_->script_url(), state_->function_name(), state_->package_root(), + state_->script_url(), name, state_->package_root(), state_->package_config(), &api_flags, state_->init_data(), &error)); state_->DecrementSpawnCount(); if (isolate == NULL) { @@ -182,7 +185,7 @@ static const char* String2UTF8(const String& str) { return result; } -DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { +DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) { GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(String, script_uri, arguments->NativeArgAt(1)); GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(2)); @@ -193,6 +196,7 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { GET_NATIVE_ARGUMENT(SendPort, onError, arguments->NativeArgAt(7)); GET_NATIVE_ARGUMENT(String, packageRoot, arguments->NativeArgAt(8)); GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(9)); + GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(10)); if (closure.IsClosure()) { Function& func = Function::Handle(); @@ -223,13 +227,15 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { const char* utf8_package_root = NULL; const char* utf8_package_config = packageConfig.IsNull() ? NULL : String2UTF8(packageConfig); + const char* utf8_debug_name = + debugName.IsNull() ? NULL : String2UTF8(debugName); IsolateSpawnState* state = new IsolateSpawnState( port.Id(), isolate->origin_id(), isolate->init_callback_data(), String2UTF8(script_uri), func, &message_buffer, isolate->spawn_count_monitor(), isolate->spawn_count(), utf8_package_root, utf8_package_config, paused.value(), fatal_errors, - on_exit_port, on_error_port); + on_exit_port, on_error_port, utf8_debug_name); // Since this is a call to Isolate.spawn, copy the parent isolate's code. state->isolate_flags()->copy_parent_code = true; @@ -285,7 +291,7 @@ static const char* CanonicalizeUri(Thread* thread, return result; } -DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) { +DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 13) { GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(1)); @@ -304,6 +310,8 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) { GET_NATIVE_ARGUMENT(String, packageRoot, arguments->NativeArgAt(10)); GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(11)); + GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(12)); + if (Dart::vm_snapshot_kind() == Snapshot::kFullAOT) { const Array& args = Array::Handle(Array::New(1)); args.SetAt( @@ -347,12 +355,15 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) { const char* utf8_package_root = NULL; const char* utf8_package_config = packageConfig.IsNull() ? NULL : String2UTF8(packageConfig); + const char* utf8_debug_name = + debugName.IsNull() ? NULL : String2UTF8(debugName); IsolateSpawnState* state = new IsolateSpawnState( port.Id(), isolate->init_callback_data(), canonical_uri, utf8_package_root, utf8_package_config, &arguments_buffer, &message_buffer, isolate->spawn_count_monitor(), isolate->spawn_count(), - paused.value(), fatal_errors, on_exit_port, on_error_port); + paused.value(), fatal_errors, on_exit_port, on_error_port, + utf8_debug_name); // If we were passed a value then override the default flags state for // checked mode. @@ -378,6 +389,15 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) { return Object::null(); } +DEFINE_NATIVE_ENTRY(Isolate_getDebugName, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); + Isolate* isolate_lookup = Isolate::LookupIsolateByPort(port.Id()); + if (isolate_lookup == NULL) { + return Object::null(); + } + return String::New(isolate_lookup->name()); +} + DEFINE_NATIVE_ENTRY(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0, 0) { const Array& result = Array::Handle(Array::New(3)); result.SetAt(0, SendPort::Handle(SendPort::New(isolate->main_port()))); diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart index 5e5c2351ec2d..cdd539484098 100644 --- a/runtime/lib/isolate_patch.dart +++ b/runtime/lib/isolate_patch.dart @@ -315,6 +315,9 @@ class Isolate { @patch static Isolate get current => _currentIsolate; + @patch + String get debugName => _getDebugName(controlPort); + @patch static Future get packageRoot { var hook = VMLibraryHooks.packageRootUriFuture; @@ -352,7 +355,8 @@ class Isolate { {bool paused: false, bool errorsAreFatal, SendPort onExit, - SendPort onError}) async { + SendPort onError, + String debugName}) async { // `paused` isn't handled yet. RawReceivePort readyPort; try { @@ -377,8 +381,18 @@ class Isolate { script = await Isolate.resolvePackageUri(script); } - _spawnFunction(readyPort.sendPort, script.toString(), entryPoint, message, - paused, errorsAreFatal, onExit, onError, null, packageConfig); + _spawnFunction( + readyPort.sendPort, + script.toString(), + entryPoint, + message, + paused, + errorsAreFatal, + onExit, + onError, + null, + packageConfig, + debugName); return await _spawnCommon(readyPort); } catch (e, st) { if (readyPort != null) { @@ -398,7 +412,8 @@ class Isolate { Map environment, Uri packageRoot, Uri packageConfig, - bool automaticPackageResolution: false}) async { + bool automaticPackageResolution: false, + String debugName}) async { RawReceivePort readyPort; if (environment != null) { throw new UnimplementedError("environment"); @@ -467,7 +482,8 @@ class Isolate { null, /* environment */ packageRootString, - packageConfigString); + packageConfigString, + debugName); return await _spawnCommon(readyPort); } catch (e) { if (readyPort != null) { @@ -524,7 +540,8 @@ class Isolate { SendPort onExit, SendPort onError, String packageRoot, - String packageConfig) native "Isolate_spawnFunction"; + String packageConfig, + String debugName) native "Isolate_spawnFunction"; static void _spawnUri( SendPort readyPort, @@ -538,10 +555,14 @@ class Isolate { bool checked, List environment, String packageRoot, - String packageConfig) native "Isolate_spawnUri"; + String packageConfig, + String debugName) native "Isolate_spawnUri"; static void _sendOOB(port, msg) native "Isolate_sendOOB"; + static String _getDebugName(SendPort controlPort) + native "Isolate_getDebugName"; + @patch void _pause(Capability resumeCapability) { var msg = new List(4) diff --git a/runtime/observatory/tests/service/dev_fs_spawn_test.dart b/runtime/observatory/tests/service/dev_fs_spawn_test.dart index c0a182e796df..1221a583d9ff 100644 --- a/runtime/observatory/tests/service/dev_fs_spawn_test.dart +++ b/runtime/observatory/tests/service/dev_fs_spawn_test.dart @@ -118,7 +118,7 @@ main(args, msg) { if (event.kind == ServiceEvent.kIsolateSpawn) { expect(event.spawnToken, equals('mySpawnToken0')); expect(event.isolate, isNotNull); - expect(event.isolate.name, equals('devfs_file0.dart:main()')); + expect(event.isolate.name, equals('main')); completer.complete(event.isolate); sub.cancel(); } @@ -147,7 +147,7 @@ main(args, msg) { if (event.kind == ServiceEvent.kIsolateSpawn) { expect(event.spawnToken, equals('mySpawnToken1')); expect(event.isolate, isNotNull); - expect(event.isolate.name, equals('devfs_file1.dart:main()')); + expect(event.isolate.name, equals('main')); completer.complete(event.isolate); sub.cancel(); } @@ -177,7 +177,7 @@ main(args, msg) { if (event.kind == ServiceEvent.kIsolateSpawn) { expect(event.spawnToken, equals('mySpawnToken2')); expect(event.isolate, isNotNull); - expect(event.isolate.name, equals('devfs_file2.dart:main()')); + expect(event.isolate.name, equals('main')); completer.complete(event.isolate); sub.cancel(); } diff --git a/runtime/observatory/tests/service/set_name_rpc_test.dart b/runtime/observatory/tests/service/set_name_rpc_test.dart index 1d743ccfc292..186e4e0fa4f0 100644 --- a/runtime/observatory/tests/service/set_name_rpc_test.dart +++ b/runtime/observatory/tests/service/set_name_rpc_test.dart @@ -10,11 +10,7 @@ import 'dart:async'; var tests = [ (Isolate isolate) async { - expect( - ((isolate.name == 'set_name_rpc_test.dart:main()') || - (isolate.name == 'out.jitsnapshot:main()')), - isTrue); - + expect(isolate.name == 'main', isTrue); Completer completer = new Completer(); var stream = await isolate.vm.getEventStream(VM.kIsolateStream); var subscription; diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 194a86c496c8..bedb991187d7 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -294,11 +294,12 @@ namespace dart { V(Int32x4_setFlagZ, 2) \ V(Int32x4_setFlagW, 2) \ V(Int32x4_select, 3) \ - V(Isolate_spawnFunction, 10) \ - V(Isolate_spawnUri, 12) \ + V(Isolate_spawnFunction, 11) \ + V(Isolate_spawnUri, 13) \ V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) \ V(Isolate_getCurrentRootUriStr, 0) \ V(Isolate_sendOOB, 2) \ + V(Isolate_getDebugName, 1) \ V(GrowableList_allocate, 2) \ V(GrowableList_getIndexed, 2) \ V(GrowableList_setIndexed, 3) \ diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 0939522629ec..f407d714559c 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -1075,43 +1075,8 @@ ISOLATE_METRIC_LIST(ISOLATE_METRIC_API); // --- Isolates --- -static char* BuildIsolateName(const char* script_uri, const char* main) { - if (script_uri == NULL) { - // Just use the main as the name. - if (main == NULL) { - return strdup("isolate"); - } else { - return strdup(main); - } - } - - if (ServiceIsolate::NameEquals(script_uri) || - (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0)) { - return strdup(script_uri); - } - - // Skip past any slashes and backslashes in the script uri. - const char* last_slash = strrchr(script_uri, '/'); - if (last_slash != NULL) { - script_uri = last_slash + 1; - } - const char* last_backslash = strrchr(script_uri, '\\'); - if (last_backslash != NULL) { - script_uri = last_backslash + 1; - } - if (main == NULL) { - main = "main"; - } - - char* chars = NULL; - intptr_t len = Utils::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1; - chars = reinterpret_cast(malloc(len)); - Utils::SNPrint(chars, len, "%s:%s()", script_uri, main); - return chars; -} - static Dart_Isolate CreateIsolate(const char* script_uri, - const char* main, + const char* name, const uint8_t* snapshot_data, const uint8_t* snapshot_instructions, const uint8_t* shared_data, @@ -1122,7 +1087,6 @@ static Dart_Isolate CreateIsolate(const char* script_uri, void* callback_data, char** error) { CHECK_NO_ISOLATE(Isolate::Current()); - char* isolate_name = BuildIsolateName(script_uri, main); // Setup default flags in case none were passed. Dart_IsolateFlags api_flags; @@ -1130,8 +1094,7 @@ static Dart_Isolate CreateIsolate(const char* script_uri, Isolate::FlagsInitialize(&api_flags); flags = &api_flags; } - Isolate* I = Dart::CreateIsolate(isolate_name, *flags); - free(isolate_name); + Isolate* I = Dart::CreateIsolate((name == NULL) ? "isolate" : name, *flags); if (I == NULL) { if (error != NULL) { *error = strdup("Isolate creation failed"); @@ -1186,7 +1149,7 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) { DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri, - const char* main, + const char* name, const uint8_t* snapshot_data, const uint8_t* snapshot_instructions, const uint8_t* shared_data, @@ -1195,21 +1158,21 @@ Dart_CreateIsolate(const char* script_uri, void* callback_data, char** error) { API_TIMELINE_DURATION(Thread::Current()); - return CreateIsolate(script_uri, main, snapshot_data, snapshot_instructions, + return CreateIsolate(script_uri, name, snapshot_data, snapshot_instructions, shared_data, shared_instructions, NULL, 0, flags, callback_data, error); } DART_EXPORT Dart_Isolate Dart_CreateIsolateFromKernel(const char* script_uri, - const char* main, + const char* name, const uint8_t* kernel_buffer, intptr_t kernel_buffer_size, Dart_IsolateFlags* flags, void* callback_data, char** error) { API_TIMELINE_DURATION(Thread::Current()); - return CreateIsolate(script_uri, main, NULL, NULL, NULL, NULL, kernel_buffer, + return CreateIsolate(script_uri, name, NULL, NULL, NULL, NULL, kernel_buffer, kernel_buffer_size, flags, callback_data, error); } diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index ce8ed3feb152..a72736e18461 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -2641,6 +2641,18 @@ intptr_t Isolate::IsolateListLength() { return count; } +Isolate* Isolate::LookupIsolateByPort(Dart_Port port) { + MonitorLocker ml(isolates_list_monitor_); + Isolate* current = isolates_list_head_; + while (current != NULL) { + if (current->main_port() == port) { + return current; + } + current = current->next_; + } + return NULL; +} + bool Isolate::AddIsolateToList(Isolate* isolate) { MonitorLocker ml(isolates_list_monitor_); if (!creation_enabled_) { @@ -2926,7 +2938,8 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, bool paused, bool errors_are_fatal, Dart_Port on_exit_port, - Dart_Port on_error_port) + Dart_Port on_error_port, + const char* debug_name) : isolate_(NULL), parent_port_(parent_port), origin_id_(origin_id), @@ -2939,6 +2952,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, library_url_(NULL), class_name_(NULL), function_name_(NULL), + debug_name_(debug_name), serialized_args_(NULL), serialized_message_(message_buffer->StealMessage()), spawn_count_monitor_(spawn_count_monitor), @@ -2975,7 +2989,8 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, bool paused, bool errors_are_fatal, Dart_Port on_exit_port, - Dart_Port on_error_port) + Dart_Port on_error_port, + const char* debug_name) : isolate_(NULL), parent_port_(parent_port), origin_id_(ILLEGAL_PORT), @@ -2988,6 +3003,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, library_url_(NULL), class_name_(NULL), function_name_(NULL), + debug_name_(debug_name), serialized_args_(args_buffer->StealMessage()), serialized_message_(message_buffer->StealMessage()), spawn_count_monitor_(spawn_count_monitor), @@ -3009,6 +3025,7 @@ IsolateSpawnState::~IsolateSpawnState() { delete[] library_url_; delete[] class_name_; delete[] function_name_; + delete[] debug_name_; delete serialized_args_; delete serialized_message_; } diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index 40f0c6f0ffa4..c4dd373294c4 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -772,6 +772,10 @@ class Isolate : public BaseIsolate { static void KillAllIsolates(LibMsgId msg_id); static void KillIfExists(Isolate* isolate, LibMsgId msg_id); + // Lookup an isolate by its main port. Returns NULL if no matching isolate is + // found. + static Isolate* LookupIsolateByPort(Dart_Port port); + static void DisableIsolateCreation(); static void EnableIsolateCreation(); static bool IsolateCreationEnabled(); @@ -1120,7 +1124,8 @@ class IsolateSpawnState { bool paused, bool errorsAreFatal, Dart_Port onExit, - Dart_Port onError); + Dart_Port onError, + const char* debug_name); IsolateSpawnState(Dart_Port parent_port, void* init_data, const char* script_url, @@ -1133,7 +1138,8 @@ class IsolateSpawnState { bool paused, bool errorsAreFatal, Dart_Port onExit, - Dart_Port onError); + Dart_Port onError, + const char* debug_name); ~IsolateSpawnState(); Isolate* isolate() const { return isolate_; } @@ -1150,6 +1156,7 @@ class IsolateSpawnState { const char* library_url() const { return library_url_; } const char* class_name() const { return class_name_; } const char* function_name() const { return function_name_; } + const char* debug_name() const { return debug_name_; } bool is_spawn_uri() const { return library_url_ == NULL; } bool paused() const { return paused_; } bool errors_are_fatal() const { return errors_are_fatal_; } @@ -1174,6 +1181,7 @@ class IsolateSpawnState { const char* library_url_; const char* class_name_; const char* function_name_; + const char* debug_name_; Message* serialized_args_; Message* serialized_message_; diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc index ab9049196eea..79fb5818b264 100644 --- a/runtime/vm/kernel_isolate.cc +++ b/runtime/vm/kernel_isolate.cc @@ -98,8 +98,9 @@ class RunKernelTask : public ThreadPool::Task { api_flags.use_osr = true; #endif - isolate = reinterpret_cast(create_callback( - KernelIsolate::kName, NULL, NULL, NULL, &api_flags, NULL, &error)); + isolate = reinterpret_cast( + create_callback(KernelIsolate::kName, KernelIsolate::kName, NULL, NULL, + &api_flags, NULL, &error)); if (isolate == NULL) { if (FLAG_trace_kernel) { OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n", diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart index 78cbf611bc74..56bab4c08bcc 100644 --- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart @@ -15,6 +15,11 @@ class Isolate { throw new UnsupportedError("Isolate.current"); } + @patch + String get debugName { + throw new UnsupportedError("Isolate.debugName"); + } + @patch static Future get packageRoot { throw new UnsupportedError("Isolate.packageRoot"); diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart index 6a737fea2384..5c5883dac582 100644 --- a/sdk/lib/isolate/isolate.dart +++ b/sdk/lib/isolate/isolate.dart @@ -111,6 +111,20 @@ class Isolate { */ final Capability terminateCapability; + /** + * The name of the [Isolate] displayed for debug purposes. + * + * This can be set using the `debugName` parameter in [spawn] and [spawnUri]. + * + * This name does not uniquely identify an isolate. Multiple isolates in the + * same process may have the same `debugName`. + * + * For a given isolate, this value will be the same as the values returned by + * `Dart_DebugName` in the C embedding API and the `debugName` property in + * [IsolateMirror]. + */ + external String get debugName; + /** * Create a new [Isolate] object with a restricted set of capabilities. * @@ -215,6 +229,9 @@ class Isolate { * corresponding parameter and was processed before the isolate starts * running. * + * If [debugName] is provided, the spawned [Isolate] will be identifiable by + * this name in debuggers and logging. + * * If [errorsAreFatal] is omitted, the platform may choose a default behavior * or inherit the current isolate's behavior. * @@ -231,7 +248,8 @@ class Isolate { {bool paused: false, bool errorsAreFatal, SendPort onExit, - SendPort onError}); + SendPort onError, + String debugName}); /** * Creates and spawns an isolate that runs the code from the library with @@ -299,6 +317,9 @@ class Isolate { * WARNING: The [environment] parameter is not implemented on all * platforms yet. * + * If [debugName] is provided, the spawned [Isolate] will be identifiable by + * this name in debuggers and logging. + * * Returns a future that will complete with an [Isolate] instance if the * spawning succeeded. It will complete with an error otherwise. */ @@ -315,7 +336,8 @@ class Isolate { @Deprecated('The packages/ dir is not supported in Dart 2') Uri packageRoot, Uri packageConfig, - bool automaticPackageResolution: false}); + bool automaticPackageResolution: false, + String debugName}); /** * Requests the isolate to pause. diff --git a/tests/lib_2/isolate/spawn_function_test.dart b/tests/lib_2/isolate/spawn_function_test.dart index eba1bfa87595..7a2a19337cb1 100644 --- a/tests/lib_2/isolate/spawn_function_test.dart +++ b/tests/lib_2/isolate/spawn_function_test.dart @@ -17,12 +17,15 @@ child(args) { void main([args, port]) { if (testRemote(main, port)) return; - test('message - reply chain', () { + test('message - reply chain', () async { ReceivePort port = new ReceivePort(); - Isolate.spawn(child, ['hi', port.sendPort]); port.listen(expectAsync((msg) { port.close(); expect(msg, equals('re: hi')); })); + const String debugName = 'spawnedIsolate'; + final i = + await Isolate.spawn(child, ['hi', port.sendPort], debugName: debugName); + expect(i.debugName, debugName); }); } diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart index 650bafa4aec6..a4d89c309681 100644 --- a/tests/lib_2/isolate/spawn_uri_test.dart +++ b/tests/lib_2/isolate/spawn_uri_test.dart @@ -12,14 +12,17 @@ import 'dart:isolate'; import 'package:expect/async_minitest.dart'; main() { - test('isolate fromUri - send and reply', () { + test('isolate fromUri - send and reply', () async { ReceivePort port = new ReceivePort(); port.listen(expectAsync((msg) { expect(msg, equals('re: hi')); port.close(); })); - Isolate.spawnUri( - Uri.parse('spawn_uri_child_isolate.dart'), ['hi'], port.sendPort); + const String debugName = 'spawnedIsolate'; + final i = await Isolate.spawnUri( + Uri.parse('spawn_uri_child_isolate.dart'), ['hi'], port.sendPort, + debugName: debugName); + expect(i.debugName, debugName); }); }