Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coverage reports differ when --optimization-counter-threshold=-1 is used #56075

Closed
a-siva opened this issue Jun 24, 2024 · 6 comments
Closed
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. closed-duplicate Closed in favor of an existing report

Comments

@a-siva
Copy link
Contributor

a-siva commented Jun 24, 2024

The CFE team has made the change to use RecordCoverage to InstanceCall and StaticCall (see https://dart-review.googlesource.com/c/sdk/+/370501)

There seems to be a difference between the coverage results on normal runs Vs runs with the option --optimization-counter-threshold=-1

Applying the following patch makes the results match up

diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 46c46cd1e1f..49c75a002e1 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -62,6 +62,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
   Fragment body(normal_entry);
   body += B->CheckStackOverflowInPrologue(field_helper.position_);
   body += SetupCapturedParameters(parsed_function()->function());
+  body += RecordCoverage(field_helper.position_);
   body += BuildExpression();  // read initializer.
   body += Return(TokenPosition::kNoSource);

@@ -655,7 +656,7 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionBody(
     const Function& dart_function,
     LocalVariable* first_parameter,
     bool constructor) {
-  Fragment body;
+  Fragment body = RecordCoverage(dart_function.token_pos());

   // TODO(27590): Currently the [VariableDeclaration]s from the
   // initializers will be visible inside the entire body of the constructor.

It is unclear why this is needed.

@a-siva a-siva added the area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. label Jun 24, 2024
@a-siva
Copy link
Contributor Author

a-siva commented Jun 24, 2024

//cc @liamappelbe @jensjoha

@alexmarkov
Copy link
Contributor

https://dart-review.googlesource.com/c/sdk/+/370501 added coverage instructions at call sites (at the InstanceCall and StaticCall instructions), so the new coverage instructions effectively replace ICData usage for coverage. However, the missing part is the replacement for function usage counters (Function::WasExecuted), which are incremented during call and used in the coverage reporting, but they are not be updated if call target is inlined during optimizations. Adding RecordCoverage instructions in the prologue should solve this problem. We can also append those instructions to flow graph conditionally (if the position is not covered yet; only when building flow graph during inlining).

Closing this issue as duplicate to #42061.

@alexmarkov alexmarkov added the closed-duplicate Closed in favor of an existing report label Jun 26, 2024
@jensjoha
Copy link
Contributor

But doesn't --optimization-counter-threshold=-1 disable optimizations?

@alexmarkov
Copy link
Contributor

That's right. However, --optimization-counter-threshold=-1 also affects Function::usage_counter() / Function::WasExecuted(): usage counter is not bumped during calls if optimizing JIT is disabled entirely:

void StubCodeCompiler::GenerateUsageCounterIncrement(Register temp_reg) {
if (FLAG_precompiled_mode) {
__ Breakpoint();
return;
}
if (FLAG_optimization_counter_threshold >= 0) {
Register func_reg = temp_reg;
ASSERT(func_reg != IC_DATA_REG);
__ Comment("Increment function counter");
__ movq(func_reg,
FieldAddress(IC_DATA_REG, target::ICData::owner_offset()));
__ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
}
}

That's a yet another reason to replace unreliable function usage counters with explicit RecordCoverage instructions when calculating coverage.

@jensjoha
Copy link
Contributor

Thanks for the explanation!
Should we just apply the patch at the top then?

@alexmarkov
Copy link
Contributor

@jensjoha Yes, we can apply your patch - adding RecordCoverage instructions to the function prologues should be a clear improvement. However, we should also consider cleaning up old coverage machinery which is based on ICData and function usage counters and replacing it with RecordCoverage instructions entirely. I'm not sure if the above patch would be enough to drop old coverage entirely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. closed-duplicate Closed in favor of an existing report
Projects
None yet
Development

No branches or pull requests

3 participants