Supporting de-virtualization for precise types.
Sharpening invoke-virtual and invoke-interface calls to invoke-direct for cases
where the type of "this" pointer in the invoke- params is precisely known.
Instructions that have an invoke opcode are marked as interesting, for each invoke-virtual/interface
we come across with a precise type for "this" we mark the location as a candidate for sharpening,
resolve the concrete method and save its method reference <DexFile, DexMethodIndex> to be sharpened
in CompilerDriver::ComputeInvokeInfo().
Added a new entry to AOT statistics showing the percentage of sharpened calls that were based on
type analysis.
Fix a minor bug in type creation for GetSuperClass(). Previously super class of a precise reference
had precise types created which is not necessarily the case.
Fixed DCHECK in Class::FindVirtualMethodForVirtual to handle cases for Miranda methods.
Sharpening only takes place for cases where no soft failures happen at verification time.
Change-Id: Ic027d0226d6f95260c1918014cb6313f2e0ca455
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 8e23b74..7153768 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -179,7 +179,7 @@
//To pass the verification, the type should be imprecise,
// instantiable or an interface with the precise type set to false.
- CHECK(!precise || klass->IsInstantiable());
+ DCHECK(!precise || klass->IsInstantiable());
// Create a precise type if:
// 1- Class is final and NOT an interface. a precise interface
@@ -189,10 +189,9 @@
RegType* entry;
// Create an imprecise type if we can't tell for a fact that it is precise.
if ((klass->IsFinal()) || precise) {
- CHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
- CHECK(!klass->IsInterface());
+ DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
+ DCHECK(!klass->IsInterface());
entry = new PreciseReferenceType(klass, descriptor, entries_.size());
-
} else {
entry = new ReferenceType(klass, descriptor, entries_.size());
}
@@ -372,7 +371,7 @@
return *cur_entry;
}
}
- std::string descriptor = "";
+ std::string descriptor("");
entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
}
entries_.push_back(entry);
@@ -401,17 +400,34 @@
return *cur_entry;
}
}
- std::string descriptor = "";
+ std::string descriptor("");
entry = new ReferenceType(klass, descriptor, entries_.size());
} else {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
- RegType* cur_entry = entries_[i];
- if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
- return *cur_entry;
+ std::string descriptor;
+ if (klass->IsFinal()) {
+ if (klass->IsInstantiable()) {
+ for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ RegType* cur_entry = entries_[i];
+ if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
+ return *cur_entry;
+ }
+ }
+ // Precise type was not found , create one !
+ entry = new PreciseReferenceType(klass, descriptor, entries_.size());
+ } else {
+ return Conflict();
+ }
+ } else {
+ // Not a final class, create an imprecise reference. Look up if we have it in the cache first.
+ for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ RegType* cur_entry = entries_[i];
+ if (cur_entry->IsReference() && !(cur_entry->IsPrecise()) &&
+ cur_entry->GetClass() == klass) {
+ return *cur_entry;
+ }
}
+ entry = new ReferenceType(klass, descriptor, entries_.size());
}
- std::string descriptor = "";
- entry = new PreciseReferenceType(klass, descriptor, entries_.size());
}
}
entries_.push_back(entry);
@@ -447,7 +463,7 @@
return *cur_entry;
}
}
- std::string descriptor = "";
+ std::string descriptor("");
entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
}
entries_.push_back(entry);