From fe30c3f23556a4859cbb52b2dcf0736550cd46be Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 26 Apr 2022 07:53:43 +0000 Subject: [PATCH] [vm] Expose whether extension stream has listeners, guard postEvent This avoids json encoding that was otherwise happening even in product mode. JSON encoding shows up CPU profiling as taking significant time, particularly on low end devices. TEST=runtime/observatory/tests/service/developer_extension_test.dart Bug: https://github.com/dart-lang/sdk/issues/48860 Change-Id: I2cf4d949e85c0b23de01ec2033b04527d40c76fe Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/242081 Reviewed-by: Ben Konyi Reviewed-by: Lasse Nielsen Reviewed-by: Alexander Markov Reviewed-by: Daco Harkes Commit-Queue: Dan Field --- .../docs/compiler/aot/entry_point_pragma.md | 6 +- .../observatory/lib/src/service/object.dart | 6 +- .../service/developer_extension_test.dart | 7 +- .../service_2/developer_extension_test.dart | 2 +- runtime/vm/compiler/frontend/kernel_to_il.cc | 20 +++ runtime/vm/compiler/frontend/kernel_to_il.h | 3 + runtime/vm/compiler/recognized_methods_list.h | 1 + runtime/vm/compiler/runtime_api.h | 6 + .../vm/compiler/runtime_offsets_extracted.h | 150 ++++++++++++++---- runtime/vm/compiler/runtime_offsets_list.h | 2 + runtime/vm/object.cc | 69 ++++++-- runtime/vm/object.h | 41 +---- runtime/vm/service.h | 11 +- runtime/vm/thread.cc | 96 +++++------ runtime/vm/thread.h | 7 + .../js_dev_runtime/patch/developer_patch.dart | 12 +- .../js_runtime/lib/developer_patch.dart | 3 + sdk/lib/_internal/wasm/lib/developer.dart | 3 + sdk/lib/developer/developer.dart | 1 + sdk/lib/developer/extension.dart | 38 ++++- tests/dartdevc/developer_events_test.dart | 10 +- tests/dartdevc_2/developer_events_test.dart | 10 +- 22 files changed, 334 insertions(+), 170 deletions(-) diff --git a/runtime/docs/compiler/aot/entry_point_pragma.md b/runtime/docs/compiler/aot/entry_point_pragma.md index 3694a98444b..fc68848a9d8 100644 --- a/runtime/docs/compiler/aot/entry_point_pragma.md +++ b/runtime/docs/compiler/aot/entry_point_pragma.md @@ -35,7 +35,7 @@ Any one of the following forms may be attached to a class: ```dart @pragma("vm:entry-point") @pragma("vm:entry-point", true/false) -@pragma("vm:entry-point", !const bool.formEnvironment("dart.vm.product")) +@pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product")) class C { ... } ``` @@ -54,7 +54,7 @@ getters, setters and constructors): ```dart @pragma("vm:entry-point") @pragma("vm:entry-point", true/false) -@pragma("vm:entry-point", !const bool.formEnvironment("dart.vm.product")) +@pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product")) @pragma("vm:entry-point", "get") @pragma("vm:entry-point", "call") void foo() { ... } @@ -83,7 +83,7 @@ three forms may be attached to static fields. @pragma("vm:entry-point") @pragma("vm:entry-point", null) @pragma("vm:entry-point", true/false) -@pragma("vm:entry-point", !const bool.formEnvironment("dart.vm.product")) +@pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product")) @pragma("vm:entry-point", "get"/"set") int foo; ``` diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart index a3e51a4bad6..181fd2b9059 100644 --- a/runtime/observatory/lib/src/service/object.dart +++ b/runtime/observatory/lib/src/service/object.dart @@ -1042,9 +1042,9 @@ abstract class VM extends ServiceObjectOwner implements M.VM { nativeZoneMemoryUsage = map['_nativeZoneMemoryUsage']; } pid = map['pid']; - mallocUsed = map['_mallocUsed']; - mallocCapacity = map['_mallocCapacity']; - mallocImplementation = map['_mallocImplementation']; + mallocUsed = map['_mallocUsed'] ?? -1; + mallocCapacity = map['_mallocCapacity'] ?? -1; + mallocImplementation = map['_mallocImplementation'] ?? 'unknown'; embedder = map['_embedder']; currentMemory = map['_currentMemory']; maxRSS = map['_maxRSS']; diff --git a/runtime/observatory/tests/service/developer_extension_test.dart b/runtime/observatory/tests/service/developer_extension_test.dart index 9b18926ce0c..2983cf45da7 100644 --- a/runtime/observatory/tests/service/developer_extension_test.dart +++ b/runtime/observatory/tests/service/developer_extension_test.dart @@ -43,10 +43,15 @@ Future Handler(String method, Map paremeters) { } void test() { + Expect.isFalse(extensionStreamHasListener); + postEvent('Disabled event', {'foo': 'bar'}); + registerExtension('ext..delay', Handler); debugger(); + Expect.isTrue(extensionStreamHasListener); postEvent('ALPHA', {'cat': 'dog'}); debugger(); + registerExtension('ext..error', Handler); registerExtension('ext..exception', Handler); registerExtension('ext..success', Handler); @@ -56,7 +61,7 @@ void test() { } catch (e) { exceptionThrown = true; } - // This check is running in the target process so we can't used package:test. + // This check is running in the target process so we can't use package:test. Expect.isTrue(exceptionThrown); } diff --git a/runtime/observatory_2/tests/service_2/developer_extension_test.dart b/runtime/observatory_2/tests/service_2/developer_extension_test.dart index 61cab8ff4c2..e6df8972d20 100644 --- a/runtime/observatory_2/tests/service_2/developer_extension_test.dart +++ b/runtime/observatory_2/tests/service_2/developer_extension_test.dart @@ -55,7 +55,7 @@ void test() { } catch (e) { exceptionThrown = true; } - // This check is running in the target process so we can't used package:test. + // This check is running in the target process so we can't use package:test. Expect.isTrue(exceptionThrown); } diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 905570f7aa7..a7699015535 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -952,6 +952,7 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph( case MethodRecognizer::kReachabilityFence: case MethodRecognizer::kUtf8DecoderScan: case MethodRecognizer::kHas63BitSmis: + case MethodRecognizer::kExtensionStreamHasListener: #define CASE(method, slot) case MethodRecognizer::k##method: LOAD_NATIVE_FIELD(CASE) STORE_NATIVE_FIELD(CASE) @@ -1488,6 +1489,17 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( #else body += Constant(Bool::False()); #endif // defined(ARCH_IS_64_BIT) + } break; + case MethodRecognizer::kExtensionStreamHasListener: { +#ifdef PRODUCT + body += Constant(Bool::False()); +#else + body += LoadServiceExtensionStream(); + body += RawLoadField(compiler::target::StreamInfo::enabled_offset()); + // StreamInfo::enabled_ is a std::atomic. This is effectively + // relaxed order access, which is acceptable for this use case. + body += IntToBool(); +#endif // PRODUCT } break; case MethodRecognizer::kFfiAsExternalTypedDataInt8: case MethodRecognizer::kFfiAsExternalTypedDataInt16: @@ -4077,6 +4089,14 @@ Fragment FlowGraphBuilder::LoadIsolate() { return body; } +Fragment FlowGraphBuilder::LoadServiceExtensionStream() { + Fragment body; + body += LoadThread(); + body += + LoadUntagged(compiler::target::Thread::service_extension_stream_offset()); + return body; +} + // TODO(http://dartbug.com/47487): Support unboxed output value. Fragment FlowGraphBuilder::BoolToInt() { // TODO(http://dartbug.com/36855) Build IfThenElseInstr, instead of letting diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h index 2a92d6ae212..eeab45d479d 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.h +++ b/runtime/vm/compiler/frontend/kernel_to_il.h @@ -282,6 +282,9 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder { // Loads the (untagged) isolate address. Fragment LoadIsolate(); + // Loads the (untagged) service extension stream address. + Fragment LoadServiceExtensionStream(); + // Converts a true to 1 and false to 0. Fragment BoolToInt(); diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h index 7055a025d60..0331e006143 100644 --- a/runtime/vm/compiler/recognized_methods_list.h +++ b/runtime/vm/compiler/recognized_methods_list.h @@ -268,6 +268,7 @@ namespace dart { V(_RootZone, runUnary, RootZoneRunUnary, 0xb607f8bf) \ V(_FutureListener, handleValue, FutureListenerHandleValue, 0x438115a8) \ V(::, has63BitSmis, Has63BitSmis, 0xf61b56f1) \ + V(::, get:extensionStreamHasListener, ExtensionStreamHasListener, 0xfab46343)\ // List of intrinsics: // (class-name, function-name, intrinsification method, fingerprint). diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 41ad454c44f..f36cdc73647 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -1068,6 +1068,11 @@ class TimelineStream : public AllStatic { static word enabled_offset(); }; +class StreamInfo : public AllStatic { + public: + static word enabled_offset(); +}; + class VMHandles : public AllStatic { public: static constexpr intptr_t kOffsetOfRawPtrInHandle = kWordSize; @@ -1099,6 +1104,7 @@ class Thread : public AllStatic { static uword exit_through_runtime_call(); static uword exit_through_ffi(); static word dart_stream_offset(); + static word service_extension_stream_offset(); static word predefined_symbols_address_offset(); static word optimize_entry_offset(); static word deoptimize_entry_offset(); diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 04a65b3697a..49c7e2649fe 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -240,6 +240,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -287,6 +288,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 796; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 820; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -330,7 +333,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 788; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 824; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -832,6 +835,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -880,6 +884,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -924,7 +930,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -1427,6 +1433,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -1474,6 +1481,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 764; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 788; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -1517,7 +1526,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 756; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 792; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -2016,6 +2025,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -2064,6 +2074,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -2108,7 +2120,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -2613,6 +2625,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -2661,6 +2674,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -2705,7 +2720,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -3209,6 +3224,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -3257,6 +3273,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -3301,7 +3319,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -3805,6 +3823,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -3852,6 +3871,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 836; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 860; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -3895,7 +3916,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 828; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 860; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 864; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -4399,6 +4420,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -4447,6 +4469,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1648; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1688; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -4491,7 +4515,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1632; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1688; + 1696; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -4991,6 +5015,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -5038,6 +5063,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 796; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 820; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -5081,7 +5108,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 788; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 824; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -5577,6 +5604,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -5625,6 +5653,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -5669,7 +5699,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -6166,6 +6196,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -6213,6 +6244,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 764; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 788; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -6256,7 +6289,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 756; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 792; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -6749,6 +6782,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -6797,6 +6831,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -6841,7 +6877,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -7340,6 +7376,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -7388,6 +7425,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -7432,7 +7471,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -7930,6 +7969,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -7978,6 +8018,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -8022,7 +8064,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -8520,6 +8562,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word String_hash_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; @@ -8567,6 +8610,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 836; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 860; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 224; @@ -8610,7 +8655,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 828; static constexpr dart::compiler::target::word Thread_isolate_offset = 40; -static constexpr dart::compiler::target::word Thread_isolate_group_offset = 860; +static constexpr dart::compiler::target::word Thread_isolate_group_offset = 864; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -9108,6 +9153,7 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word String_hash_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; @@ -9156,6 +9202,8 @@ static constexpr dart::compiler::target::word Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word Thread_double_truncate_round_supported_offset = 1648; +static constexpr dart::compiler::target::word + Thread_service_extension_stream_offset = 1688; static constexpr dart::compiler::target::word Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424; @@ -9200,7 +9248,7 @@ static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset = 1632; static constexpr dart::compiler::target::word Thread_isolate_offset = 80; static constexpr dart::compiler::target::word Thread_isolate_group_offset = - 1688; + 1696; static constexpr dart::compiler::target::word Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -9735,6 +9783,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word AOT_String_hash_offset = 8; static constexpr dart::compiler::target::word AOT_String_length_offset = 4; static constexpr dart::compiler::target::word @@ -9786,6 +9835,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 796; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 820; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -9831,7 +9882,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 788; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 820; + 824; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -10401,6 +10452,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -10452,6 +10504,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -10497,7 +10551,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -11073,6 +11127,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -11124,6 +11179,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -11169,7 +11226,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -11742,6 +11799,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -11793,6 +11851,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -11838,7 +11898,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -12410,6 +12470,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -12461,6 +12522,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -12506,7 +12569,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -13079,6 +13142,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word AOT_String_hash_offset = 8; static constexpr dart::compiler::target::word AOT_String_length_offset = 4; static constexpr dart::compiler::target::word @@ -13130,6 +13194,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 836; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 860; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -13175,7 +13241,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 828; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 860; + 864; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -13747,6 +13813,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -13798,6 +13865,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1648; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1688; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -13843,7 +13912,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1688; + 1696; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -14411,6 +14480,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word AOT_String_hash_offset = 8; static constexpr dart::compiler::target::word AOT_String_length_offset = 4; static constexpr dart::compiler::target::word @@ -14462,6 +14532,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 796; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 820; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -14507,7 +14579,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 788; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 820; + 824; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -15070,6 +15142,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -15121,6 +15194,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -15166,7 +15241,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -15735,6 +15810,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -15786,6 +15862,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -15831,7 +15909,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -16397,6 +16475,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -16448,6 +16527,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1592; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -16493,7 +16574,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1576; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1632; + 1640; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -17058,6 +17139,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -17109,6 +17191,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1656; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1696; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -17154,7 +17238,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1640; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1696; + 1704; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word @@ -17720,6 +17804,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 8; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 4; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 4; static constexpr dart::compiler::target::word AOT_String_hash_offset = 8; static constexpr dart::compiler::target::word AOT_String_length_offset = 4; static constexpr dart::compiler::target::word @@ -17771,6 +17856,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 44; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 836; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 860; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 312; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -17816,7 +17903,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 828; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 860; + 864; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 64; static constexpr dart::compiler::target::word @@ -18381,6 +18468,7 @@ static constexpr dart::compiler::target::word AOT_StoreBufferBlock_pointers_offset = 16; static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset = 8; +static constexpr dart::compiler::target::word AOT_StreamInfo_enabled_offset = 8; static constexpr dart::compiler::target::word AOT_String_hash_offset = 4; static constexpr dart::compiler::target::word AOT_String_length_offset = 8; static constexpr dart::compiler::target::word @@ -18432,6 +18520,8 @@ static constexpr dart::compiler::target::word AOT_Thread_dispatch_table_array_offset = 88; static constexpr dart::compiler::target::word AOT_Thread_double_truncate_round_supported_offset = 1648; +static constexpr dart::compiler::target::word + AOT_Thread_service_extension_stream_offset = 1688; static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset = 600; static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset = @@ -18477,7 +18567,7 @@ static constexpr dart::compiler::target::word AOT_Thread_exit_through_ffi_offset = 1632; static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80; static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset = - 1688; + 1696; static constexpr dart::compiler::target::word AOT_Thread_field_table_values_offset = 128; static constexpr dart::compiler::target::word diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h index 1e03be5f276..65982cf1f2c 100644 --- a/runtime/vm/compiler/runtime_offsets_list.h +++ b/runtime/vm/compiler/runtime_offsets_list.h @@ -186,6 +186,7 @@ FIELD(SingleTargetCache, upper_limit_offset) \ FIELD(StoreBufferBlock, pointers_offset) \ FIELD(StoreBufferBlock, top_offset) \ + FIELD(StreamInfo, enabled_offset) \ FIELD(String, hash_offset) \ FIELD(String, length_offset) \ FIELD(SubtypeTestCache, cache_offset) \ @@ -213,6 +214,7 @@ FIELD(Thread, dart_stream_offset) \ FIELD(Thread, dispatch_table_array_offset) \ FIELD(Thread, double_truncate_round_supported_offset) \ + FIELD(Thread, service_extension_stream_offset) \ FIELD(Thread, optimize_entry_offset) \ FIELD(Thread, optimize_stub_offset) \ FIELD(Thread, deoptimize_entry_offset) \ diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 9162e8b0e75..1ae59b4e438 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -6,6 +6,7 @@ #include +#include "compiler/method_recognizer.h" #include "include/dart_api.h" #include "lib/stacktrace.h" #include "platform/assert.h" @@ -8097,31 +8098,66 @@ void Function::SetIsOptimizable(bool value) const { } bool Function::ForceOptimize() const { - return IsFfiFromAddress() || IsFfiGetAddress() || IsFfiLoad() || - IsFfiStore() || IsFfiTrampoline() || IsFfiAsExternalTypedData() || - IsTypedDataViewFactory() || IsUtf8Scan() || IsGetNativeField() || - IsFinalizerForceOptimized(); + return RecognizedKindForceOptimize() || IsFfiTrampoline() || + IsTypedDataViewFactory(); } -bool Function::IsFinalizerForceOptimized() const { - // Either because of unboxed/untagged data, or because we don't want the GC - // to trigger in between. +bool Function::RecognizedKindForceOptimize() const { switch (recognized_kind()) { + // Uses unboxed/untagged data not supported in unoptimized. case MethodRecognizer::kFinalizerBase_getIsolateFinalizers: case MethodRecognizer::kFinalizerBase_setIsolate: case MethodRecognizer::kFinalizerBase_setIsolateFinalizers: case MethodRecognizer::kFinalizerEntry_getExternalSize: - // Unboxed/untagged representation not supported in unoptimized. - return true; + case MethodRecognizer::kExtensionStreamHasListener: + case MethodRecognizer::kFfiLoadInt8: + case MethodRecognizer::kFfiLoadInt16: + case MethodRecognizer::kFfiLoadInt32: + case MethodRecognizer::kFfiLoadInt64: + case MethodRecognizer::kFfiLoadUint8: + case MethodRecognizer::kFfiLoadUint16: + case MethodRecognizer::kFfiLoadUint32: + case MethodRecognizer::kFfiLoadUint64: + case MethodRecognizer::kFfiLoadFloat: + case MethodRecognizer::kFfiLoadFloatUnaligned: + case MethodRecognizer::kFfiLoadDouble: + case MethodRecognizer::kFfiLoadDoubleUnaligned: + case MethodRecognizer::kFfiLoadPointer: + case MethodRecognizer::kFfiStoreInt8: + case MethodRecognizer::kFfiStoreInt16: + case MethodRecognizer::kFfiStoreInt32: + case MethodRecognizer::kFfiStoreInt64: + case MethodRecognizer::kFfiStoreUint8: + case MethodRecognizer::kFfiStoreUint16: + case MethodRecognizer::kFfiStoreUint32: + case MethodRecognizer::kFfiStoreUint64: + case MethodRecognizer::kFfiStoreFloat: + case MethodRecognizer::kFfiStoreFloatUnaligned: + case MethodRecognizer::kFfiStoreDouble: + case MethodRecognizer::kFfiStoreDoubleUnaligned: + case MethodRecognizer::kFfiStorePointer: + case MethodRecognizer::kFfiFromAddress: + case MethodRecognizer::kFfiGetAddress: + case MethodRecognizer::kFfiAsExternalTypedDataInt8: + case MethodRecognizer::kFfiAsExternalTypedDataInt16: + case MethodRecognizer::kFfiAsExternalTypedDataInt32: + case MethodRecognizer::kFfiAsExternalTypedDataInt64: + case MethodRecognizer::kFfiAsExternalTypedDataUint8: + case MethodRecognizer::kFfiAsExternalTypedDataUint16: + case MethodRecognizer::kFfiAsExternalTypedDataUint32: + case MethodRecognizer::kFfiAsExternalTypedDataUint64: + case MethodRecognizer::kFfiAsExternalTypedDataFloat: + case MethodRecognizer::kFfiAsExternalTypedDataDouble: + case MethodRecognizer::kGetNativeField: + case MethodRecognizer::kUtf8DecoderScan: + // Prevent the GC from running so that the operation is atomic from + // a GC point of view. Always double check implementation in + // kernel_to_il.cc that no GC can happen in between the relevant IL + // instructions. + // TODO(https://dartbug.com/48527): Support inlining. case MethodRecognizer::kFinalizerBase_exchangeEntriesCollectedWithNull: - // Prevent the GC from running so that the operation is atomic from - // a GC point of view. Always double check implementation in - // kernel_to_il.cc that no GC can happen in between the relevant IL - // instructions. - // TODO(https://dartbug.com/48527): Support inlining. - return true; + // Both unboxed/untagged data and atomic-to-GC operation. case MethodRecognizer::kFinalizerEntry_allocate: - // Both of the above reasons. return true; default: return false; @@ -14538,6 +14574,7 @@ void Library::CheckFunctionFingerprints() { all_libs.Add(&Library::ZoneHandle(Library::InternalLibrary())); all_libs.Add(&Library::ZoneHandle(Library::FfiLibrary())); all_libs.Add(&Library::ZoneHandle(Library::NativeWrappersLibrary())); + all_libs.Add(&Library::ZoneHandle(Library::DeveloperLibrary())); INTERNAL_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS_ASM_INTRINSIC); OTHER_RECOGNIZED_LIST(CHECK_FINGERPRINTS_OTHER); POLYMORPHIC_TARGET_LIST(CHECK_FINGERPRINTS); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 7d9ffe061d3..3bd1912e2b2 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -3240,7 +3240,8 @@ class Function : public Object { // run. bool ForceOptimize() const; - bool IsFinalizerForceOptimized() const; + // Whether this function's |recognized_kind| requires optimization. + bool RecognizedKindForceOptimize() const; bool CanBeInlined() const; @@ -3549,44 +3550,6 @@ class Function : public Object { UntaggedFunction::kFfiTrampoline; } - bool IsFfiLoad() const { - const auto kind = recognized_kind(); - return MethodRecognizer::kFfiLoadInt8 <= kind && - kind <= MethodRecognizer::kFfiLoadPointer; - } - - bool IsFfiStore() const { - const auto kind = recognized_kind(); - return MethodRecognizer::kFfiStoreInt8 <= kind && - kind <= MethodRecognizer::kFfiStorePointer; - } - - bool IsFfiFromAddress() const { - const auto kind = recognized_kind(); - return kind == MethodRecognizer::kFfiFromAddress; - } - - bool IsFfiGetAddress() const { - const auto kind = recognized_kind(); - return kind == MethodRecognizer::kFfiGetAddress; - } - - bool IsFfiAsExternalTypedData() const { - const auto kind = recognized_kind(); - return MethodRecognizer::kFfiAsExternalTypedDataInt8 <= kind && - kind <= MethodRecognizer::kFfiAsExternalTypedDataDouble; - } - - bool IsGetNativeField() const { - const auto kind = recognized_kind(); - return kind == MethodRecognizer::kGetNativeField; - } - - bool IsUtf8Scan() const { - const auto kind = recognized_kind(); - return kind == MethodRecognizer::kUtf8DecoderScan; - } - // Recognise async functions like: // user_func async { // // ... diff --git a/runtime/vm/service.h b/runtime/vm/service.h index 6bf1e40ccbc..7dc4d4569b1 100644 --- a/runtime/vm/service.h +++ b/runtime/vm/service.h @@ -5,6 +5,8 @@ #ifndef RUNTIME_VM_SERVICE_H_ #define RUNTIME_VM_SERVICE_H_ +#include + #include "include/dart_tools_api.h" #include "vm/allocation.h" @@ -73,17 +75,20 @@ class StreamInfo { const char* id() const { return id_; } - void set_enabled(bool value) { enabled_ = value; } - bool enabled() const { return enabled_; } + void set_enabled(bool value) { enabled_ = value ? 1 : 0; } + bool enabled() const { return !!enabled_; } void set_include_private_members(bool value) { include_private_members_ = value; } bool include_private_members() const { return include_private_members_; } + // This may get access by multiple threads, but relaxed access is ok. + static intptr_t enabled_offset() { return OFFSET_OF(StreamInfo, enabled_); } + private: const char* id_; - bool enabled_; + std::atomic enabled_; bool include_private_members_; }; diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index e8ad780c06d..573e775d5a4 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -19,6 +19,7 @@ #include "vm/os_thread.h" #include "vm/profiler.h" #include "vm/runtime_entry.h" +#include "vm/service.h" #include "vm/stub_code.h" #include "vm/symbols.h" #include "vm/thread_interrupter.h" @@ -39,15 +40,15 @@ DECLARE_FLAG(bool, trace_service_verbose); Thread::~Thread() { // We should cleanly exit any isolate before destruction. - ASSERT(isolate_ == NULL); - ASSERT(store_buffer_block_ == NULL); - ASSERT(marking_stack_block_ == NULL); + ASSERT(isolate_ == nullptr); + ASSERT(store_buffer_block_ == nullptr); + ASSERT(marking_stack_block_ == nullptr); // There should be no top api scopes at this point. - ASSERT(api_top_scope() == NULL); + ASSERT(api_top_scope() == nullptr); // Delete the resusable api scope if there is one. if (api_reusable_scope_ != nullptr) { delete api_reusable_scope_; - api_reusable_scope_ = NULL; + api_reusable_scope_ = nullptr; } DO_IF_TSAN(delete tsan_utils_); @@ -60,21 +61,21 @@ Thread::~Thread() { #define REUSABLE_HANDLE_SCOPE_INIT(object) #endif // defined(DEBUG) -#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(NULL), +#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(nullptr), Thread::Thread(bool is_vm_isolate) : ThreadState(false), stack_limit_(0), write_barrier_mask_(UntaggedObject::kGenerationalBarrierMask), heap_base_(0), - isolate_(NULL), - dispatch_table_array_(NULL), + isolate_(nullptr), + dispatch_table_array_(nullptr), saved_stack_limit_(0), stack_overflow_flags_(0), - heap_(NULL), + heap_(nullptr), top_exit_frame_info_(0), - store_buffer_block_(NULL), - marking_stack_block_(NULL), + store_buffer_block_(nullptr), + marking_stack_block_(nullptr), vm_tag_(0), unboxed_int64_runtime_arg_(0), unboxed_double_runtime_arg_(0.0), @@ -86,32 +87,37 @@ Thread::Thread(bool is_vm_isolate) safepoint_state_(0), ffi_callback_code_(GrowableObjectArray::null()), ffi_callback_stack_return_(TypedData::null()), - api_top_scope_(NULL), + api_top_scope_(nullptr), double_truncate_round_supported_( TargetCPUFeatures::double_truncate_round_supported() ? 1 : 0), tsan_utils_(DO_IF_TSAN(new TsanUtils()) DO_IF_NOT_TSAN(nullptr)), task_kind_(kUnknownTask), - dart_stream_(NULL), + dart_stream_(nullptr), + service_extension_stream_(nullptr), thread_lock_(), - api_reusable_scope_(NULL), + api_reusable_scope_(nullptr), no_callback_scope_depth_(0), #if defined(DEBUG) no_safepoint_scope_depth_(0), #endif reusable_handles_(), stack_overflow_count_(0), - hierarchy_info_(NULL), - type_usage_info_(NULL), + hierarchy_info_(nullptr), + type_usage_info_(nullptr), sticky_error_(Error::null()), REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) #if defined(USING_SAFE_STACK) saved_safestack_limit_(0), #endif - next_(NULL) { + next_(nullptr) { #if defined(SUPPORT_TIMELINE) dart_stream_ = Timeline::GetDartStream(); - ASSERT(dart_stream_ != NULL); + ASSERT(dart_stream_ != nullptr); +#endif +#ifndef PRODUCT + service_extension_stream_ = &Service::extension_stream; + ASSERT(service_extension_stream_ != nullptr); #endif #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ member_name = default_init_value; @@ -276,8 +282,8 @@ bool Thread::EnterIsolate(Isolate* isolate, bool is_nested_reenter) { Thread* thread = isolate->ScheduleThread(kIsMutatorThread, is_nested_reenter, kBypassSafepoint); - if (thread != NULL) { - ASSERT(thread->store_buffer_block_ == NULL); + if (thread != nullptr) { + ASSERT(thread->store_buffer_block_ == nullptr); ASSERT(thread->isolate() == isolate); ASSERT(thread->isolate_group() == isolate->group()); thread->FinishEntering(kMutatorTask); @@ -316,7 +322,7 @@ bool Thread::EnterIsolateAsHelper(Isolate* isolate, const bool kIsNestedReenter = false; Thread* thread = isolate->ScheduleThread(kIsMutatorThread, kIsNestedReenter, bypass_safepoint); - if (thread != NULL) { + if (thread != nullptr) { ASSERT(!thread->IsMutatorThread()); ASSERT(thread->isolate() == isolate); ASSERT(thread->isolate_group() == isolate->group()); @@ -336,7 +342,7 @@ void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { thread->PrepareLeaving(); Isolate* isolate = thread->isolate(); - ASSERT(isolate != NULL); + ASSERT(isolate != nullptr); const bool kIsMutatorThread = false; const bool kIsNestedExit = false; isolate->UnscheduleThread(thread, kIsMutatorThread, kIsNestedExit, @@ -348,7 +354,7 @@ bool Thread::EnterIsolateGroupAsHelper(IsolateGroup* isolate_group, bool bypass_safepoint) { ASSERT(kind != kMutatorTask); Thread* thread = isolate_group->ScheduleThread(bypass_safepoint); - if (thread != NULL) { + if (thread != nullptr) { ASSERT(!thread->IsMutatorThread()); ASSERT(thread->isolate() == nullptr); ASSERT(thread->isolate_group() == isolate_group); @@ -375,7 +381,7 @@ void Thread::ExitIsolateGroupAsHelper(bool bypass_safepoint) { void Thread::ReleaseStoreBuffer() { ASSERT(IsAtSafepoint()); // Prevent scheduling another GC by ignoring the threshold. - ASSERT(store_buffer_block_ != NULL); + ASSERT(store_buffer_block_ != nullptr); StoreBufferRelease(StoreBuffer::kIgnoreThreshold); // Make sure to get an *empty* block; the isolate needs all entries // at GC time. @@ -502,7 +508,7 @@ void Thread::StoreBufferAddObjectGC(ObjectPtr obj) { void Thread::StoreBufferRelease(StoreBuffer::ThresholdPolicy policy) { StoreBufferBlock* block = store_buffer_block_; - store_buffer_block_ = NULL; + store_buffer_block_ = nullptr; isolate_group()->store_buffer()->PushBlock(block, policy); } @@ -536,7 +542,7 @@ void Thread::DeferredMarkingStackAddObject(ObjectPtr obj) { void Thread::MarkingStackRelease() { MarkingStackBlock* block = marking_stack_block_; - marking_stack_block_ = NULL; + marking_stack_block_ = nullptr; write_barrier_mask_ = UntaggedObject::kGenerationalBarrierMask; isolate_group()->marking_stack()->PushBlock(block); } @@ -549,7 +555,7 @@ void Thread::MarkingStackAcquire() { void Thread::DeferredMarkingStackRelease() { MarkingStackBlock* block = deferred_marking_stack_block_; - deferred_marking_stack_block_ = NULL; + deferred_marking_stack_block_ = nullptr; isolate_group()->deferred_marking_stack()->PushBlock(block); } @@ -591,9 +597,9 @@ void Thread::ClearReusableHandles() { void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor, ValidationPolicy validation_policy) { - ASSERT(visitor != NULL); + ASSERT(visitor != nullptr); - if (zone() != NULL) { + if (zone() != nullptr) { zone()->VisitObjectPointers(visitor); } @@ -610,7 +616,7 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor, // Visit the api local scope as it has all the api local handles. ApiLocalScope* scope = api_top_scope_; - while (scope != NULL) { + while (scope != nullptr) { scope->local_handles()->VisitObjectPointers(visitor); scope = scope->previous(); } @@ -634,7 +640,7 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor, StackFrameIterator frames_iterator(top_exit_frame_info(), validation_policy, this, cross_thread_policy); StackFrame* frame = frames_iterator.NextFrame(); - while (frame != NULL) { + while (frame != nullptr) { frame->VisitObjectPointers(visitor); frame = frames_iterator.NextFrame(); } @@ -735,7 +741,7 @@ void Thread::RestoreWriteBarrierInvariant(RestoreWriteBarrierInvariantOp op) { RestoreWriteBarrierInvariantVisitor visitor(isolate_group(), this, op); ObjectStore* object_store = isolate_group()->object_store(); bool scan_next_dart_frame = false; - for (StackFrame* frame = frames_iterator.NextFrame(); frame != NULL; + for (StackFrame* frame = frames_iterator.NextFrame(); frame != nullptr; frame = frames_iterator.NextFrame()) { if (frame->IsExitFrame()) { scan_next_dart_frame = true; @@ -891,7 +897,7 @@ bool Thread::IsValidHandle(Dart_Handle object) const { bool Thread::IsValidLocalHandle(Dart_Handle object) const { ApiLocalScope* scope = api_top_scope_; - while (scope != NULL) { + while (scope != nullptr) { if (scope->local_handles()->IsValidHandle(object)) { return true; } @@ -903,7 +909,7 @@ bool Thread::IsValidLocalHandle(Dart_Handle object) const { intptr_t Thread::CountLocalHandles() const { intptr_t total = 0; ApiLocalScope* scope = api_top_scope_; - while (scope != NULL) { + while (scope != nullptr) { total += scope->local_handles()->CountHandles(); scope = scope->previous(); } @@ -913,7 +919,7 @@ intptr_t Thread::CountLocalHandles() const { int Thread::ZoneSizeInBytes() const { int total = 0; ApiLocalScope* scope = api_top_scope_; - while (scope != NULL) { + while (scope != nullptr) { total += scope->zone()->SizeInBytes(); scope = scope->previous(); } @@ -923,12 +929,12 @@ int Thread::ZoneSizeInBytes() const { void Thread::EnterApiScope() { ASSERT(MayAllocateHandles()); ApiLocalScope* new_scope = api_reusable_scope(); - if (new_scope == NULL) { + if (new_scope == nullptr) { new_scope = new ApiLocalScope(api_top_scope(), top_exit_frame_info()); - ASSERT(new_scope != NULL); + ASSERT(new_scope != nullptr); } else { new_scope->Reinit(this, api_top_scope(), top_exit_frame_info()); - set_api_reusable_scope(NULL); + set_api_reusable_scope(nullptr); } set_api_top_scope(new_scope); // New scope is now the top scope. } @@ -938,7 +944,7 @@ void Thread::ExitApiScope() { ApiLocalScope* scope = api_top_scope(); ApiLocalScope* reusable_scope = api_reusable_scope(); set_api_top_scope(scope->previous()); // Reset top scope to previous. - if (reusable_scope == NULL) { + if (reusable_scope == nullptr) { scope->Reset(this); // Reset the old scope which we just exited. set_api_reusable_scope(scope); } else { @@ -951,7 +957,7 @@ void Thread::UnwindScopes(uword stack_marker) { // Unwind all scopes using the same stack_marker, i.e. all scopes allocated // under the same top_exit_frame_info. ApiLocalScope* scope = api_top_scope_; - while (scope != NULL && scope->stack_marker() != 0 && + while (scope != nullptr && scope->stack_marker() != 0 && scope->stack_marker() == stack_marker) { api_top_scope_ = scope->previous(); delete scope; @@ -975,7 +981,7 @@ void Thread::FinishEntering(TaskKind kind) { ASSERT(store_buffer_block_ == nullptr); task_kind_ = kind; - if (isolate_group()->marking_stack() != NULL) { + if (isolate_group()->marking_stack() != nullptr) { // Concurrent mark in progress. Enable barrier for this thread. MarkingStackAcquire(); DeferredMarkingStackAcquire(); @@ -1004,17 +1010,17 @@ void Thread::PrepareLeaving() { DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) : StackResource(thread) { - if (thread != NULL) { + if (thread != nullptr) { OSThread* os_thread = thread->os_thread(); - ASSERT(os_thread != NULL); + ASSERT(os_thread != nullptr); os_thread->DisableThreadInterrupts(); } } DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { - if (thread() != NULL) { + if (thread() != nullptr) { OSThread* os_thread = thread()->os_thread(); - ASSERT(os_thread != NULL); + ASSERT(os_thread != nullptr); os_thread->EnableThreadInterrupts(); } } diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h index 15a7bd926b7..5918a360afb 100644 --- a/runtime/vm/thread.h +++ b/runtime/vm/thread.h @@ -58,6 +58,7 @@ class RuntimeEntry; class Smi; class StackResource; class StackTrace; +class StreamInfo; class String; class TimelineStream; class TypeArguments; @@ -512,6 +513,11 @@ class Thread : public ThreadState { return OFFSET_OF(Thread, dart_stream_); } + // Offset of the Dart VM Service Extension StreamInfo object. + static intptr_t service_extension_stream_offset() { + return OFFSET_OF(Thread, service_extension_stream_); + } + // Is |this| executing Dart code? bool IsExecutingDartCode() const; @@ -1173,6 +1179,7 @@ class Thread : public ThreadState { TaskKind task_kind_; TimelineStream* dart_stream_; + StreamInfo* service_extension_stream_; IsolateGroup* isolate_group_ = nullptr; mutable Monitor thread_lock_; ApiLocalScope* api_reusable_scope_; diff --git a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart index 761bf6e7eff..c451d7fc366 100644 --- a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart +++ b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart @@ -11,7 +11,6 @@ import 'dart:async'; import 'dart:convert' show json; import 'dart:isolate'; -var _issuedPostEventWarning = false; var _issuedRegisterExtensionWarning = false; final _developerSupportWarning = 'from dart:developer is only supported in ' 'build/run/test environments where the developer event method hooks have ' @@ -116,16 +115,11 @@ _invokeExtension(String methodName, String encodedJson) { }); } +@patch +bool get extensionStreamHasListener => _debuggerAttached; + @patch void _postEvent(String eventKind, String eventData) { - if (!_debuggerAttached) { - if (!_issuedPostEventWarning) { - var message = 'postEvent() $_developerSupportWarning'; - JS('', 'console.warn(#)', message); - _issuedPostEventWarning = true; - } - return; - } // TODO(46377) Update this check when we have a documented API for DDC apps. if (JS('!', r'!!#.$emitDebugEvent', dart.global_)) { // See hooks assigned by package:dwds: diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart index feb0d485b37..54f7ca1b426 100644 --- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart @@ -47,6 +47,9 @@ _registerExtension(String method, ServiceExtensionHandler handler) { _extensions[method] = handler; } +@patch +bool get extensionStreamHasListener => false; + @patch void _postEvent(String eventKind, String eventData) { // TODO. diff --git a/sdk/lib/_internal/wasm/lib/developer.dart b/sdk/lib/_internal/wasm/lib/developer.dart index ba930b33edc..32d3050e6f3 100644 --- a/sdk/lib/_internal/wasm/lib/developer.dart +++ b/sdk/lib/_internal/wasm/lib/developer.dart @@ -26,6 +26,9 @@ void log(String message, Object? error, StackTrace? stackTrace}) {} +@patch +bool get extensionStreamHasListener => false; + @patch void _postEvent(String eventKind, String eventData) {} diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart index e9df841ba85..2d8e15cfcd3 100644 --- a/sdk/lib/developer/developer.dart +++ b/sdk/lib/developer/developer.dart @@ -15,6 +15,7 @@ /// {@category Core} library dart.developer; +import "dart:_internal" show checkNotNullable; import 'dart:async'; import 'dart:convert'; import 'dart:isolate' show Isolate, RawReceivePort, SendPort; diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart index 184a00f956b..aa106744ced 100644 --- a/sdk/lib/developer/extension.dart +++ b/sdk/lib/developer/extension.dart @@ -27,7 +27,7 @@ class ServiceExtensionResponse { errorCode = null, errorDetail = null { // TODO: When NNBD is complete, delete the following line. - ArgumentError.checkNotNull(result, "result"); + checkNotNullable(result, "result"); } /// Creates an error response to a service protocol extension RPC. @@ -42,7 +42,7 @@ class ServiceExtensionResponse { errorDetail = errorDetail { _validateErrorCode(errorCode); // TODO: When NNBD is complete, delete the following line. - ArgumentError.checkNotNull(errorDetail, "errorDetail"); + checkNotNullable(errorDetail, "errorDetail"); } /// Invalid method parameter(s) error code. @@ -83,7 +83,7 @@ class ServiceExtensionResponse { static _validateErrorCode(int errorCode) { // TODO: When NNBD is complete, delete the following line. - ArgumentError.checkNotNull(errorCode, "errorCode"); + checkNotNullable(errorCode, "errorCode"); if (errorCode == invalidParams) return; if ((errorCode >= extensionErrorMin) && (errorCode <= extensionErrorMax)) { return; @@ -129,7 +129,7 @@ typedef Future ServiceExtensionHandler( /// must always include an 'isolateId' parameter with each RPC. void registerExtension(String method, ServiceExtensionHandler handler) { // TODO: When NNBD is complete, delete the following line. - ArgumentError.checkNotNull(method, 'method'); + checkNotNullable(method, 'method'); if (!method.startsWith('ext.')) { throw new ArgumentError.value(method, 'method', 'Must begin with ext.'); } @@ -137,16 +137,38 @@ void registerExtension(String method, ServiceExtensionHandler handler) { throw new ArgumentError('Extension already registered: $method'); } // TODO: When NNBD is complete, delete the following line. - ArgumentError.checkNotNull(handler, 'handler'); + checkNotNullable(handler, 'handler'); _registerExtension(method, handler); } -/// Post an event of [eventKind] with payload of [eventData] to the `Extension` +/// Whether the "Extension" stream currently has at least one listener. +/// +/// A client of the VM service can register as a listener +/// on the extension stream using `listenStream` method. +/// The extension stream has a listener while at least one such +/// client has registered as a listener, and has not yet disconnected +/// again. +/// +/// Calling [postEvent] while the stream has listeners will attempt to +/// deliver that event to all current listeners, +/// although a listener can disconnect before the event is delivered. +/// Calling [postEvent] when the stream has no listener means that +/// no-one will receive the event, and the call is effectively a no-op. +@pragma("vm:recognized", "other") +@pragma("vm:prefer-inline") +external bool get extensionStreamHasListener; + +/// Post an event of [eventKind] with payload of [eventData] to the "Extension" /// event stream. +/// +/// If [extensionStreamHasListener] is false, this method is a no-op. void postEvent(String eventKind, Map eventData) { + if (!extensionStreamHasListener) { + return; + } // TODO: When NNBD is complete, delete the following two lines. - ArgumentError.checkNotNull(eventKind, 'eventKind'); - ArgumentError.checkNotNull(eventData, 'eventData'); + checkNotNullable(eventKind, 'eventKind'); + checkNotNullable(eventData, 'eventData'); String eventDataAsString = json.encode(eventData); _postEvent(eventKind, eventDataAsString); } diff --git a/tests/dartdevc/developer_events_test.dart b/tests/dartdevc/developer_events_test.dart index 907d801f993..22481f8f92b 100644 --- a/tests/dartdevc/developer_events_test.dart +++ b/tests/dartdevc/developer_events_test.dart @@ -122,17 +122,15 @@ void testWarningMessages() { var data0 = {'key0': 'value0'}; postEvent('kind0', data0); - // A warning message was issued about calling `postEvent()` from - // dart:developer. - expect(consoleWarnLog.single.contains('postEvent() from dart:developer'), - true); + // Nothing is listening, so this was a no-op. + expect(consoleWarnLog.isEmpty, true); postEvent('kind0', data0); var data1 = {'key1': 'value1'}; postEvent('kind1', data1); - // A warning is only issued on the first call of `postEvent()`. - expect(consoleWarnLog.length, 1); + // No warnings should be issued because postEvent is a no-op. + expect(consoleWarnLog.length, 0); consoleWarnLog.clear(); diff --git a/tests/dartdevc_2/developer_events_test.dart b/tests/dartdevc_2/developer_events_test.dart index 8bc5ed877ba..d1851215d44 100644 --- a/tests/dartdevc_2/developer_events_test.dart +++ b/tests/dartdevc_2/developer_events_test.dart @@ -122,17 +122,15 @@ void testWarningMessages() { var data0 = {'key0': 'value0'}; postEvent('kind0', data0); - // A warning message was issued about calling `postEvent()` from - // dart:developer. - expect(consoleWarnLog.single.contains('postEvent() from dart:developer'), - true); + // Nothing is listening, so this was a no-op. + expect(consoleWarnLog.isEmpty, true); postEvent('kind0', data0); var data1 = {'key1': 'value1'}; postEvent('kind1', data1); - // A warning is only issued on the first call of `postEvent()`. - expect(consoleWarnLog.length, 1); + // No warnings should be issued because postEvent is a no-op. + expect(consoleWarnLog.length, 0); consoleWarnLog.clear();