diff options
20 files changed, 117 insertions, 91 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 79386defae..e84cfcbe80 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -690,7 +690,6 @@ void CodeGenerator::GenerateUnresolvedFieldAccess( HInstruction* field_access, DataType::Type field_type, uint32_t field_index, - [[maybe_unused]] uint32_t dex_pc, const FieldAccessCallingConvention& calling_convention) { LocationSummary* locations = field_access->GetLocations(); @@ -1168,26 +1167,6 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, // the regular case, we retrieve the dex_pc from the instruction's environment. DCHECK_IMPLIES(native_debug_info, GetCompilerOptions().GetNativeDebuggable()); DCHECK_IMPLIES(!native_debug_info, instruction->HasEnvironment()) << *instruction; - // The code generated for some type conversions - // may call the runtime, thus normally requiring a subsequent - // call to this method. However, the method verifier does not - // produce PC information for certain instructions, which are - // considered "atomic" (they cannot join a GC). - // Therefore we do not currently record PC information for such - // instructions. As this may change later, we added this special - // case so that code generators may nevertheless call - // CodeGenerator::RecordPcInfo without triggering an error in - // CodeGenerator::BuildNativeGCMap ("Missing ref for dex pc 0x") - // thereafter. - if (instruction->IsTypeConversion()) { - return; - } - if (instruction->IsRem()) { - DataType::Type type = instruction->AsRem()->GetResultType(); - if ((type == DataType::Type::kFloat32) || (type == DataType::Type::kFloat64)) { - return; - } - } LocationSummary* locations = instruction->GetLocations(); uint32_t register_mask = locations->GetRegisterMask(); diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 741d3fb589..3919bb0cc1 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -641,12 +641,10 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { DataType::Type field_type, const FieldAccessCallingConvention& calling_convention); -// TODO(solanes): Remove dex_pc from this method void GenerateUnresolvedFieldAccess( HInstruction* field_access, DataType::Type field_type, uint32_t field_index, - [[maybe_unused]] uint32_t dex_pc, const FieldAccessCallingConvention& calling_convention); static void CreateLoadClassRuntimeCallLocationSummary(HLoadClass* cls, diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index b6fe630f64..58447919f6 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -6656,7 +6656,6 @@ void InstructionCodeGeneratorARM64::VisitUnresolvedInstanceFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6673,7 +6672,6 @@ void InstructionCodeGeneratorARM64::VisitUnresolvedInstanceFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6690,7 +6688,6 @@ void InstructionCodeGeneratorARM64::VisitUnresolvedStaticFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6707,7 +6704,6 @@ void InstructionCodeGeneratorARM64::VisitUnresolvedStaticFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 20e9d4e0ff..a7854ac886 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -6445,7 +6445,6 @@ void InstructionCodeGeneratorARMVIXL::VisitUnresolvedInstanceFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6462,7 +6461,6 @@ void InstructionCodeGeneratorARMVIXL::VisitUnresolvedInstanceFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6479,7 +6477,6 @@ void InstructionCodeGeneratorARMVIXL::VisitUnresolvedStaticFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6496,7 +6493,6 @@ void InstructionCodeGeneratorARMVIXL::VisitUnresolvedStaticFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc index cd34b90f98..ba2e307af5 100644 --- a/compiler/optimizing/code_generator_riscv64.cc +++ b/compiler/optimizing/code_generator_riscv64.cc @@ -5085,7 +5085,6 @@ void InstructionCodeGeneratorRISCV64::VisitUnresolvedInstanceFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5102,7 +5101,6 @@ void InstructionCodeGeneratorRISCV64::VisitUnresolvedInstanceFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5119,7 +5117,6 @@ void InstructionCodeGeneratorRISCV64::VisitUnresolvedStaticFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5136,7 +5133,6 @@ void InstructionCodeGeneratorRISCV64::VisitUnresolvedStaticFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 58d38feb8d..ae31e9f198 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -6397,7 +6397,6 @@ void InstructionCodeGeneratorX86::VisitUnresolvedInstanceFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6414,7 +6413,6 @@ void InstructionCodeGeneratorX86::VisitUnresolvedInstanceFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6431,7 +6429,6 @@ void InstructionCodeGeneratorX86::VisitUnresolvedStaticFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -6448,7 +6445,6 @@ void InstructionCodeGeneratorX86::VisitUnresolvedStaticFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 9133f87c7b..891bdd72e8 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -5709,7 +5709,6 @@ void InstructionCodeGeneratorX86_64::VisitUnresolvedInstanceFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5726,7 +5725,6 @@ void InstructionCodeGeneratorX86_64::VisitUnresolvedInstanceFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5743,7 +5741,6 @@ void InstructionCodeGeneratorX86_64::VisitUnresolvedStaticFieldGet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } @@ -5760,7 +5757,6 @@ void InstructionCodeGeneratorX86_64::VisitUnresolvedStaticFieldSet( codegen_->GenerateUnresolvedFieldAccess(instruction, instruction->GetFieldType(), instruction->GetFieldIndex(), - instruction->GetDexPc(), calling_convention); } diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc index c5ec0b93b2..b8cd39e77f 100644 --- a/compiler/optimizing/dead_code_elimination.cc +++ b/compiler/optimizing/dead_code_elimination.cc @@ -488,7 +488,8 @@ void HDeadCodeElimination::MaybeAddPhi(HBasicBlock* block) { if (block_cond->GetLeft() != dominator_cond->GetLeft() || block_cond->GetRight() != dominator_cond->GetRight() || - block_cond->GetOppositeCondition() != dominator_cond->GetCondition()) { + block_cond->GetOppositeCondition() != dominator_cond->GetCondition() || + block_cond->GetBias() != dominator_cond->GetBias()) { return; } } diff --git a/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java index b7f47543fc..51a01b363d 100644 --- a/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java +++ b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java @@ -17,6 +17,7 @@ package com.android.server.art; import static com.android.server.art.model.ArtFlags.ScheduleStatus; +import static com.android.server.art.prereboot.PreRebootDriver.PreRebootResult; import static com.android.server.art.proto.PreRebootStats.Status; import android.annotation.NonNull; @@ -158,9 +159,10 @@ public class PreRebootDexoptJob implements ArtServiceJobInterface { // return value of `onStopJob` will be respected, and this call will be ignored. jobService.jobFinished(params, false /* wantsReschedule */); }; - // No need to handle exceptions thrown by the future because exceptions are handled inside - // the future itself. - startLocked(onJobFinishedLocked); + startLocked(onJobFinishedLocked).exceptionally(t -> { + AsLog.e("Fatal error", t); + return null; + }); } @Override @@ -357,10 +359,15 @@ public class PreRebootDexoptJob implements ArtServiceJobInterface { var cancellationSignal = mCancellationSignal = new CancellationSignal(); mRunningJob = new CompletableFuture().runAsync(() -> { markHasStarted(true); + PreRebootStatsReporter statsReporter = mInjector.getStatsReporter(); try { - mInjector.getPreRebootDriver().run(otaSlot, mapSnapshotsForOta, cancellationSignal); + statsReporter.recordJobStarted(); + PreRebootResult result = mInjector.getPreRebootDriver().run( + otaSlot, mapSnapshotsForOta, cancellationSignal); + statsReporter.recordJobEnded(result); } catch (RuntimeException e) { - AsLog.e("Fatal error", e); + statsReporter.recordJobEnded(new PreRebootResult(false /* success */)); + throw e; } finally { synchronized (this) { if (onJobFinishedLocked != null) { diff --git a/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java b/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java index 7c1a1c55fa..c29e0b4b2c 100644 --- a/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java +++ b/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java @@ -86,20 +86,16 @@ public class PreRebootDriver { } /** - * Runs Pre-reboot Dexopt and returns whether it is successful. Returns false if Pre-reboot - * dexopt failed, the system requirement check failed, or system requirements are not met. + * Runs Pre-reboot Dexopt and returns the result. * * @param otaSlot The slot that contains the OTA update, "_a" or "_b", or null for a Mainline * update. * @param mapSnapshotsForOta Whether to map/unmap snapshots. Only applicable to an OTA update. */ - public boolean run(@Nullable String otaSlot, boolean mapSnapshotsForOta, + public @NonNull PreRebootResult run(@Nullable String otaSlot, boolean mapSnapshotsForOta, @NonNull CancellationSignal cancellationSignal) { - var statsReporter = new PreRebootStatsReporter(); - boolean success = false; boolean systemRequirementCheckFailed = false; try { - statsReporter.recordJobStarted(); try (var snapshot = mInjector.getPackageManagerLocal().withFilteredSnapshot()) { BatchDexoptParams params = mInjector.getArtManagerLocal().getBatchDexoptParams( snapshot, ReasonMapping.REASON_PRE_REBOOT_DEXOPT, cancellationSignal); @@ -108,8 +104,7 @@ public class PreRebootDriver { runFromChroot(cancellationSignal, snapshot, params); } } - success = true; - return true; + return new PreRebootResult(true /* success */); } catch (RemoteException e) { Utils.logArtdException(e); } catch (ServiceSpecificException e) { @@ -139,11 +134,9 @@ public class PreRebootDriver { Utils.logArtdException(e); } catch (ServiceSpecificException | IOException e) { AsLog.e("Failed to tear down chroot", e); - } finally { - statsReporter.recordJobEnded(success, systemRequirementCheckFailed); } } - return false; + return new PreRebootResult(false /* success */, systemRequirementCheckFailed); } public void test() { @@ -257,6 +250,16 @@ public class PreRebootDriver { } /** + * @param success whether Pre-reboot Dexopt is successful. False if Pre-reboot dexopt failed, + * the system requirement check failed, or system requirements are not met. + */ + public record PreRebootResult(boolean success, boolean systemRequirementCheckFailed) { + public PreRebootResult(boolean success) { + this(success, false /* systemRequirementCheckFailed */); + } + } + + /** * Injector pattern for testing purpose. * * @hide diff --git a/libartservice/service/java/com/android/server/art/prereboot/PreRebootStatsReporter.java b/libartservice/service/java/com/android/server/art/prereboot/PreRebootStatsReporter.java index fbf242db62..ec5c1acf31 100644 --- a/libartservice/service/java/com/android/server/art/prereboot/PreRebootStatsReporter.java +++ b/libartservice/service/java/com/android/server/art/prereboot/PreRebootStatsReporter.java @@ -16,6 +16,7 @@ package com.android.server.art.prereboot; +import static com.android.server.art.prereboot.PreRebootDriver.PreRebootResult; import static com.android.server.art.proto.PreRebootStats.JobRun; import static com.android.server.art.proto.PreRebootStats.JobType; import static com.android.server.art.proto.PreRebootStats.Status; @@ -141,7 +142,7 @@ public class PreRebootStatsReporter { } } - public void recordJobEnded(boolean success, boolean systemRequirementCheckFailed) { + public void recordJobEnded(@NonNull PreRebootResult result) { PreRebootStats.Builder statsBuilder = load(); if (statsBuilder.getStatus() == Status.STATUS_UNKNOWN) { // Failed to load, the error is already logged. @@ -157,7 +158,7 @@ public class PreRebootStatsReporter { mInjector.getCurrentTimeMillis()); Status status; - if (success) { + if (result.success()) { // The job is cancelled if it hasn't done package scanning (total package count is 0), // or it's interrupted in the middle of package processing (package counts don't add up // to the total). @@ -172,7 +173,7 @@ public class PreRebootStatsReporter { status = Status.STATUS_CANCELLED; } } else { - if (systemRequirementCheckFailed) { + if (result.systemRequirementCheckFailed()) { status = Status.STATUS_ABORTED_SYSTEM_REQUIREMENTS; } else { status = Status.STATUS_FAILED; diff --git a/libartservice/service/javatests/com/android/server/art/PreRebootDexoptJobTest.java b/libartservice/service/javatests/com/android/server/art/PreRebootDexoptJobTest.java index 4aaf1d5be9..0d99db20e7 100644 --- a/libartservice/service/javatests/com/android/server/art/PreRebootDexoptJobTest.java +++ b/libartservice/service/javatests/com/android/server/art/PreRebootDexoptJobTest.java @@ -17,6 +17,7 @@ package com.android.server.art; import static com.android.server.art.PreRebootDexoptJob.JOB_ID; +import static com.android.server.art.prereboot.PreRebootDriver.PreRebootResult; import static com.google.common.truth.Truth.assertThat; @@ -236,7 +237,7 @@ public class PreRebootDexoptJobTest { when(mPreRebootDriver.run(any(), eq(true) /* mapSnapshotsForOta */, any())) .thenAnswer(invocation -> { jobStarted.release(); - return true; + return new PreRebootResult(true /* success */); }); when(ArtJni.setProperty("dalvik.vm.pre-reboot.has-started", "true")) @@ -259,7 +260,7 @@ public class PreRebootDexoptJobTest { @Test public void testSyncStart() throws Exception { when(mPreRebootDriver.run(any(), eq(false) /* mapSnapshotsForOta */, any())) - .thenReturn(true); + .thenReturn(new PreRebootResult(true /* success */)); CompletableFuture<Void> future = mPreRebootDexoptJob.onUpdateReadyStartNow( null /* otaSlot */, false /* mapSnapshotsForOta */); @@ -276,7 +277,7 @@ public class PreRebootDexoptJobTest { cancellationSignal.setOnCancelListener(() -> dexoptCancelled.release()); assertThat(dexoptCancelled.tryAcquire(TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue(); jobExited.release(); - return true; + return new PreRebootResult(true /* success */); }); mPreRebootDexoptJob.onUpdateReadyImpl(null /* otaSlot */); @@ -297,7 +298,7 @@ public class PreRebootDexoptJobTest { cancellationSignal.setOnCancelListener(() -> dexoptCancelled.release()); assertThat(dexoptCancelled.tryAcquire(TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue(); jobExited.release(); - return true; + return new PreRebootResult(true /* success */); }); CompletableFuture<Void> future = mPreRebootDexoptJob.onUpdateReadyStartNow( @@ -314,7 +315,8 @@ public class PreRebootDexoptJobTest { mPreRebootDexoptJob.onUpdateReadyImpl("_b" /* otaSlot */); mPreRebootDexoptJob.onUpdateReadyImpl(null /* otaSlot */); - when(mPreRebootDriver.run(eq("_b"), anyBoolean(), any())).thenReturn(true); + when(mPreRebootDriver.run(eq("_b"), anyBoolean(), any())) + .thenReturn(new PreRebootResult(true /* success */)); mPreRebootDexoptJob.onStartJobImpl(mJobService, mJobParameters); mPreRebootDexoptJob.waitForRunningJob(); @@ -325,7 +327,8 @@ public class PreRebootDexoptJobTest { mPreRebootDexoptJob.onUpdateReadyImpl(null /* otaSlot */); mPreRebootDexoptJob.onUpdateReadyImpl("_a" /* otaSlot */); - when(mPreRebootDriver.run(eq("_a"), anyBoolean(), any())).thenReturn(true); + when(mPreRebootDriver.run(eq("_a"), anyBoolean(), any())) + .thenReturn(new PreRebootResult(true /* success */)); mPreRebootDexoptJob.onStartJobImpl(mJobService, mJobParameters); mPreRebootDexoptJob.waitForRunningJob(); @@ -336,7 +339,8 @@ public class PreRebootDexoptJobTest { mPreRebootDexoptJob.onUpdateReadyImpl(null /* otaSlot */); mPreRebootDexoptJob.onUpdateReadyImpl(null /* otaSlot */); - when(mPreRebootDriver.run(isNull(), anyBoolean(), any())).thenReturn(true); + when(mPreRebootDriver.run(isNull(), anyBoolean(), any())) + .thenReturn(new PreRebootResult(true /* success */)); mPreRebootDexoptJob.onStartJobImpl(mJobService, mJobParameters); mPreRebootDexoptJob.waitForRunningJob(); @@ -347,7 +351,8 @@ public class PreRebootDexoptJobTest { mPreRebootDexoptJob.onUpdateReadyImpl("_b" /* otaSlot */); mPreRebootDexoptJob.onUpdateReadyImpl("_b" /* otaSlot */); - when(mPreRebootDriver.run(eq("_b"), anyBoolean(), any())).thenReturn(true); + when(mPreRebootDriver.run(eq("_b"), anyBoolean(), any())) + .thenReturn(new PreRebootResult(true /* success */)); mPreRebootDexoptJob.onStartJobImpl(mJobService, mJobParameters); mPreRebootDexoptJob.waitForRunningJob(); @@ -375,7 +380,7 @@ public class PreRebootDexoptJobTest { when(mPreRebootDriver.run(any(), anyBoolean(), any())).thenAnswer(invocation -> { // Simulate that the job takes a while to exit, no matter it's cancelled or not. assertThat(jobBlocker.tryAcquire(TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue(); - return true; + return new PreRebootResult(true /* success */); }); // An update arrives. A job is scheduled. @@ -461,7 +466,7 @@ public class PreRebootDexoptJobTest { cancellationSignal.setOnCancelListener(() -> dexoptCancelled.release()); assertThat(dexoptCancelled.tryAcquire(TIMEOUT_SEC, TimeUnit.SECONDS)).isTrue(); jobExited.release(); - return true; + return new PreRebootResult(true /* success */); }); // An update arrives. A job is scheduled. diff --git a/libartservice/service/javatests/com/android/server/art/prereboot/PreRebootStatsReporterTest.java b/libartservice/service/javatests/com/android/server/art/prereboot/PreRebootStatsReporterTest.java index 59291b7471..846a835b75 100644 --- a/libartservice/service/javatests/com/android/server/art/prereboot/PreRebootStatsReporterTest.java +++ b/libartservice/service/javatests/com/android/server/art/prereboot/PreRebootStatsReporterTest.java @@ -17,6 +17,7 @@ package com.android.server.art.prereboot; import static com.android.server.art.model.DexoptStatus.DexContainerFileDexoptStatus; +import static com.android.server.art.prereboot.PreRebootDriver.PreRebootResult; import static com.android.server.art.proto.PreRebootStats.JobRun; import static com.android.server.art.proto.PreRebootStats.JobType; import static com.android.server.art.proto.PreRebootStats.Status; @@ -118,7 +119,7 @@ public class PreRebootStatsReporterTest { .build()); doReturn(300l).when(mInjector).getCurrentTimeMillis(); - reporter.recordJobEnded(true /* success */, false /* systemRequirementCheckFailed */); + reporter.recordJobEnded(new PreRebootResult(true /* success */)); checkProto(PreRebootStats.newBuilder() .setStatus(Status.STATUS_CANCELLED) .setJobType(JobType.JOB_TYPE_MAINLINE) @@ -174,7 +175,7 @@ public class PreRebootStatsReporterTest { .build()); doReturn(600l).when(mInjector).getCurrentTimeMillis(); - reporter.recordJobEnded(true /* success */, false /* systemRequirementCheckFailed */); + reporter.recordJobEnded(new PreRebootResult(true /* success */)); checkProto(PreRebootStats.newBuilder() .setStatus(Status.STATUS_FINISHED) .setJobType(JobType.JOB_TYPE_MAINLINE) @@ -290,7 +291,7 @@ public class PreRebootStatsReporterTest { .build()); doReturn(300l).when(mInjector).getCurrentTimeMillis(); - reporter.recordJobEnded(true /* success */, false /* systemRequirementCheckFailed */); + reporter.recordJobEnded(new PreRebootResult(true /* success */)); checkProto(PreRebootStats.newBuilder() .setStatus(Status.STATUS_FINISHED) .setJobType(JobType.JOB_TYPE_OTA) @@ -350,7 +351,8 @@ public class PreRebootStatsReporterTest { .build()); doReturn(300l).when(mInjector).getCurrentTimeMillis(); - reporter.recordJobEnded(false /* success */, systemRequirementCheckFailed); + reporter.recordJobEnded( + new PreRebootResult(false /* success */, systemRequirementCheckFailed)); checkProto(PreRebootStats.newBuilder() .setStatus(systemRequirementCheckFailed ? Status.STATUS_ABORTED_SYSTEM_REQUIREMENTS diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index 26a665bd41..9d7b20052b 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -1023,6 +1023,7 @@ void ReaderWriterMutex::WakeupToRespondToEmptyCheckpoint() { ConditionVariable::ConditionVariable(const char* name, Mutex& guard) : name_(name), guard_(guard) { + DCHECK(name != nullptr); #if ART_USE_FUTEXES DCHECK_EQ(0, sequence_.load(std::memory_order_relaxed)); num_waiters_ = 0; @@ -1120,7 +1121,7 @@ void ConditionVariable::WaitHoldingLocks(Thread* self) { // EAGAIN == EWOULDBLK, so we let the caller try again. // EINTR implies a signal was sent to this thread. if ((errno != EINTR) && (errno != EAGAIN)) { - PLOG(FATAL) << "futex wait failed for " << name_; + PLOG(FATAL) << "futex wait failed for " << name_ << ": " << strerror(errno); } } SleepIfRuntimeDeleted(self); diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index 7f80c03a2a..6e4a12d3cc 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -364,7 +364,7 @@ void MemberSignature::WarnAboutAccess(AccessMethod access_method, if (log_warning_count_ > kMaxLogWarnings) { return; } - LOG(policy == EnforcementPolicy::kEnabled ? ERROR : WARNING) + LOG(access_denied ? (policy == EnforcementPolicy::kEnabled ? ERROR : WARNING) : INFO) << "hiddenapi: Accessing hidden " << (type_ == kField ? "field " : "method ") << Dumpable<MemberSignature>(*this) << " (runtime_flags=" << FormatHiddenApiRuntimeFlags(runtime_flags) diff --git a/test/2038-hiddenapi-jvmti-ext/run.py b/test/2038-hiddenapi-jvmti-ext/run.py index c3f6d8fb72..49a7ef365a 100644 --- a/test/2038-hiddenapi-jvmti-ext/run.py +++ b/test/2038-hiddenapi-jvmti-ext/run.py @@ -18,6 +18,5 @@ def run(ctx, args): ctx.default_run(args, jvmti=True) - # Delete hiddenapi's denial errors which go to stderr on host. - if args.host: - ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") + # Ignore hiddenapi's denial errors which go to stderr on host and qemu (but not on device). + ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") diff --git a/test/2255-checker-branch-redirection/src/Main.java b/test/2255-checker-branch-redirection/src/Main.java index bfc6381942..a2c04ef6e0 100644 --- a/test/2255-checker-branch-redirection/src/Main.java +++ b/test/2255-checker-branch-redirection/src/Main.java @@ -32,6 +32,15 @@ public class Main { assertEquals(30, $noinline$testEliminateIfParameterOppositeCondition(20, 10, 20 < 10)); assertEquals(40, $noinline$testEliminateIfParameterOppositeCondition_2(20, 40, 20 < 40)); assertEquals(30, $noinline$testEliminateIfParameterOppositeCondition_2(20, 10, 20 < 10)); + + assertEquals(2, $noinline$testEliminateIfFp(20.0, 40.0)); + assertEquals(3, $noinline$testEliminateIfFp(20.0, 10.0)); + assertEquals(3, $noinline$testEliminateIfFp(20.0, Double.NaN)); + assertEquals(3, $noinline$testEliminateIfFp(Double.NaN, 10.0)); + assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, 40.0)); + assertEquals(2, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, 10.0)); + assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, Double.NaN)); + assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(Double.NaN, 10.0)); } private static int $noinline$emptyMethod(int a) { @@ -274,6 +283,50 @@ public class Main { return result; } + /// CHECK-START: int Main.$noinline$testEliminateIfFp(double, double) dead_code_elimination$after_gvn (before) + /// CHECK: If + /// CHECK: If + + /// CHECK-START: int Main.$noinline$testEliminateIfFp(double, double) dead_code_elimination$after_gvn (after) + /// CHECK: If + /// CHECK-NOT: If + private static int $noinline$testEliminateIfFp(double a, double b) { + int result = 0; + if (a < b) { + $noinline$emptyMethod(0); + } else { + $noinline$emptyMethod(1); + } + if (a < b) { + result += $noinline$emptyMethod(2); + } else { + result += $noinline$emptyMethod(3); + } + return result; + } + + /// CHECK-START: int Main.$noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double, double) dead_code_elimination$initial (before) + /// CHECK: If + /// CHECK: If + + /// CHECK-START: int Main.$noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double, double) dead_code_elimination$initial (after) + /// CHECK: If + /// CHECK: If + private static int $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double a, double b) { + int result = 0; + if (a < b) { + $noinline$emptyMethod(0); + } else { + $noinline$emptyMethod(1); + } + if (a >= b) { + result += $noinline$emptyMethod(2); + } else { + result += $noinline$emptyMethod(3); + } + return result; + } + public static void assertEquals(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); diff --git a/test/674-hiddenapi/run.py b/test/674-hiddenapi/run.py index ea0cd1d3b5..7967a46047 100644 --- a/test/674-hiddenapi/run.py +++ b/test/674-hiddenapi/run.py @@ -25,6 +25,5 @@ def run(ctx, args): ctx.run(fr"sed -i -E '/(JNI_OnLoad|JNI_OnUnload)/d' '{args.stdout_file}'") - # Delete hiddenapi's denial errors which go to stderr on host. - if args.host: - ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") + # Ignore hiddenapi's denial errors which go to stderr on host and qemu (but not on device). + ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") diff --git a/test/817-hiddenapi/run.py b/test/817-hiddenapi/run.py index 14670eb0c5..a394a4ea29 100644 --- a/test/817-hiddenapi/run.py +++ b/test/817-hiddenapi/run.py @@ -21,6 +21,5 @@ def run(ctx, args): # be emitted. If so, remove it. ctx.run(fr"sed -i '/^JNI_OnUnload called$/d' '{args.stdout_file}'") - # Delete hiddenapi's denial errors which go to stderr on host. - if args.host: - ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") + # Ignore hiddenapi's denial errors which go to stderr on host and qemu (but not on device). + ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") diff --git a/test/999-redefine-hiddenapi/run.py b/test/999-redefine-hiddenapi/run.py index c3f6d8fb72..49a7ef365a 100644 --- a/test/999-redefine-hiddenapi/run.py +++ b/test/999-redefine-hiddenapi/run.py @@ -18,6 +18,5 @@ def run(ctx, args): ctx.default_run(args, jvmti=True) - # Delete hiddenapi's denial errors which go to stderr on host. - if args.host: - ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") + # Ignore hiddenapi's denial errors which go to stderr on host and qemu (but not on device). + ctx.run(fr"sed -i -E '/ E dalvikvm.* hiddenapi: /d' '{args.stderr_file}'") |