Prevent overflow for AOT hotness counters
Previous, the addition did not have a check for overflow and might wrap
around since the counter is only 16 bits.
Modified the test to exercise this.
The slowdown from fixing the overflow is 2% average on golem arm32/64.
Overall this brings the slowdown from the counter to ~15% from ~13%.
The benchmarks that regress the most are loopy ones that I would
consider non-representative. Code size increases by 0.6%.
Bug: 139883463
Test: test/run-test --host --64 --prebuild 674-hotness-compiled
Test: test/run-test --host --prebuild 674-hotness-compiled
Test: test/run-test --64 --prebuild 674-hotness-compiled
Test: test/run-test ---prebuild 674-hotness-compiled
Change-Id: Icf0ab2aedbc40ab10c9d952ce0f9c7b5e5feaf15
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 4ab398e..797fe32 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1078,8 +1078,15 @@
DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
- __ addw(Address(kMethodRegisterArgument, ArtMethod::HotnessCountOffset().Int32Value()),
+ NearLabel overflow;
+ __ cmpw(Address(kMethodRegisterArgument,
+ ArtMethod::HotnessCountOffset().Int32Value()),
+ Immediate(ArtMethod::MaxCounter()));
+ __ j(kEqual, &overflow);
+ __ addw(Address(kMethodRegisterArgument,
+ ArtMethod::HotnessCountOffset().Int32Value()),
Immediate(1));
+ __ Bind(&overflow);
}
if (!skip_overflow_check) {
@@ -1385,7 +1392,13 @@
if (codegen_->GetCompilerOptions().CountHotnessInCompiledCode()) {
__ pushl(EAX);
__ movl(EAX, Address(ESP, kX86WordSize));
- __ addw(Address(EAX, ArtMethod::HotnessCountOffset().Int32Value()), Immediate(1));
+ NearLabel overflow;
+ __ cmpw(Address(EAX, ArtMethod::HotnessCountOffset().Int32Value()),
+ Immediate(ArtMethod::MaxCounter()));
+ __ j(kEqual, &overflow);
+ __ addw(Address(EAX, ArtMethod::HotnessCountOffset().Int32Value()),
+ Immediate(1));
+ __ Bind(&overflow);
__ popl(EAX);
}
GenerateSuspendCheck(info->GetSuspendCheck(), successor);