Make the specification of when we need precise constants more precise.
Means that oatdump output showing values for deoptimization actually reflects
what we see at runtime.
Also, doesn't do precise in the case of determining methods and fields for the
quickened case, which may be an occasional performance win.
Change-Id: I62c7fb244f7996ba9d52e7a7ce75c046b663fa17
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 8c8a355..984f287 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2881,7 +2881,7 @@
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 c7fbc87..449ccce 100644
--- a/runtime/deoptimize_stack_visitor.cc
+++ b/runtime/deoptimize_stack_visitor.cc
@@ -55,7 +55,7 @@
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 c53520d..3123fd7 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -983,7 +983,7 @@
// 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 4863b83..743fd1b 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -165,7 +165,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 495d3c5..9bb915a 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -185,7 +185,7 @@
// 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 @@
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 @@
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 @@
// 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.