diff options
| author | 2014-05-23 18:14:40 +0000 | |
|---|---|---|
| committer | 2014-05-23 18:14:40 +0000 | |
| commit | ae19a731ccd62117d8b14e478caee5ac1b6251d2 (patch) | |
| tree | 51fc2db34a7d834e505db07877ff36732b456e6f | |
| parent | ec23021ceb9f91a424c524fbfbcc9de6fb21f2b1 (diff) | |
| parent | 46960fe5dcc1be07b39a55114338423a73554449 (diff) | |
Merge "Make the specification of when we need precise constants more precise."
| -rw-r--r-- | oatdump/oatdump.cc | 2 | ||||
| -rw-r--r-- | runtime/debugger.cc | 2 | ||||
| -rw-r--r-- | runtime/deoptimize_stack_visitor.cc | 2 | ||||
| -rw-r--r-- | runtime/monitor.cc | 2 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 61 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.h | 13 |
6 files changed, 46 insertions, 36 deletions
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index d38f37f0f3..5dee1af9dc 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -430,7 +430,7 @@ class OatDumper { auto class_loader(hs.NewHandle<mirror::ClassLoader>(nullptr)); verifier::MethodVerifier verifier(&dex_file, &dex_cache, &class_loader, &class_def, code_item, dex_method_idx, nullptr, method_access_flags, - true, true); + true, true, true); verifier.Verify(); DumpCode(indent2_os, &verifier, oat_method, code_item); } else { diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 8c8a3556da..984f28723c 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -2881,7 +2881,7 @@ static bool IsMethodPossiblyInlined(Thread* self, mirror::ArtMethod* m) Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m, - m->GetAccessFlags(), false, true); + m->GetAccessFlags(), false, true, false); // Note: we don't need to verify the method. return InlineMethodAnalyser::AnalyseMethodCode(&verifier, nullptr); } diff --git a/runtime/deoptimize_stack_visitor.cc b/runtime/deoptimize_stack_visitor.cc index c7fbc87572..449ccce64f 100644 --- a/runtime/deoptimize_stack_visitor.cc +++ b/runtime/deoptimize_stack_visitor.cc @@ -55,7 +55,7 @@ bool DeoptimizeStackVisitor::HandleDeoptimization(mirror::ArtMethod* m) { Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m, - m->GetAccessFlags(), false, true); + m->GetAccessFlags(), false, true, true); verifier.Verify(); std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc); for (uint16_t reg = 0; reg < num_regs; ++reg) { diff --git a/runtime/monitor.cc b/runtime/monitor.cc index c53520de12..3123fd7787 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -983,7 +983,7 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::O // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to // the locks held in this stack frame. std::vector<uint32_t> monitor_enter_dex_pcs; - verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), monitor_enter_dex_pcs); + verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), &monitor_enter_dex_pcs); if (monitor_enter_dex_pcs.empty()) { return; } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 4863b8367b..743fd1bd9f 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -165,7 +165,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags(), - allow_soft_failures); + allow_soft_failures, + false); if (result != kNoFailure) { if (result == kHardFailure) { hard_fail = true; @@ -207,7 +208,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags(), - allow_soft_failures); + allow_soft_failures, + false); if (result != kNoFailure) { if (result == kHardFailure) { hard_fail = true; @@ -238,32 +240,34 @@ MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, uint32_t method_access_flags, - bool allow_soft_failures) { + bool allow_soft_failures, + bool need_precise_constants) { MethodVerifier::FailureKind result = kNoFailure; uint64_t start_ns = NanoTime(); - MethodVerifier verifier_(dex_file, &dex_cache, &class_loader, class_def, code_item, - method_idx, method, method_access_flags, true, allow_soft_failures); - if (verifier_.Verify()) { + MethodVerifier verifier(dex_file, &dex_cache, &class_loader, class_def, code_item, + method_idx, method, method_access_flags, true, allow_soft_failures, + need_precise_constants); + if (verifier.Verify()) { // Verification completed, however failures may be pending that didn't cause the verification // to hard fail. - CHECK(!verifier_.have_pending_hard_failure_); - if (verifier_.failures_.size() != 0) { + CHECK(!verifier.have_pending_hard_failure_); + if (verifier.failures_.size() != 0) { if (VLOG_IS_ON(verifier)) { - verifier_.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in " + verifier.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in " << PrettyMethod(method_idx, *dex_file) << "\n"); } result = kSoftFailure; } } else { // Bad method data. - CHECK_NE(verifier_.failures_.size(), 0U); - CHECK(verifier_.have_pending_hard_failure_); - verifier_.DumpFailures(LOG(INFO) << "Verification error in " + CHECK_NE(verifier.failures_.size(), 0U); + CHECK(verifier.have_pending_hard_failure_); + verifier.DumpFailures(LOG(INFO) << "Verification error in " << PrettyMethod(method_idx, *dex_file) << "\n"); if (gDebugVerify) { - std::cout << "\n" << verifier_.info_messages_.str(); - verifier_.Dump(std::cout); + std::cout << "\n" << verifier.info_messages_.str(); + verifier.Dump(std::cout); } result = kHardFailure; } @@ -284,7 +288,7 @@ void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_i mirror::ArtMethod* method, uint32_t method_access_flags) { MethodVerifier verifier(dex_file, &dex_cache, &class_loader, class_def, code_item, - dex_method_idx, method, method_access_flags, true, true); + dex_method_idx, method, method_access_flags, true, true, true); verifier.Verify(); verifier.DumpFailures(os); os << verifier.info_messages_.str(); @@ -296,7 +300,8 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, Handle<mirror::DexCache> const DexFile::ClassDef* class_def, const DexFile::CodeItem* code_item, uint32_t dex_method_idx, mirror::ArtMethod* method, uint32_t method_access_flags, - bool can_load_classes, bool allow_soft_failures) + bool can_load_classes, bool allow_soft_failures, + bool need_precise_constants) : reg_types_(can_load_classes), work_insn_idx_(-1), dex_method_idx_(dex_method_idx), @@ -317,6 +322,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, Handle<mirror::DexCache> monitor_enter_count_(0), can_load_classes_(can_load_classes), allow_soft_failures_(allow_soft_failures), + need_precise_constants_(need_precise_constants), has_check_casts_(false), has_virtual_or_interface_invokes_(false) { Runtime::Current()->AddMethodVerifier(this); @@ -329,16 +335,16 @@ MethodVerifier::~MethodVerifier() { } void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc, - std::vector<uint32_t>& monitor_enter_dex_pcs) { + std::vector<uint32_t>* monitor_enter_dex_pcs) { MethodHelper mh(m); StackHandleScope<2> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, - true); + true, false); verifier.interesting_dex_pc_ = dex_pc; - verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs; + verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs; verifier.FindLocksAtDexPc(); } @@ -354,14 +360,14 @@ void MethodVerifier::FindLocksAtDexPc() { } mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, - uint32_t dex_pc) { + uint32_t dex_pc) { MethodHelper mh(m); StackHandleScope<2> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, - true); + true, false); return verifier.FindAccessedFieldAtDexPc(dex_pc); } @@ -392,7 +398,7 @@ mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, - true); + true, false); return verifier.FindInvokedMethodAtDexPc(dex_pc); } @@ -1436,9 +1442,6 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { std::unique_ptr<RegisterLine> branch_line; std::unique_ptr<RegisterLine> fallthrough_line; - // We need precise constant types only for deoptimization which happens at runtime. - const bool need_precise_constant = !Runtime::Current()->IsCompiler(); - switch (inst->Opcode()) { case Instruction::NOP: /* @@ -1590,25 +1593,25 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::CONST_4: { int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28; work_line_->SetRegisterType(inst->VRegA_11n(), - DetermineCat1Constant(val, need_precise_constant)); + DetermineCat1Constant(val, need_precise_constants_)); break; } case Instruction::CONST_16: { int16_t val = static_cast<int16_t>(inst->VRegB_21s()); work_line_->SetRegisterType(inst->VRegA_21s(), - DetermineCat1Constant(val, need_precise_constant)); + DetermineCat1Constant(val, need_precise_constants_)); break; } case Instruction::CONST: { int32_t val = inst->VRegB_31i(); work_line_->SetRegisterType(inst->VRegA_31i(), - DetermineCat1Constant(val, need_precise_constant)); + DetermineCat1Constant(val, need_precise_constants_)); break; } case Instruction::CONST_HIGH16: { int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16); work_line_->SetRegisterType(inst->VRegA_21h(), - DetermineCat1Constant(val, need_precise_constant)); + DetermineCat1Constant(val, need_precise_constants_)); break; } /* could be long or double; resolved upon use */ diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 495d3c5353..9bb915acc8 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -185,7 +185,7 @@ class MethodVerifier { // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding // to the locks held at 'dex_pc' in method 'm'. static void FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc, - std::vector<uint32_t>& monitor_enter_dex_pcs) + std::vector<uint32_t>* monitor_enter_dex_pcs) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the accessed field corresponding to the quick instruction's field @@ -208,7 +208,8 @@ class MethodVerifier { MethodVerifier(const DexFile* dex_file, Handle<mirror::DexCache>* dex_cache, Handle<mirror::ClassLoader>* class_loader, const DexFile::ClassDef* class_def, const DexFile::CodeItem* code_item, uint32_t method_idx, mirror::ArtMethod* method, - uint32_t access_flags, bool can_load_classes, bool allow_soft_failures) + uint32_t access_flags, bool can_load_classes, bool allow_soft_failures, + bool need_precise_constants) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ~MethodVerifier(); @@ -260,7 +261,7 @@ class MethodVerifier { const DexFile::ClassDef* class_def_idx, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, uint32_t method_access_flags, - bool allow_soft_failures) + bool allow_soft_failures, bool need_precise_constants) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -672,6 +673,12 @@ class MethodVerifier { // running and the verifier is called from the class linker. const bool allow_soft_failures_; + // An optimization where instead of generating unique RegTypes for constants we use imprecise + // constants that cover a range of constants. This isn't good enough for deoptimization that + // avoids loading from registers in the case of a constant as the dex instruction set lost the + // notion of whether a value should be in a floating point or general purpose register file. + const bool need_precise_constants_; + // Indicates the method being verified contains at least one check-cast or aput-object // instruction. Aput-object operations implicitly check for array-store exceptions, similar to // check-cast. |