diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index ac1581a3e96..954d7e489e2 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -198,20 +198,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 45; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32; + Isolate_has_resumption_breakpoints_offset = 41; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 8; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 12; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 44; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 40; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 12; @@ -877,20 +877,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 89; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64; + Isolate_has_resumption_breakpoints_offset = 81; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 24; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 88; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 80; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 24; @@ -1561,20 +1561,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 45; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32; + Isolate_has_resumption_breakpoints_offset = 41; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 8; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 12; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 44; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 40; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 12; @@ -2240,20 +2240,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 89; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64; + Isolate_has_resumption_breakpoints_offset = 81; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 24; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 88; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 80; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 24; @@ -2925,20 +2925,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 89; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64; + Isolate_has_resumption_breakpoints_offset = 81; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 24; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 88; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 80; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 16; @@ -3610,20 +3610,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 89; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64; + Isolate_has_resumption_breakpoints_offset = 81; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 24; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 88; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 80; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 16; @@ -4296,20 +4296,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 45; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32; + Isolate_has_resumption_breakpoints_offset = 41; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 8; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 12; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 44; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 40; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 12; @@ -4977,20 +4977,20 @@ static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; static constexpr dart::compiler::target::word Int32x4_value_offset = 8; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56; -static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80; +static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; +static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72; static constexpr dart::compiler::target::word - Isolate_has_resumption_breakpoints_offset = 89; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64; + Isolate_has_resumption_breakpoints_offset = 81; +static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; static constexpr dart::compiler::target::word IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word IsolateGroup_class_table_offset = 16; static constexpr dart::compiler::target::word IsolateGroup_cached_class_table_table_offset = 24; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 88; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40; +static constexpr dart::compiler::target::word Isolate_single_step_offset = 80; +static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word ImmutableLinkedHashBase_data_offset = 24; @@ -11078,15 +11078,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 24; + 20; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 28; + 24; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 40; + 36; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 45; + AOT_Isolate_has_resumption_breakpoints_offset = 41; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 32; + 28; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 16; static constexpr dart::compiler::target::word @@ -11094,8 +11094,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 12; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 44; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 20; + 40; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 12; static constexpr dart::compiler::target::word @@ -11831,15 +11831,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 48; + 40; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 56; + 48; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 80; + 72; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 89; + AOT_Isolate_has_resumption_breakpoints_offset = 81; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 64; + 56; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word @@ -11847,8 +11847,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 24; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 88; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40; + 80; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word @@ -12591,15 +12591,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 48; + 40; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 56; + 48; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 80; + 72; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 89; + AOT_Isolate_has_resumption_breakpoints_offset = 81; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 64; + 56; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word @@ -12607,8 +12607,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 24; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 88; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40; + 80; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word @@ -13349,15 +13349,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 48; + 40; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 56; + 48; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 80; + 72; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 89; + AOT_Isolate_has_resumption_breakpoints_offset = 81; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 64; + 56; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word @@ -13365,8 +13365,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 24; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 88; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40; + 80; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 16; static constexpr dart::compiler::target::word @@ -14107,15 +14107,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 48; + 40; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 56; + 48; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 80; + 72; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 89; + AOT_Isolate_has_resumption_breakpoints_offset = 81; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 64; + 56; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word @@ -14123,8 +14123,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 24; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 88; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40; + 80; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 16; static constexpr dart::compiler::target::word @@ -14865,15 +14865,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 24; + 20; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 28; + 24; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 40; + 36; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 45; + AOT_Isolate_has_resumption_breakpoints_offset = 41; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 32; + 28; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 16; static constexpr dart::compiler::target::word @@ -14881,8 +14881,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 12; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 44; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 20; + 40; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 12; static constexpr dart::compiler::target::word @@ -15620,15 +15620,15 @@ static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset = - 48; + 40; static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset = - 56; + 48; static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset = - 80; + 72; static constexpr dart::compiler::target::word - AOT_Isolate_has_resumption_breakpoints_offset = 89; + AOT_Isolate_has_resumption_breakpoints_offset = 81; static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset = - 64; + 56; static constexpr dart::compiler::target::word AOT_IsolateGroup_object_store_offset = 32; static constexpr dart::compiler::target::word @@ -15636,8 +15636,8 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word AOT_IsolateGroup_cached_class_table_table_offset = 24; static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset = - 88; -static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40; + 80; +static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32; static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset = 24; static constexpr dart::compiler::target::word diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index c288aaef339..0ddd22d5225 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -2382,97 +2382,6 @@ void Isolate::Run() { reinterpret_cast(this)); } -#if !defined(PRODUCT) -void Isolate::set_current_sample_block(SampleBlock* current) { - ASSERT(current_sample_block_lock_.IsOwnedByCurrentThread()); - if (current != nullptr) { - current->set_is_allocation_block(false); - current->set_owner(this); - } - current_sample_block_ = current; -} - -void Isolate::set_current_allocation_sample_block(SampleBlock* current) { - if (current != nullptr) { - current->set_is_allocation_block(true); - current->set_owner(this); - } - current_allocation_sample_block_ = current; -} - -void Isolate::FreeSampleBlock(SampleBlock* block) { - if (block == nullptr) { - return; - } - SampleBlock* head; - // We're pushing the freed sample block to the front of the free_block_list_, - // which means the last element of the list will be the oldest freed sample. - do { - head = free_block_list_.load(std::memory_order_acquire); - block->next_free_ = head; - } while (!free_block_list_.compare_exchange_weak(head, block, - std::memory_order_release)); -} - -class StreamableSampleFilter : public SampleFilter { - public: - explicit StreamableSampleFilter(Dart_Port port) - : SampleFilter(port, kNoTaskFilter, -1, -1) {} - - bool FilterSample(Sample* sample) override { - const UserTag& tag = - UserTag::Handle(UserTag::FindTagById(sample->user_tag())); - return tag.streamable(); - } -}; - -void Isolate::ProcessFreeSampleBlocks(Thread* thread) { - SampleBlock* head = free_block_list_.exchange(nullptr); - if (head == nullptr) { - // No sample blocks to process. - return; - } - // Reverse the list before processing so older blocks are streamed and reused - // first. - SampleBlock* reversed_head = nullptr; - do { - SampleBlock* next = head->next_free_; - if (reversed_head == nullptr) { - reversed_head = head; - reversed_head->next_free_ = nullptr; - } else { - head->next_free_ = reversed_head; - reversed_head = head; - } - head = next; - } while (head != nullptr); - head = reversed_head; - if (Service::profiler_stream.enabled() && !IsSystemIsolate(this)) { - StackZone zone(thread); - SampleBlockListProcessor buffer(head); - if (buffer.HasStreamableSamples(thread)) { - HandleScope handle_scope(thread); - StreamableSampleFilter filter(main_port()); - Profile profile; - profile.Build(thread, &filter, &buffer); - ASSERT(profile.sample_count() > 0); - ServiceEvent event(this, ServiceEvent::kCpuSamples); - event.set_cpu_profile(&profile); - Service::HandleEvent(&event); - } - } - - do { - SampleBlock* next = head->next_free_; - head->next_free_ = nullptr; - head->evictable_ = true; - Profiler::sample_block_buffer()->FreeBlock(head); - head = next; - thread->CheckForSafepoint(); - } while (head != nullptr); -} -#endif // !defined(PRODUCT) - void Isolate::RunAndCleanupFinalizersOnShutdown() { if (finalizers_ == GrowableObjectArray::null()) return; @@ -2616,25 +2525,7 @@ void Isolate::Shutdown() { ServiceIsolate::SendIsolateShutdownMessage(); #if !defined(PRODUCT) debugger()->Shutdown(); - // Cleanup profiler state. - SampleBlock* cpu_block = current_sample_block(); - if (cpu_block != nullptr) { - cpu_block->release_block(); - } - SampleBlock* allocation_block = current_allocation_sample_block(); - if (allocation_block != nullptr) { - allocation_block->release_block(); - } - - // Process the previously assigned sample blocks if we're using the - // profiler's sample buffer. Some tests create their own SampleBlockBuffer - // and handle block processing themselves. - if ((cpu_block != nullptr || allocation_block != nullptr) && - Profiler::sample_block_buffer() != nullptr) { - StackZone zone(thread); - HandleScope handle_scope(thread); - Profiler::sample_block_buffer()->ProcessCompletedBlocks(); - } + Profiler::IsolateShutdown(thread); #endif } diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index ec73e874e57..08ffb1a70a0 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -1130,33 +1130,27 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { #if !defined(PRODUCT) Debugger* debugger() const { return debugger_; } - // NOTE: this lock should only be acquired within the profiler signal handler. - Mutex* current_sample_block_lock() const { - return const_cast(¤t_sample_block_lock_); - } - // Returns the current SampleBlock used to track CPU profiling samples. - // - // NOTE: current_sample_block_lock() should be held when accessing this - // block. SampleBlock* current_sample_block() const { return current_sample_block_; } - void set_current_sample_block(SampleBlock* current); - - void FreeSampleBlock(SampleBlock* block); - void ProcessFreeSampleBlocks(Thread* thread); - bool should_process_blocks() const { - return free_block_list_.load(std::memory_order_relaxed) != nullptr; + void set_current_sample_block(SampleBlock* block) { + current_sample_block_ = block; } - std::atomic free_block_list_ = nullptr; + void ProcessFreeSampleBlocks(Thread* thread); // Returns the current SampleBlock used to track Dart allocation samples. - // - // Allocations should only occur on the mutator thread for an isolate, so we - // don't need to worry about grabbing a lock while accessing this block. SampleBlock* current_allocation_sample_block() const { return current_allocation_sample_block_; } - void set_current_allocation_sample_block(SampleBlock* current); + void set_current_allocation_sample_block(SampleBlock* block) { + current_allocation_sample_block_ = block; + } + + bool TakeHasCompletedBlocks() { + return has_completed_blocks_.exchange(0) != 0; + } + bool TrySetHasCompletedBlocks() { + return has_completed_blocks_.exchange(1) == 0; + } void set_single_step(bool value) { single_step_ = value; } bool single_step() const { return single_step_; } @@ -1637,18 +1631,12 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { Debugger* debugger_ = nullptr; // SampleBlock containing CPU profiling samples. - // - // Can be accessed by multiple threads, so current_sample_block_lock_ should - // be acquired before accessing. - SampleBlock* current_sample_block_ = nullptr; - Mutex current_sample_block_lock_; + RelaxedAtomic current_sample_block_ = nullptr; // SampleBlock containing Dart allocation profiling samples. - // - // Allocations should only occur on the mutator thread for an isolate, so we - // shouldn't need to worry about grabbing a lock for the allocation sample - // block. - SampleBlock* current_allocation_sample_block_ = nullptr; + RelaxedAtomic current_allocation_sample_block_ = nullptr; + + RelaxedAtomic has_completed_blocks_ = {0}; int64_t last_resume_timestamp_; diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc index cba2e2f510e..c709cbc3592 100644 --- a/runtime/vm/os_thread.cc +++ b/runtime/vm/os_thread.cc @@ -21,6 +21,9 @@ Mutex* OSThread::thread_list_lock_ = NULL; bool OSThread::creation_enabled_ = false; thread_local ThreadState* OSThread::current_vm_thread_ = NULL; +#if defined(DEBUG) +thread_local bool ThreadInterruptScope::in_thread_interrupt_scope_ = false; +#endif #if defined(SUPPORT_TIMELINE) inline void UpdateTimelineTrackMetadata(const OSThread& thread) { diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h index ab2a6fa9c67..c934c7c7f1a 100644 --- a/runtime/vm/os_thread.h +++ b/runtime/vm/os_thread.h @@ -173,6 +173,11 @@ class OSThread : public BaseThread { static void SetCurrent(OSThread* current) { SetCurrentTLS(current); } static ThreadState* CurrentVMThread() { return current_vm_thread_; } +#if defined(DEBUG) + static void SetCurrentVMThread(ThreadState* thread) { + current_vm_thread_ = thread; + } +#endif // TODO(5411455): Use flag to override default value and Validate the // stack size by querying OS. @@ -382,6 +387,35 @@ inline bool Mutex::IsOwnedByCurrentThread() const { #endif } +// Mark when we are running in a signal handler (Linux, Android) or with a +// suspended thread (Windows, Mac, Fuchia). During this time, we cannot take +// locks, access Thread/Isolate::Current(), or use malloc. +class ThreadInterruptScope : public ValueObject { +#if defined(DEBUG) + public: + ThreadInterruptScope() { + ASSERT(!in_thread_interrupt_scope_); // We don't use nested signals. + in_thread_interrupt_scope_ = true; + + // Poison attempts to use Thread::Current. This is much cheaper than adding + // an assert in Thread::Current itself. + saved_current_vm_thread_ = OSThread::CurrentVMThread(); + OSThread::SetCurrentVMThread(reinterpret_cast(0xabababab)); + } + + ~ThreadInterruptScope() { + OSThread::SetCurrentVMThread(saved_current_vm_thread_); + in_thread_interrupt_scope_ = false; + } + + static bool in_thread_interrupt_scope() { return in_thread_interrupt_scope_; } + + private: + ThreadState* saved_current_vm_thread_; + static thread_local bool in_thread_interrupt_scope_; +#endif // DEBUG +}; + } // namespace dart #endif // RUNTIME_VM_OS_THREAD_H_ diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc index 2133ebf5288..48554ee9f4e 100644 --- a/runtime/vm/os_thread_android.cc +++ b/runtime/vm/os_thread_android.cc @@ -327,6 +327,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); // Specifically check for dead lock to help debugging. ASSERT(result != EDEADLK); @@ -338,6 +340,8 @@ void Mutex::Lock() { } bool Mutex::TryLock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -409,6 +413,8 @@ Monitor::~Monitor() { } bool Monitor::TryEnter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -424,6 +430,8 @@ bool Monitor::TryEnter() { } void Monitor::Enter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); VALIDATE_PTHREAD_RESULT(result); diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc index b6a17467c71..9c4c8c71a78 100644 --- a/runtime/vm/os_thread_fuchsia.cc +++ b/runtime/vm/os_thread_fuchsia.cc @@ -328,6 +328,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); // Specifically check for dead lock to help debugging. ASSERT(result != EDEADLK); @@ -339,6 +341,8 @@ void Mutex::Lock() { } bool Mutex::TryLock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -413,6 +417,8 @@ Monitor::~Monitor() { } bool Monitor::TryEnter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -428,6 +434,8 @@ bool Monitor::TryEnter() { } void Monitor::Enter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); VALIDATE_PTHREAD_RESULT(result); diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc index 038b79e6cfc..d3c49db675d 100644 --- a/runtime/vm/os_thread_linux.cc +++ b/runtime/vm/os_thread_linux.cc @@ -330,6 +330,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); // Specifically check for dead lock to help debugging. ASSERT(result != EDEADLK); @@ -341,6 +343,8 @@ void Mutex::Lock() { } bool Mutex::TryLock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -415,6 +419,8 @@ Monitor::~Monitor() { } bool Monitor::TryEnter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if (result == EBUSY) { @@ -430,6 +436,8 @@ bool Monitor::TryEnter() { } void Monitor::Enter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); VALIDATE_PTHREAD_RESULT(result); diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc index 3fba2cada34..bc2830a3543 100644 --- a/runtime/vm/os_thread_macos.cc +++ b/runtime/vm/os_thread_macos.cc @@ -298,6 +298,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); // Specifically check for dead lock to help debugging. ASSERT(result != EDEADLK); @@ -309,6 +311,8 @@ void Mutex::Lock() { } bool Mutex::TryLock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if ((result == EBUSY) || (result == EDEADLK)) { @@ -373,6 +377,8 @@ Monitor::~Monitor() { } bool Monitor::TryEnter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_trylock(data_.mutex()); // Return false if the lock is busy and locking failed. if ((result == EBUSY) || (result == EDEADLK)) { @@ -388,6 +394,8 @@ bool Monitor::TryEnter() { } void Monitor::Enter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + int result = pthread_mutex_lock(data_.mutex()); VALIDATE_PTHREAD_RESULT(result); diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc index 63b6a03fe32..62172bf3db4 100644 --- a/runtime/vm/os_thread_win.cc +++ b/runtime/vm/os_thread_win.cc @@ -247,6 +247,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + AcquireSRWLockExclusive(&data_.lock_); #if defined(DEBUG) // When running with assertions enabled we do track the owner. @@ -255,6 +257,8 @@ void Mutex::Lock() { } bool Mutex::TryLock() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) { #if defined(DEBUG) // When running with assertions enabled we do track the owner. @@ -291,6 +295,8 @@ Monitor::~Monitor() { } bool Monitor::TryEnter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + // Attempt to pass the semaphore but return immediately. if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) { #if defined(DEBUG) @@ -304,6 +310,8 @@ bool Monitor::TryEnter() { } void Monitor::Enter() { + DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope()); + AcquireSRWLockExclusive(&data_.lock_); #if defined(DEBUG) diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index 24fab64fae9..280a7a1f47e 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -2,11 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +#include "vm/profiler.h" + #include "platform/address_sanitizer.h" +#include "platform/atomic.h" #include "platform/memory_sanitizer.h" #include "platform/utils.h" - -#include "platform/atomic.h" #include "vm/allocation.h" #include "vm/code_patcher.h" #if !defined(DART_PRECOMPILED_RUNTIME) @@ -21,7 +22,6 @@ #include "vm/native_symbol.h" #include "vm/object.h" #include "vm/os.h" -#include "vm/profiler.h" #include "vm/profiler_service.h" #include "vm/reusable_handles.h" #include "vm/signal_handler.h" @@ -610,10 +610,7 @@ class SampleBlockCleanupVisitor : public IsolateVisitor { void VisitIsolate(Isolate* isolate) { isolate->set_current_allocation_sample_block(nullptr); - { - MutexLocker ml(isolate->current_sample_block_lock()); - isolate->set_current_sample_block(nullptr); - } + isolate->set_current_sample_block(nullptr); } }; @@ -700,8 +697,6 @@ SampleBlockBuffer::SampleBlockBuffer(intptr_t blocks, } capacity_ = blocks; cursor_ = 0; - free_list_head_ = nullptr; - free_list_tail_ = nullptr; } SampleBlockBuffer::~SampleBlockBuffer() { @@ -714,67 +709,34 @@ SampleBlockBuffer::~SampleBlockBuffer() { } SampleBlock* SampleBlockBuffer::ReserveSampleBlock() { - // Don't increment right away to avoid unlikely wrap-around errors. - if (cursor_.load() < capacity_) { - intptr_t index = cursor_.fetch_add(1u); - // Check the index again to make sure the last block hasn't been snatched - // from underneath us. - if (index < capacity_) { - return &blocks_[index]; + intptr_t capacity = capacity_; + intptr_t start = cursor_.fetch_add(1) % capacity; + intptr_t i = start; + do { + SampleBlock* block = &blocks_[i]; + if (block->TryAllocateFree()) { + return block; } - } - // Try to re-use a previously freed SampleBlock once we've handed out each - // block at least once. Freed blocks aren't cleared immediately and are still - // valid until they're re-allocated, similar to how a ring buffer would clear - // the oldest samples. - SampleBlock* block = GetFreeBlock(); - if (block != nullptr) { - block->Clear(); - } - return block; -} + i = (i + 1) % capacity; + } while (i != start); -void SampleBlockBuffer::ProcessCompletedBlocks() { - Thread* thread = Thread::Current(); - DisableThreadInterruptsScope dtis(thread); - int64_t start = Dart_TimelineGetMicros(); - thread->isolate()->ProcessFreeSampleBlocks(thread); - int64_t end = Dart_TimelineGetMicros(); - Dart_TimelineEvent("SampleBlockBuffer::ProcessCompletedBlocks", start, end, - Dart_Timeline_Event_Duration, 0, nullptr, nullptr); -} - -ProcessedSampleBuffer* SampleBlockListProcessor::BuildProcessedSampleBuffer( - SampleFilter* filter, - ProcessedSampleBuffer* buffer) { - Thread* thread = Thread::Current(); - Zone* zone = thread->zone(); - - if (buffer == nullptr) { - buffer = new (zone) ProcessedSampleBuffer(); - } - while (head_ != nullptr) { - head_->BuildProcessedSampleBuffer(filter, buffer); - head_ = head_->next_free_; - } - return buffer; -} - -bool SampleBlockListProcessor::HasStreamableSamples(Thread* thread) { - ReusableGrowableObjectArrayHandleScope reusable_array_handle_scope(thread); - Zone* zone = thread->zone(); - Isolate* isolate = thread->isolate(); - ASSERT(isolate->tag_table() != GrowableObjectArray::null()); - GrowableObjectArray& tag_table = reusable_array_handle_scope.Handle(); - tag_table ^= isolate->tag_table(); - UserTag& tag = UserTag::Handle(zone); - while (head_ != nullptr) { - if (head_->HasStreamableSamples(tag_table, &tag)) { - return true; + // No free blocks: try for completed block instead. + i = start; + do { + SampleBlock* block = &blocks_[i]; + if (block->TryAllocateCompleted()) { + return block; } - head_ = head_->next_free_; + i = (i + 1) % capacity; + } while (i != start); + + return nullptr; +} + +void SampleBlockBuffer::FreeCompletedBlocks() { + for (intptr_t i = 0; i < capacity_; i++) { + blocks_[i].FreeCompleted(); } - return false; } bool SampleBlock::HasStreamableSamples(const GrowableObjectArray& tag_table, @@ -792,6 +754,20 @@ bool SampleBlock::HasStreamableSamples(const GrowableObjectArray& tag_table, return false; } +static void FlushSampleBlocks(Isolate* isolate) { + SampleBlock* block = isolate->current_sample_block(); + if (block != nullptr) { + isolate->set_current_sample_block(nullptr); + block->MarkCompleted(); + } + + block = isolate->current_allocation_sample_block(); + if (block != nullptr) { + isolate->set_current_allocation_sample_block(nullptr); + block->MarkCompleted(); + } +} + ProcessedSampleBuffer* SampleBlockBuffer::BuildProcessedSampleBuffer( SampleFilter* filter, ProcessedSampleBuffer* buffer) { @@ -802,22 +778,29 @@ ProcessedSampleBuffer* SampleBlockBuffer::BuildProcessedSampleBuffer( buffer = new (zone) ProcessedSampleBuffer(); } + FlushSampleBlocks(thread->isolate()); + for (intptr_t i = 0; i < capacity_; ++i) { - (&blocks_[i])->BuildProcessedSampleBuffer(filter, buffer); + SampleBlock* block = &blocks_[i]; + if (block->TryAcquireStreaming(thread->isolate())) { + block->BuildProcessedSampleBuffer(filter, buffer); + if (filter->take_samples()) { + block->StreamingToFree(); + } else { + block->StreamingToCompleted(); + } + } } return buffer; } Sample* SampleBlock::ReserveSample() { - if (full_.load()) { - return nullptr; - } intptr_t slot = cursor_.fetch_add(1u); - if (slot + 1 == capacity_) { - full_ = true; + if (slot < capacity_) { + return At(slot); } - return (slot < capacity_) ? At(slot) : nullptr; + return nullptr; } Sample* SampleBlock::ReserveSampleAndLink(Sample* previous) { @@ -858,34 +841,27 @@ Sample* SampleBlockBuffer::ReserveSampleImpl(Isolate* isolate, if (sample != nullptr) { return sample; } - SampleBlock* next = nullptr; - if (allocation_sample) { - // We only need to be locked while accessing the CPU sample block since - // Dart allocations can only occur on the mutator thread. - next = ReserveSampleBlock(); - if (next == nullptr) { - // We're out of blocks to reserve. Drop the sample. - return nullptr; - } - isolate->set_current_allocation_sample_block(next); - isolate->FreeSampleBlock(block); - } else { - MutexLocker locker(isolate->current_sample_block_lock()); - next = ReserveSampleBlock(); - if (next == nullptr) { - // We're out of blocks to reserve. Drop the sample. - return nullptr; - } - isolate->set_current_sample_block(next); - isolate->FreeSampleBlock(block); - } - next->set_is_allocation_block(allocation_sample); - bool scheduled = can_process_block_.exchange(true); - if (!scheduled) { - isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt); + SampleBlock* next = ReserveSampleBlock(); + if (next == nullptr) { + // We're out of blocks to reserve. Drop the sample. + return nullptr; } - return ReserveSampleImpl(isolate, allocation_sample); + + next->set_owner(isolate); + if (allocation_sample) { + isolate->set_current_allocation_sample_block(next); + } else { + isolate->set_current_sample_block(next); + } + if (block != nullptr) { + block->MarkCompleted(); + if (!Isolate::IsSystemIsolate(isolate) && + isolate->TrySetHasCompletedBlocks()) { + isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt); + } + } + return next->ReserveSample(); } AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity) { @@ -2015,22 +1991,51 @@ void SampleBlockProcessor::Cleanup() { ASSERT(!thread_running_); } +class StreamableSampleFilter : public SampleFilter { + public: + explicit StreamableSampleFilter(Dart_Port port) + : SampleFilter(port, kNoTaskFilter, -1, -1, true) {} + + bool FilterSample(Sample* sample) override { + const UserTag& tag = + UserTag::Handle(UserTag::FindTagById(sample->user_tag())); + return tag.streamable(); + } +}; + +void Profiler::ProcessCompletedBlocks(Thread* thread) { + if (!Service::profiler_stream.enabled()) return; + Isolate* isolate = thread->isolate(); + if (Isolate::IsSystemIsolate(isolate)) return; + + TIMELINE_DURATION(thread, Isolate, "Profiler::ProcessCompletedBlocks") + DisableThreadInterruptsScope dtis(thread); + StackZone zone(thread); + HandleScope handle_scope(thread); + StreamableSampleFilter filter(isolate->main_port()); + Profile profile; + profile.Build(thread, &filter, Profiler::sample_block_buffer()); + ServiceEvent event(isolate, ServiceEvent::kCpuSamples); + event.set_cpu_profile(&profile); + Service::HandleEvent(&event); +} + +void Profiler::IsolateShutdown(Thread* thread) { + FlushSampleBlocks(thread->isolate()); + ProcessCompletedBlocks(thread); +} + class SampleBlockProcessorVisitor : public IsolateVisitor { public: SampleBlockProcessorVisitor() = default; virtual ~SampleBlockProcessorVisitor() = default; void VisitIsolate(Isolate* isolate) { - if (!isolate->should_process_blocks()) { - return; + if (isolate->TakeHasCompletedBlocks()) { + Thread::EnterIsolateAsHelper(isolate, Thread::kSampleBlockTask); + Profiler::ProcessCompletedBlocks(Thread::Current()); + Thread::ExitIsolateAsHelper(); } - Thread::EnterIsolateAsHelper(isolate, Thread::kSampleBlockTask); - Thread* thread = Thread::Current(); - { - DisableThreadInterruptsScope dtis(thread); - isolate->ProcessFreeSampleBlocks(thread); - } - Thread::ExitIsolateAsHelper(); } }; diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h index dc7e10ba2c9..cab583a7f06 100644 --- a/runtime/vm/profiler.h +++ b/runtime/vm/profiler.h @@ -93,8 +93,8 @@ class Profiler : public AllStatic { // SampleThread is called from inside the signal handler and hence it is very // critical that the implementation of SampleThread does not do any of the // following: - // * Accessing TLS -- Because on Windows and Fuchsia the callback will be - // running in a different thread. + // * Accessing TLS -- Because on Fuchsia, Mac and Windows the callback will + // be running in a different thread. // * Allocating memory -- Because this takes locks which may already be // held, resulting in a dead lock. // * Taking a lock -- See above. @@ -106,6 +106,9 @@ class Profiler : public AllStatic { } inline static intptr_t Size(); + static void ProcessCompletedBlocks(Thread* thread); + static void IsolateShutdown(Thread* thread); + private: static void DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash); @@ -157,11 +160,13 @@ class SampleFilter : public ValueObject { SampleFilter(Dart_Port port, intptr_t thread_task_mask, int64_t time_origin_micros, - int64_t time_extent_micros) + int64_t time_extent_micros, + bool take_samples = false) : port_(port), thread_task_mask_(thread_task_mask), time_origin_micros_(time_origin_micros), - time_extent_micros_(time_extent_micros) { + time_extent_micros_(time_extent_micros), + take_samples_(take_samples) { ASSERT(thread_task_mask != 0); ASSERT(time_origin_micros_ >= -1); ASSERT(time_extent_micros_ >= -1); @@ -180,6 +185,8 @@ class SampleFilter : public ValueObject { // Returns |true| if |sample| passes the thread task filter. bool TaskFilterSample(Sample* sample); + bool take_samples() const { return take_samples_; } + static const intptr_t kNoTaskFilter = -1; private: @@ -187,6 +194,7 @@ class SampleFilter : public ValueObject { intptr_t thread_task_mask_; int64_t time_origin_micros_; int64_t time_extent_micros_; + bool take_samples_; }; class ClearProfileVisitor : public SampleVisitor { @@ -718,60 +726,88 @@ class SampleBlock : public SampleBuffer { SampleBlock() = default; virtual ~SampleBlock() = default; - void Clear() { - allocation_block_ = false; - cursor_ = 0; - full_ = false; - evictable_ = false; - next_free_ = nullptr; - } - // Returns the number of samples contained within this block. intptr_t capacity() const { return capacity_; } - // Specify whether or not this block is used for assigning allocation - // samples. - void set_is_allocation_block(bool is_allocation_block) { - allocation_block_ = is_allocation_block; - } - Isolate* owner() const { return owner_; } void set_owner(Isolate* isolate) { owner_ = isolate; } - // Manually marks the block as full so it can be processed and added back to - // the pool of available blocks. - void release_block() { full_.store(true); } - - // When true, this sample block is considered complete and will no longer be - // used to assign new Samples. This block is **not** available for - // re-allocation simply because it's full. It must be processed by - // SampleBlockBuffer::ProcessCompletedBlocks before it can be considered - // evictable and available for re-allocation. - bool is_full() const { return full_.load(); } - - // When true, this sample block is available for re-allocation. - bool evictable() const { return evictable_.load(); } - virtual Sample* ReserveSample(); virtual Sample* ReserveSampleAndLink(Sample* previous); + bool TryAllocateFree() { + State expected = kFree; + State desired = kSampling; + std::memory_order success_order = std::memory_order_acquire; + std::memory_order failure_order = std::memory_order_relaxed; + return state_.compare_exchange_strong(expected, desired, success_order, + failure_order); + } + bool TryAllocateCompleted() { + State expected = kCompleted; + State desired = kSampling; + std::memory_order success_order = std::memory_order_acquire; + std::memory_order failure_order = std::memory_order_relaxed; + if (state_.compare_exchange_strong(expected, desired, success_order, + failure_order)) { + owner_ = nullptr; + cursor_ = 0; + return true; + } + return false; + } + void MarkCompleted() { + ASSERT(state_.load(std::memory_order_relaxed) == kSampling); + state_.store(kCompleted, std::memory_order_release); + } + bool TryAcquireStreaming(Isolate* isolate) { + if (state_.load(std::memory_order_relaxed) != kCompleted) return false; + if (owner_ != isolate) return false; + + State expected = kCompleted; + State desired = kStreaming; + std::memory_order success_order = std::memory_order_acquire; + std::memory_order failure_order = std::memory_order_relaxed; + return state_.compare_exchange_strong(expected, desired, success_order, + failure_order); + } + void StreamingToCompleted() { + ASSERT(state_.load(std::memory_order_relaxed) == kStreaming); + state_.store(kCompleted, std::memory_order_relaxed); + } + void StreamingToFree() { + ASSERT(state_.load(std::memory_order_relaxed) == kStreaming); + owner_ = nullptr; + cursor_ = 0; + state_.store(kFree, std::memory_order_release); + } + void FreeCompleted() { + State expected = kCompleted; + State desired = kStreaming; + std::memory_order success_order = std::memory_order_acquire; + std::memory_order failure_order = std::memory_order_relaxed; + if (state_.compare_exchange_strong(expected, desired, success_order, + failure_order)) { + StreamingToFree(); + } + } + protected: bool HasStreamableSamples(const GrowableObjectArray& tag_table, UserTag* tag); + enum State : uint32_t { + kFree, + kSampling, // I.e., writing. + kCompleted, + kStreaming, // I.e., reading. + }; + std::atomic state_ = kFree; + RelaxedAtomic cursor_ = 0; Isolate* owner_ = nullptr; - bool allocation_block_ = false; - - intptr_t index_; - RelaxedAtomic cursor_ = 0; - RelaxedAtomic full_ = false; - RelaxedAtomic evictable_ = false; - - SampleBlock* next_free_ = nullptr; private: friend class SampleBlockListProcessor; friend class SampleBlockBuffer; - friend class Isolate; DISALLOW_COPY_AND_ASSIGN(SampleBlock); }; @@ -792,23 +828,12 @@ class SampleBlockBuffer : public ProcessedSampleBufferBuilder { void VisitSamples(SampleVisitor* visitor) { ASSERT(visitor != NULL); - for (intptr_t i = 0; i < cursor_.load(); ++i) { - (&blocks_[i])->VisitSamples(visitor); + for (intptr_t i = 0; i < capacity_; ++i) { + blocks_[i].VisitSamples(visitor); } } - // Returns true when there is at least a single block that needs to be - // processed. - // - // NOTE: this should only be called from the interrupt handler as - // invocation will have the side effect of clearing the underlying flag. - bool process_blocks() { return can_process_block_.exchange(false); } - - // Iterates over the blocks in the buffer and processes blocks marked as - // full. Processing consists of sending a service event with the samples from - // completed, unprocessed blocks and marking these blocks are evictable - // (i.e., safe to be re-allocated and re-used). - void ProcessCompletedBlocks(); + void FreeCompletedBlocks(); // Reserves a sample for a CPU profile. // @@ -832,41 +857,10 @@ class SampleBlockBuffer : public ProcessedSampleBufferBuilder { // Returns nullptr if there are no available blocks. SampleBlock* ReserveSampleBlock(); - void FreeBlock(SampleBlock* block) { - ASSERT(block->next_free_ == nullptr); - MutexLocker ml(&free_block_lock_); - if (free_list_head_ == nullptr) { - free_list_head_ = block; - free_list_tail_ = block; - return; - } - free_list_tail_->next_free_ = block; - free_list_tail_ = block; - } - - SampleBlock* GetFreeBlock() { - MutexLocker ml(&free_block_lock_); - if (free_list_head_ == nullptr) { - return nullptr; - } - SampleBlock* block = free_list_head_; - free_list_head_ = block->next_free_; - if (free_list_head_ == nullptr) { - free_list_tail_ = nullptr; - } - block->next_free_ = nullptr; - return block; - } - - Mutex free_block_lock_; - RelaxedAtomic can_process_block_ = false; - // Sample block management. RelaxedAtomic cursor_; SampleBlock* blocks_; intptr_t capacity_; - SampleBlock* free_list_head_; - SampleBlock* free_list_tail_; // Sample buffer management. VirtualMemory* memory_; @@ -876,9 +870,9 @@ class SampleBlockBuffer : public ProcessedSampleBufferBuilder { DISALLOW_COPY_AND_ASSIGN(SampleBlockBuffer); }; -class SampleBlockListProcessor : public ProcessedSampleBufferBuilder { +class StreamingSampleBufferBuilder : public ProcessedSampleBufferBuilder { public: - explicit SampleBlockListProcessor(SampleBlock* head) : head_(head) {} + explicit StreamingSampleBufferBuilder(Isolate* isolate) : isolate_(isolate) {} virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer( SampleFilter* filter, @@ -889,9 +883,9 @@ class SampleBlockListProcessor : public ProcessedSampleBufferBuilder { bool HasStreamableSamples(Thread* thread); private: - SampleBlock* head_; + Isolate* isolate_; - DISALLOW_COPY_AND_ASSIGN(SampleBlockListProcessor); + DISALLOW_COPY_AND_ASSIGN(StreamingSampleBufferBuilder); }; class AllocationSampleBuffer : public SampleBuffer { diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc index 8ddfc77d6ae..817aa9c35ee 100644 --- a/runtime/vm/profiler_service.cc +++ b/runtime/vm/profiler_service.cc @@ -1486,7 +1486,6 @@ void Profile::Build(Thread* thread, ProcessedSampleBufferBuilder* sample_buffer) { // Disable thread interrupts while processing the buffer. DisableThreadInterruptsScope dtis(thread); - ThreadInterrupter::SampleBufferReaderScope scope; ProfileBuilder builder(thread, filter, sample_buffer, this); builder.Build(); } @@ -1906,7 +1905,6 @@ void ProfilerService::ClearSamples() { // Disable thread interrupts while processing the buffer. DisableThreadInterruptsScope dtis(thread); - ThreadInterrupter::SampleBufferReaderScope scope; ClearProfileVisitor clear_profile(isolate); sample_block_buffer->VisitSamples(&clear_profile); diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc index 60d9568cea3..f4d9986de97 100644 --- a/runtime/vm/profiler_test.cc +++ b/runtime/vm/profiler_test.cc @@ -80,9 +80,7 @@ class ProfileSampleBufferTestHelper : public SampleVisitor { intptr_t sum_ = 0; }; -void VisitSamples(SampleBlockBuffer* buffer, SampleVisitor* visitor) { - // Mark the completed blocks as free so they can be re-used. - buffer->ProcessCompletedBlocks(); +static void VisitSamples(SampleBlockBuffer* buffer, SampleVisitor* visitor) { visitor->Reset(); buffer->VisitSamples(visitor); } @@ -119,35 +117,38 @@ TEST_CASE(Profiler_SampleBufferWrapTest) { Sample* s; s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, 2); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(2, visitor.sum()); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, 4); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(6, visitor.sum()); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, 6); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(12, visitor.sum()); // Mark the completed blocks as free so they can be re-used. - sample_buffer->ProcessCompletedBlocks(); + sample_buffer->FreeCompletedBlocks(); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, 8); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(18, visitor.sum()); - { - MutexLocker ml(isolate->current_sample_block_lock()); - isolate->set_current_sample_block(nullptr); - } + + // The overridden sample buffer will be freed before isolate shutdown. + isolate->set_current_sample_block(nullptr); } TEST_CASE(Profiler_SampleBufferIterateTest) { @@ -163,33 +164,35 @@ TEST_CASE(Profiler_SampleBufferIterateTest) { EXPECT_EQ(0, visitor.visited()); Sample* s; s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, kValidPc); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(1, visitor.visited()); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, kValidPc); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(2, visitor.visited()); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, kValidPc); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(3, visitor.visited()); s = sample_buffer->ReserveCPUSample(isolate); + EXPECT_NOTNULL(s); s->Init(i, kValidTimeStamp, 0); s->SetAt(0, kValidPc); VisitSamples(sample_buffer, &visitor); EXPECT_EQ(3, visitor.visited()); - { - MutexLocker ml(isolate->current_sample_block_lock()); - isolate->set_current_sample_block(nullptr); - } + // The overridden sample buffer will be freed before isolate shutdown. + isolate->set_current_sample_block(nullptr); } TEST_CASE(Profiler_AllocationSampleTest) { diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 99024efcabc..50e38212087 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -451,15 +451,8 @@ ErrorPtr Thread::HandleInterrupts() { } #if !defined(PRODUCT) - // Don't block system isolates to process CPU samples to avoid blocking - // them during critical tasks (e.g., initial compilation). - if (!Isolate::IsSystemIsolate(isolate())) { - // Processes completed SampleBlocks and sends CPU sample events over the - // service protocol when applicable. - SampleBlockBuffer* sample_buffer = Profiler::sample_block_buffer(); - if (sample_buffer != nullptr && sample_buffer->process_blocks()) { - sample_buffer->ProcessCompletedBlocks(); - } + if (isolate()->TakeHasCompletedBlocks()) { + Profiler::ProcessCompletedBlocks(this); } HeapProfileSampler& sampler = heap_sampler(); if (sampler.ShouldSetThreadSamplingInterval()) { diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc index 978b4284a0c..aa770abaac3 100644 --- a/runtime/vm/thread_interrupter.cc +++ b/runtime/vm/thread_interrupter.cc @@ -48,11 +48,6 @@ ThreadJoinId ThreadInterrupter::interrupter_thread_id_ = Monitor* ThreadInterrupter::monitor_ = NULL; intptr_t ThreadInterrupter::interrupt_period_ = 1000; intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout; -// Note this initial state means there is one sample buffer reader. This -// allows the EnterSampleReader during Cleanup (needed to ensure the buffer can -// be safely freed) to be balanced by a ExitSampleReader during Init. -std::atomic ThreadInterrupter::sample_buffer_lock_ = {-1}; -std::atomic ThreadInterrupter::sample_buffer_waiters_ = {1}; void ThreadInterrupter::Init() { ASSERT(!initialized_); @@ -81,8 +76,6 @@ void ThreadInterrupter::Startup() { if (FLAG_trace_thread_interrupter) { OS::PrintErr("ThreadInterrupter running.\n"); } - - ExitSampleReader(); } void ThreadInterrupter::Cleanup() { @@ -110,9 +103,6 @@ void ThreadInterrupter::Cleanup() { if (FLAG_trace_thread_interrupter) { OS::PrintErr("ThreadInterrupter shut down.\n"); } - - // Wait for outstanding signals. - EnterSampleReader(); } // Delay between interrupts. diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h index b78765a314b..cc7a71823a3 100644 --- a/runtime/vm/thread_interrupter.h +++ b/runtime/vm/thread_interrupter.h @@ -36,52 +36,6 @@ class ThreadInterrupter : public AllStatic { // Interrupt a thread. static void InterruptThread(OSThread* thread); - class SampleBufferWriterScope : public ValueObject { - public: - SampleBufferWriterScope() { - intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed); - intptr_t new_value; - do { - if (old_value < 0) { - entered_lock_ = false; - return; - } - new_value = old_value + 1; - } while (!sample_buffer_lock_.compare_exchange_weak( - old_value, new_value, std::memory_order_acquire)); - entered_lock_ = true; - } - - ~SampleBufferWriterScope() { - if (!entered_lock_) return; - intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed); - intptr_t new_value; - do { - ASSERT(old_value > 0); - new_value = old_value - 1; - } while (!sample_buffer_lock_.compare_exchange_weak( - old_value, new_value, std::memory_order_release)); - } - - bool CanSample() const { - return entered_lock_ && - sample_buffer_waiters_.load(std::memory_order_relaxed) == 0; - } - - private: - bool entered_lock_; - DISALLOW_COPY_AND_ASSIGN(SampleBufferWriterScope); - }; - - class SampleBufferReaderScope : public ValueObject { - public: - SampleBufferReaderScope() { EnterSampleReader(); } - ~SampleBufferReaderScope() { ExitSampleReader(); } - - private: - DISALLOW_COPY_AND_ASSIGN(SampleBufferReaderScope); - }; - private: static const intptr_t kMaxThreads = 4096; static bool initialized_; @@ -93,15 +47,6 @@ class ThreadInterrupter : public AllStatic { static intptr_t interrupt_period_; static intptr_t current_wait_time_; - // Something like a reader-writer lock. Positive values indicate there are - // outstanding signal handlers that can write to the sample buffer. Negative - // values indicate there are outstanding sample buffer processors that can - // read from the sample buffer. A reader will spin-wait to enter the lock. A - // writer will give up if it fails to enter lock, causing samples to be - // skipping while we are processing the sample buffer or trying to shut down. - static std::atomic sample_buffer_lock_; - static std::atomic sample_buffer_waiters_; - static bool InDeepSleep() { return current_wait_time_ == Monitor::kNoTimeout; } @@ -112,33 +57,6 @@ class ThreadInterrupter : public AllStatic { static void RemoveSignalHandler(); - static void EnterSampleReader() { - sample_buffer_waiters_.fetch_add(1, std::memory_order_relaxed); - - intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed); - intptr_t new_value; - do { - while (old_value > 0) { - // Spin waiting for outstanding SIGPROFs to complete. - old_value = sample_buffer_lock_.load(std::memory_order_relaxed); - } - new_value = old_value - 1; - } while (!sample_buffer_lock_.compare_exchange_weak( - old_value, new_value, std::memory_order_acquire)); - } - - static void ExitSampleReader() { - sample_buffer_waiters_.fetch_sub(1, std::memory_order_relaxed); - - intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed); - intptr_t new_value; - do { - ASSERT(old_value < 0); - new_value = old_value + 1; - } while (!sample_buffer_lock_.compare_exchange_weak( - old_value, new_value, std::memory_order_release)); - } - friend class ThreadInterrupterVisitIsolates; }; diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc index 2f8ed986352..146515c1bf8 100644 --- a/runtime/vm/thread_interrupter_android.cc +++ b/runtime/vm/thread_interrupter_android.cc @@ -41,10 +41,7 @@ void ThreadInterruptSignalHandler(int signal, siginfo_t* info, void* context_) { if (thread == NULL) { return; } - ThreadInterrupter::SampleBufferWriterScope scope; - if (!scope.CanSample()) { - return; - } + ThreadInterruptScope signal_handler_scope; // Extract thread state. ucontext_t* context = reinterpret_cast(context_); mcontext_t mcontext = context->uc_mcontext; diff --git a/runtime/vm/thread_interrupter_fuchsia.cc b/runtime/vm/thread_interrupter_fuchsia.cc index 31b8ba4741d..35620a464bf 100644 --- a/runtime/vm/thread_interrupter_fuchsia.cc +++ b/runtime/vm/thread_interrupter_fuchsia.cc @@ -161,6 +161,7 @@ class ThreadInterrupterFuchsia : public AllStatic { // here as the thread which is being queried is suspended. Thread* thread = static_cast(os_thread->thread()); if (thread != NULL) { + ThreadInterruptScope signal_handler_scope; Profiler::SampleThread(thread, its); } } diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc index 5d7661df6b0..7da18f24a72 100644 --- a/runtime/vm/thread_interrupter_linux.cc +++ b/runtime/vm/thread_interrupter_linux.cc @@ -31,10 +31,7 @@ class ThreadInterrupterLinux : public AllStatic { if (thread == NULL) { return; } - ThreadInterrupter::SampleBufferWriterScope scope; - if (!scope.CanSample()) { - return; - } + ThreadInterruptScope signal_handler_scope; // Extract thread state. ucontext_t* context = reinterpret_cast(context_); mcontext_t mcontext = context->uc_mcontext; diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc index 9676b53f486..e9243a24973 100644 --- a/runtime/vm/thread_interrupter_macos.cc +++ b/runtime/vm/thread_interrupter_macos.cc @@ -66,6 +66,7 @@ class ThreadInterrupterMacOS { if (thread == nullptr) { return; } + ThreadInterruptScope signal_handler_scope; Profiler::SampleThread(thread, ProcessState(state)); } @@ -117,10 +118,6 @@ void ThreadInterrupter::InterruptThread(OSThread* os_thread) { OS::PrintErr("ThreadInterrupter interrupting %p\n", os_thread->id()); } - ThreadInterrupter::SampleBufferWriterScope scope; - if (!scope.CanSample()) { - return; - } ThreadInterrupterMacOS interrupter(os_thread); interrupter.CollectSample(); } diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc index a7cdef781b5..aa13c6796e1 100644 --- a/runtime/vm/thread_interrupter_win.cc +++ b/runtime/vm/thread_interrupter_win.cc @@ -94,6 +94,7 @@ class ThreadInterrupterWin : public AllStatic { // here as the thread which is being queried is suspended. Thread* thread = static_cast(os_thread->thread()); if (thread != NULL) { + ThreadInterruptScope signal_handler_scope; Profiler::SampleThread(thread, its); } ResumeThread(handle);