Verifier improvements.
Make type hierarchy for unresolved and unitialized types explicit.
Tidy and comment code.
Add DexFile::FindStringId that takes UTF-16 to avoid unnecessary UTF-8
conversions during image writing.
Explicitly disable RTTI that causes problems in debug builds.
Change-Id: I701f1c3be8be5854fcabf5ec39e9f9c5d388aab0
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 5c642be..e06c8cd 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -54,6 +54,7 @@
art/src
art_cflags := \
+ -fno-rtti \
-O2 \
-ggdb3 \
-Wall \
diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc
index 733fdc9..d74c33f 100644
--- a/src/compiler/dex/quick/gen_invoke.cc
+++ b/src/compiler/dex/quick/gen_invoke.cc
@@ -1225,9 +1225,9 @@
* method. By doing this during basic block construction, we can also
* take advantage of/generate new useful dataflow info.
*/
- const char* tgt_methods_declaring_class =
- cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index));
- if (strstr(tgt_methods_declaring_class, "Ljava/lang") != NULL) {
+ StringPiece tgt_methods_declaring_class(
+ cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index)));
+ if (tgt_methods_declaring_class.starts_with("Ljava/lang/Double;")) {
std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
return GenInlinedDoubleCvt(info);
@@ -1235,12 +1235,17 @@
if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
return GenInlinedDoubleCvt(info);
}
+ } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Float;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "int java.lang.Float.float_to_raw_int_bits(float)") {
return GenInlinedFloatCvt(info);
}
if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
return GenInlinedFloatCvt(info);
}
+ } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Math;") ||
+ tgt_methods_declaring_class.starts_with("Ljava/lang/StrictMath;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "int java.lang.Math.abs(int)" ||
tgt_method == "int java.lang.StrictMath.abs(int)") {
return GenInlinedAbsInt(info);
@@ -1261,6 +1266,8 @@
tgt_method == "double java.lang.StrictMath.sqrt(double)") {
return GenInlinedSqrt(info);
}
+ } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/String;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "char java.lang.String.charAt(int)") {
return GenInlinedCharAt(info);
}
@@ -1279,10 +1286,12 @@
if (tgt_method == "int java.lang.String.length()") {
return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
}
+ } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Thread;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
return GenInlinedCurrentThread(info);
}
- } else if (strstr(tgt_methods_declaring_class, "Lsun/misc/Unsafe;") != NULL) {
+ } else if (tgt_methods_declaring_class.starts_with("Lsun/misc/Unsafe;")) {
std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
return GenInlinedCas32(info, false);
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 6feda17..aad77ad 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -752,9 +752,8 @@
}
// Search dex file for localized ssb index, may fail if field's class is a parent
// of the class mentioned in the dex file and there is no dex cache entry.
- std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
const DexFile::StringId* string_id =
- mUnit->GetDexFile()->FindStringId(descriptor);
+ mUnit->GetDexFile()->FindStringId(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
if (string_id != NULL) {
const DexFile::TypeId* type_id =
mUnit->GetDexFile()->FindTypeId(mUnit->GetDexFile()->GetIndexForStringId(*string_id));
diff --git a/src/dex_file.cc b/src/dex_file.cc
index a8fb0e0..dad083c 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -436,7 +436,7 @@
return NULL;
}
-const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
+const DexFile::StringId* DexFile::FindStringId(const char* string) const {
int32_t lo = 0;
int32_t hi = NumStringIds() - 1;
while (hi >= lo) {
@@ -444,7 +444,27 @@
uint32_t length;
const DexFile::StringId& str_id = GetStringId(mid);
const char* str = GetStringDataAndLength(str_id, &length);
- int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
+ int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
+ if (compare > 0) {
+ lo = mid + 1;
+ } else if (compare < 0) {
+ hi = mid - 1;
+ } else {
+ return &str_id;
+ }
+ }
+ return NULL;
+}
+
+const DexFile::StringId* DexFile::FindStringId(const uint16_t* string) const {
+ int32_t lo = 0;
+ int32_t hi = NumStringIds() - 1;
+ while (hi >= lo) {
+ int32_t mid = (hi + lo) / 2;
+ uint32_t length;
+ const DexFile::StringId& str_id = GetStringId(mid);
+ const char* str = GetStringDataAndLength(str_id, &length);
+ int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string);
if (compare > 0) {
lo = mid + 1;
} else if (compare < 0) {
@@ -544,7 +564,7 @@
descriptor += c;
} while (c != ';');
}
- const DexFile::StringId* string_id = FindStringId(descriptor);
+ const DexFile::StringId* string_id = FindStringId(descriptor.c_str());
if (string_id == NULL) {
return false;
}
diff --git a/src/dex_file.h b/src/dex_file.h
index 6e34b57..ecc985f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -436,8 +436,11 @@
return StringDataAndLengthByIdx(idx, &unicode_length);
}
- // Looks up a string id for a given string
- const StringId* FindStringId(const std::string& string) const;
+ // Looks up a string id for a given modified utf8 string.
+ const StringId* FindStringId(const char* string) const;
+
+ // Looks up a string id for a given utf16 string.
+ const StringId* FindStringId(const uint16_t* string) const;
// Returns the number of type identifiers in the .dex file.
size_t NumTypeIds() const {
@@ -974,7 +977,7 @@
bool HasNext() const {
return pos_ < EndOfVirtualMethodsPos();
}
- void Next() {
+ inline void Next() {
pos_++;
if (pos_ < EndOfStaticFieldsPos()) {
last_idx_ = GetMemberIndex();
diff --git a/src/image_writer.cc b/src/image_writer.cc
index bda0138..faa13f7 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -168,13 +168,13 @@
return;
}
String* string = obj->AsString();
- std::string utf8_string(string->ToModifiedUtf8());
+ const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset();
ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
typedef Set::const_iterator CacheIt; // TODO: C++0x auto
for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) {
DexCache* dex_cache = *it;
const DexFile& dex_file = *dex_cache->GetDexFile();
- const DexFile::StringId* string_id = dex_file.FindStringId(utf8_string);
+ const DexFile::StringId* string_id = dex_file.FindStringId(utf16_string);
if (string_id != NULL) {
// This string occurs in this dex file, assign the dex cache entry.
uint32_t string_idx = dex_file.GetIndexForStringId(*string_id);
diff --git a/src/utf.cc b/src/utf.cc
index 8d3547e..1add7d9 100644
--- a/src/utf.cc
+++ b/src/utf.cc
@@ -119,6 +119,23 @@
}
}
+int CompareModifiedUtf8ToUtf16AsCodePointValues(const char* utf8_1, const uint16_t* utf8_2) {
+ for (;;) {
+ if (*utf8_1 == '\0') {
+ return (*utf8_2 == '\0') ? 0 : -1;
+ } else if (*utf8_2 == '\0') {
+ return 1;
+ }
+
+ int c1 = GetUtf16FromUtf8(&utf8_1);
+ int c2 = *utf8_2;
+
+ if (c1 != c2) {
+ return c1 > c2 ? 1 : -1;
+ }
+ }
+}
+
size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count) {
size_t result = 0;
while (char_count--) {
diff --git a/src/utf.h b/src/utf.h
index 44899bf..57c811f 100644
--- a/src/utf.h
+++ b/src/utf.h
@@ -56,6 +56,12 @@
int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2);
/*
+ * Compare a modified UTF-8 string with a UTF-16 string as code point values in a non-locale
+ * sensitive manner.
+ */
+int CompareModifiedUtf8ToUtf16AsCodePointValues(const char* utf8_1, const uint16_t* utf8_2);
+
+/*
* Convert from UTF-16 to Modified UTF-8. Note that the output is _not_
* NUL-terminated. You probably need to call CountUtf8Bytes before calling
* this anyway, so if you want a NUL-terminated string, you know where to
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index ce65829..fc285bc 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -19,6 +19,7 @@
#include <iostream>
#include "base/logging.h"
+#include "base/mutex-inl.h"
#include "base/stringpiece.h"
#include "class_linker.h"
#include "compiler/driver/compiler_driver.h"
@@ -267,13 +268,14 @@
: reg_types_(can_load_classes),
work_insn_idx_(-1),
dex_method_idx_(dex_method_idx),
- foo_method_(method),
+ mirror_method_(method),
method_access_flags_(method_access_flags),
dex_file_(dex_file),
dex_cache_(dex_cache),
class_loader_(class_loader),
class_def_idx_(class_def_idx),
code_item_(code_item),
+ declaring_class_(NULL),
interesting_dex_pc_(-1),
monitor_enter_dex_pcs_(NULL),
have_pending_hard_failure_(false),
@@ -896,6 +898,7 @@
static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vector<uint8_t>& gc_map) {
std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
+ length_prefixed_gc_map->reserve(gc_map.size() + 4);
length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
length_prefixed_gc_map->push_back((gc_map.size() & 0x0000ff00) >> 8);
@@ -2542,7 +2545,7 @@
const RegType& referrer = GetDeclaringClass();
mirror::Class* klass = dex_cache_->GetResolvedType(class_idx);
const RegType& result =
- klass != NULL ? reg_types_.FromClass(klass, klass->IsFinal())
+ klass != NULL ? reg_types_.FromClass(descriptor, klass, klass->IsFinal())
: reg_types_.FromDescriptor(class_loader_, descriptor, false);
if (result.IsConflict()) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
@@ -2756,7 +2759,8 @@
}
if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
- const RegType& res_method_class = reg_types_.FromClass(klass, klass->IsFinal());
+ const RegType& res_method_class = reg_types_.FromClass(ClassHelper(klass).GetDescriptor(),
+ klass, klass->IsFinal());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
<< "' not instance of '" << res_method_class << "'";
@@ -2935,7 +2939,7 @@
mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx,
dex_cache_, class_loader_);
if (field == NULL) {
- LOG(INFO) << "unable to resolve static field " << field_idx << " ("
+ LOG(INFO) << "Unable to resolve static field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
<< dex_file_->GetFieldDeclaringClassDescriptor(field_id);
DCHECK(Thread::Current()->IsExceptionPending());
@@ -2970,7 +2974,7 @@
mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx,
dex_cache_, class_loader_);
if (field == NULL) {
- LOG(INFO) << "unable to resolve instance field " << field_idx << " ("
+ LOG(INFO) << "Unable to resolve instance field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
<< dex_file_->GetFieldDeclaringClassDescriptor(field_id);
DCHECK(Thread::Current()->IsExceptionPending());
@@ -2990,7 +2994,9 @@
return field;
} else {
mirror::Class* klass = field->GetDeclaringClass();
- const RegType& field_klass = reg_types_.FromClass(klass, klass->IsFinal());
+ const RegType& field_klass =
+ reg_types_.FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
+ klass, klass->IsFinal());
if (obj_type.IsUninitializedTypes() &&
(!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
!field_klass.Equals(GetDeclaringClass()))) {
@@ -3198,14 +3204,17 @@
}
const RegType& MethodVerifier::GetDeclaringClass() {
- if (foo_method_ != NULL) {
- mirror::Class* klass = foo_method_->GetDeclaringClass();
- return reg_types_.FromClass(klass, klass->IsFinal());
- } else {
+ if (declaring_class_ == NULL) {
const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
- return reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ if (mirror_method_ != NULL) {
+ mirror::Class* klass = mirror_method_->GetDeclaringClass();
+ declaring_class_ = ®_types_.FromClass(descriptor, klass, klass->IsFinal());
+ } else {
+ declaring_class_ = ®_types_.FromDescriptor(class_loader_, descriptor, false);
+ }
}
+ return *declaring_class_;
}
void MethodVerifier::ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits,
@@ -3396,9 +3405,10 @@
}
}
-void MethodVerifier::SetDexGcMap(CompilerDriver::MethodReference ref, const std::vector<uint8_t>& gc_map) {
+void MethodVerifier::SetDexGcMap(CompilerDriver::MethodReference ref,
+ const std::vector<uint8_t>& gc_map) {
{
- MutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
+ WriterMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
DexGcMapTable::iterator it = dex_gc_maps_->find(ref);
if (it != dex_gc_maps_->end()) {
delete it->second;
@@ -3409,9 +3419,20 @@
DCHECK(GetDexGcMap(ref) != NULL);
}
-void MethodVerifier::SetDevirtMap(CompilerDriver::MethodReference ref, const PcToConcreteMethod* devirt_map) {
+const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(CompilerDriver::MethodReference ref) {
+ ReaderMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
+ DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
+ if (it == dex_gc_maps_->end()) {
+ LOG(WARNING) << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
+ return NULL;
+ }
+ CHECK(it->second != NULL);
+ return it->second;
+}
- MutexLock mu(Thread::Current(), *devirt_maps_lock_);
+void MethodVerifier::SetDevirtMap(CompilerDriver::MethodReference ref,
+ const PcToConcreteMethod* devirt_map) {
+ WriterMutexLock mu(Thread::Current(), *devirt_maps_lock_);
DevirtualizationMapTable::iterator it = devirt_maps_->find(ref);
if (it != devirt_maps_->end()) {
delete it->second;
@@ -3422,20 +3443,9 @@
CHECK(devirt_maps_->find(ref) != devirt_maps_->end());
}
-const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(CompilerDriver::MethodReference ref) {
- MutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
- DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
- if (it == dex_gc_maps_->end()) {
- LOG(WARNING) << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
- return NULL;
- }
- CHECK(it->second != NULL);
- return it->second;
-}
-
const CompilerDriver::MethodReference* MethodVerifier::GetDevirtMap(const CompilerDriver::MethodReference& ref,
uint32_t dex_pc) {
- MutexLock mu(Thread::Current(), *devirt_maps_lock_);
+ ReaderMutexLock mu(Thread::Current(), *devirt_maps_lock_);
DevirtualizationMapTable::const_iterator it = devirt_maps_->find(ref);
if (it == devirt_maps_->end()) {
return NULL;
@@ -3494,26 +3504,26 @@
return result;
}
-Mutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
+ReaderWriterMutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
MethodVerifier::DexGcMapTable* MethodVerifier::dex_gc_maps_ = NULL;
-Mutex* MethodVerifier::devirt_maps_lock_ = NULL;
+ReaderWriterMutex* MethodVerifier::devirt_maps_lock_ = NULL;
MethodVerifier::DevirtualizationMapTable* MethodVerifier::devirt_maps_ = NULL;
Mutex* MethodVerifier::rejected_classes_lock_ = NULL;
MethodVerifier::RejectedClassesTable* MethodVerifier::rejected_classes_ = NULL;
void MethodVerifier::Init() {
- dex_gc_maps_lock_ = new Mutex("verifier GC maps lock");
+ dex_gc_maps_lock_ = new ReaderWriterMutex("verifier GC maps lock");
Thread* self = Thread::Current();
{
- MutexLock mu(self, *dex_gc_maps_lock_);
+ WriterMutexLock mu(self, *dex_gc_maps_lock_);
dex_gc_maps_ = new MethodVerifier::DexGcMapTable;
}
- devirt_maps_lock_ = new Mutex("verifier Devirtualization lock");
+ devirt_maps_lock_ = new ReaderWriterMutex("verifier Devirtualization lock");
{
- MutexLock mu(self, *devirt_maps_lock_);
+ WriterMutexLock mu(self, *devirt_maps_lock_);
devirt_maps_ = new MethodVerifier::DevirtualizationMapTable();
}
@@ -3528,7 +3538,7 @@
void MethodVerifier::Shutdown() {
Thread* self = Thread::Current();
{
- MutexLock mu(self, *dex_gc_maps_lock_);
+ WriterMutexLock mu(self, *dex_gc_maps_lock_);
STLDeleteValues(dex_gc_maps_);
delete dex_gc_maps_;
dex_gc_maps_ = NULL;
@@ -3537,7 +3547,7 @@
dex_gc_maps_lock_ = NULL;
{
- MutexLock mu(self, *devirt_maps_lock_);
+ WriterMutexLock mu(self, *devirt_maps_lock_);
STLDeleteValues(devirt_maps_);
delete devirt_maps_;
devirt_maps_ = NULL;
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index 9b4b8e5..75f94ea 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -577,7 +577,7 @@
// All the GC maps that the verifier has created
typedef SafeMap<const CompilerDriver::MethodReference, const std::vector<uint8_t>*,
CompilerDriver::MethodReferenceComparator> DexGcMapTable;
- static Mutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ static ReaderWriterMutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static DexGcMapTable* dex_gc_maps_ GUARDED_BY(dex_gc_maps_lock_);
static void SetDexGcMap(CompilerDriver::MethodReference ref, const std::vector<uint8_t>& dex_gc_map)
LOCKS_EXCLUDED(dex_gc_maps_lock_);
@@ -590,7 +590,7 @@
MethodVerifier::PcToConcreteMethod* GenerateDevirtMap()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static Mutex* devirt_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ static ReaderWriterMutex* devirt_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static DevirtualizationMapTable* devirt_maps_ GUARDED_BY(devirt_maps_lock_);
static void SetDevirtMap(CompilerDriver::MethodReference ref,
const PcToConcreteMethod* pc_method_map)
@@ -616,20 +616,20 @@
// Storage for the register status we're saving for later.
UniquePtr<RegisterLine> saved_line_;
- uint32_t dex_method_idx_; // The method we're working on.
+ const uint32_t dex_method_idx_; // The method we're working on.
// Its object representation if known.
- mirror::AbstractMethod* foo_method_ GUARDED_BY(Locks::mutator_lock_);
- uint32_t method_access_flags_; // Method's access flags.
- const DexFile* dex_file_; // The dex file containing the method.
+ mirror::AbstractMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_);
+ const uint32_t method_access_flags_; // Method's access flags.
+ const DexFile* const dex_file_; // The dex file containing the method.
// The dex_cache for the declaring class of the method.
mirror::DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_);
// The class loader for the declaring class of the method.
mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_);
- uint32_t class_def_idx_; // The class def index of the declaring class of the method.
- const DexFile::CodeItem* code_item_; // The code item containing the code for the method.
+ const uint32_t class_def_idx_; // The class def index of the declaring class of the method.
+ const DexFile::CodeItem* const code_item_; // The code item containing the code for the method.
+ const RegType* declaring_class_; // Lazily computed reg type of the method's declaring class.
// Instruction widths and flags, one entry per code unit.
UniquePtr<InstructionFlags[]> insn_flags_;
-
// The dex PC of a FindLocksAtDexPc request, -1 otherwise.
uint32_t interesting_dex_pc_;
// The container into which FindLocksAtDexPc should write the registers containing held locks,
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
index 5db6aff..e738e80 100644
--- a/src/verifier/reg_type.cc
+++ b/src/verifier/reg_type.cc
@@ -25,6 +25,7 @@
#include "mirror/object_array-inl.h"
#include "object_utils.h"
#include "reg_type_cache-inl.h"
+#include "scoped_thread_state_change.h"
#include <limits>
#include <sstream>
@@ -45,6 +46,41 @@
DoubleHiType* DoubleHiType::instance_ = NULL;
IntegerType* IntegerType::instance_ = NULL;
+int32_t RegType::ConstantValue() const {
+ ScopedObjectAccess soa(Thread::Current());
+ LOG(FATAL) << "Unexpected call to ConstantValue: " << *this;
+ return 0;
+}
+
+int32_t RegType::ConstantValueLo() const {
+ ScopedObjectAccess soa(Thread::Current());
+ LOG(FATAL) << "Unexpected call to ConstantValueLo: " << *this;
+ return 0;
+}
+
+int32_t RegType::ConstantValueHi() const {
+ ScopedObjectAccess soa(Thread::Current());
+ LOG(FATAL) << "Unexpected call to ConstantValueHi: " << *this;
+ return 0;
+}
+
+PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : RegType(klass, descriptor, cache_id) {
+ CHECK(klass != NULL);
+ CHECK(!descriptor.empty());
+}
+
+Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : PrimitiveType(klass, descriptor, cache_id) {
+}
+
+Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : PrimitiveType(klass, descriptor, cache_id) {
+}
+
std::string PreciseConstType::Dump() const {
std::stringstream result;
uint32_t val = ConstantValue();
@@ -349,6 +385,12 @@
}
}
+PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
+ uint16_t cache_id)
+ : RegType(klass, descriptor, cache_id) {
+ DCHECK(klass->IsInstantiable());
+}
+
std::string UnresolvedMergedType::Dump() const {
std::stringstream result;
std::set<uint16_t> types = GetMergedTypes();
@@ -486,80 +528,10 @@
return result.str();
}
-BooleanType::BooleanType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-ConflictType::ConflictType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-ByteType::ByteType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-ShortType::ShortType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-CharType::CharType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-IntegerType::IntegerType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
ConstantType::ConstantType(uint32_t constant, uint16_t cache_id)
: RegType(NULL, "", cache_id), constant_(constant) {
}
-ReferenceType::ReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
- uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
- DCHECK(klass->IsInstantiable());
-}
-
-UnresolvedUninitializedThisRefType::UnresolvedUninitializedThisRefType(const std::string& descriptor,
- uint16_t cache_id)
- : UninitializedType(NULL, descriptor, 0, cache_id) {
-}
-
-UnresolvedUninitializedRefType::UnresolvedUninitializedRefType(const std::string& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
- : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
-}
-
-UninitializedReferenceType::UninitializedReferenceType(mirror::Class* klass,
- const std::string& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
- : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
-}
-
-LongHiType::LongHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-FloatType::FloatType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-DoubleLoType::DoubleLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-DoubleHiType::DoubleHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
-LongLoType::LongLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id) {
-}
-
const RegType& UndefinedType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (incoming_type.IsUndefined()) {
@@ -603,6 +575,17 @@
}
}
+bool UninitializedType::IsUninitializedTypes() const {
+ return true;
+}
+
+bool UninitializedType::IsNonZeroReferenceTypes() const {
+ return true;
+}
+
+bool UnresolvedType::IsNonZeroReferenceTypes() const {
+ return true;
+}
std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
const RegType& _left(reg_type_cache_->GetFromId(refs.first));
@@ -640,7 +623,7 @@
if (super_klass != NULL) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
- return cache->FromClass(super_klass, false);
+ return cache->FromClass(ClassHelper(super_klass).GetDescriptor(), super_klass, false);
} else {
return cache->Zero();
}
@@ -915,7 +898,7 @@
} else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
- return reg_types->FromClass(join_class, false);
+ return reg_types->FromClass(ClassHelper(join_class).GetDescriptor(), join_class, false);
}
}
} else {
@@ -980,33 +963,22 @@
CHECK(descriptor_.empty()) << *this;
CHECK(klass_ == NULL) << *this;
}
-}
-
-UninitializedType::UninitializedType(mirror::Class* klass, const std::string& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
- : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
-}
-
-void UninitializedType::CheckInvariants() const {
- CHECK_EQ(allocation_pc_, 0U) << *this;
+ if (klass_ != NULL) {
+ CHECK(!descriptor_.empty()) << *this;
+ }
}
void UninitializedThisReferenceType::CheckInvariants() const {
- UninitializedType::CheckInvariants();
-}
-
-UninitializedThisReferenceType::UninitializedThisReferenceType(mirror::Class* klass,
- const std::string& descriptor, uint16_t cache_id) : UninitializedType(klass, descriptor, 0, cache_id) {
+ CHECK_EQ(GetAllocationPc(), 0U) << *this;
}
void UnresolvedUninitializedThisRefType::CheckInvariants() const {
- UninitializedType::CheckInvariants();
+ CHECK_EQ(GetAllocationPc(), 0U) << *this;
CHECK(!descriptor_.empty()) << *this;
CHECK(klass_ == NULL) << *this;
}
void UnresolvedUninitializedRefType::CheckInvariants() const {
- UninitializedType::CheckInvariants();
CHECK(!descriptor_.empty()) << *this;
CHECK(klass_ == NULL) << *this;
}
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
index 39c33c6..424b071 100644
--- a/src/verifier/reg_type.h
+++ b/src/verifier/reg_type.h
@@ -18,6 +18,7 @@
#define ART_SRC_VERIFIER_REG_TYPE_H_
#include "base/macros.h"
+#include "globals.h"
#include "primitive.h"
#include "jni.h"
@@ -39,105 +40,43 @@
*/
class RegType {
public:
- // The high half that corresponds to this low half
- const RegType& HighHalf(RegTypeCache* cache) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- inline virtual bool IsUndefined() const {
- return false;
- }
- inline virtual bool IsConflict() const {
- return false;
- }
- inline virtual bool IsBoolean() const {
- return false;
- }
- inline virtual bool IsByte() const {
- return false;
- }
- inline virtual bool IsChar() const {
- return false;
- }
- inline virtual bool IsShort() const {
- return false;
- }
- inline virtual bool IsInteger() const {
- return false;
- }
- inline virtual bool IsLongLo() const {
- return false;
- }
- inline virtual bool IsLongHi() const {
- return false;
- }
- inline virtual bool IsFloat() const {
- return false;
- }
- inline virtual bool IsDouble() const {
- return false;
- }
- inline virtual bool IsDoubleLo() const {
- return false;
- }
- inline virtual bool IsDoubleHi() const {
- return false;
- }
- inline virtual bool IsUnresolvedReference() const {
- return false;
- }
- inline virtual bool IsUninitializedReference() const {
- return false;
- }
- inline virtual bool IsUninitializedThisReference() const {
- return false;
- }
- inline virtual bool IsUnresolvedAndUninitializedReference() const {
- return false;
- }
- inline virtual bool IsUnresolvedAndUninitializedThisReference() const {
- return false;
- }
- inline virtual bool IsUnresolvedMergedReference() const {
- return false;
- }
- inline virtual bool IsUnresolvedSuperClass() const {
- return false;
- }
- inline virtual bool IsReference() const {
- return false;
- }
- inline virtual bool IsPreciseReference() const {
- return false;
- }
- inline virtual bool IsPreciseConstant() const {
- return false;
- }
- inline virtual bool IsPreciseConstantLo() const {
- return false;
- }
- inline virtual bool IsPreciseConstantHi() const {
- return false;
- }
- inline virtual bool IsImpreciseConstantLo() const {
- return false;
- }
- inline virtual bool IsImpreciseConstantHi() const {
- return false;
- }
- virtual bool IsImpreciseConstant() const {
- return false;
- }
-
- inline virtual bool IsConstantTypes() const {
- return false;
- }
+ virtual bool IsUndefined() const { return false; }
+ virtual bool IsConflict() const { return false; }
+ virtual bool IsBoolean() const { return false; }
+ virtual bool IsByte() const { return false; }
+ virtual bool IsChar() const { return false; }
+ virtual bool IsShort() const { return false; }
+ virtual bool IsInteger() const { return false; }
+ virtual bool IsLongLo() const { return false; }
+ virtual bool IsLongHi() const { return false; }
+ virtual bool IsFloat() const { return false; }
+ virtual bool IsDouble() const { return false; }
+ virtual bool IsDoubleLo() const { return false; }
+ virtual bool IsDoubleHi() const { return false; }
+ virtual bool IsUnresolvedReference() const { return false; }
+ virtual bool IsUninitializedReference() const { return false; }
+ virtual bool IsUninitializedThisReference() const { return false; }
+ virtual bool IsUnresolvedAndUninitializedReference() const { return false; }
+ virtual bool IsUnresolvedAndUninitializedThisReference() const { return false; }
+ virtual bool IsUnresolvedMergedReference() const { return false; }
+ virtual bool IsUnresolvedSuperClass() const { return false; }
+ virtual bool IsReference() const { return false; }
+ virtual bool IsPreciseReference() const { return false; }
+ virtual bool IsPreciseConstant() const { return false; }
+ virtual bool IsPreciseConstantLo() const { return false; }
+ virtual bool IsPreciseConstantHi() const { return false; }
+ virtual bool IsImpreciseConstantLo() const { return false; }
+ virtual bool IsImpreciseConstantHi() const { return false; }
+ virtual bool IsImpreciseConstant() const { return false; }
+ virtual bool IsConstantTypes() const { return false; }
bool IsConstant() const {
- return (IsPreciseConstant() || IsImpreciseConstant());
+ return IsPreciseConstant() || IsImpreciseConstant();
}
bool IsConstantLo() const {
- return (IsPreciseConstantLo() || IsImpreciseConstantLo());
+ return IsPreciseConstantLo() || IsImpreciseConstantLo();
}
bool IsPrecise() const {
- return (IsPreciseConstantLo() || IsPreciseConstant() ||
- IsPreciseConstantHi());
+ return IsPreciseConstantLo() || IsPreciseConstant() || IsPreciseConstantHi();
}
bool IsLongConstant() const {
return IsConstantLo();
@@ -148,11 +87,7 @@
bool IsLongConstantHigh() const {
return IsConstantHi();
}
- bool IsUninitializedTypes() const {
- return IsUninitializedReference() || IsUninitializedThisReference() ||
- IsUnresolvedAndUninitializedReference() ||
- IsUnresolvedAndUninitializedThisReference();
- }
+ virtual bool IsUninitializedTypes() const { return false; }
bool IsUnresolvedTypes() const {
return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
IsUnresolvedAndUninitializedThisReference() ||
@@ -170,7 +105,7 @@
bool IsLongOrDoubleTypes() const {
return IsLowHalf();
}
- // Check this is the low half, and that type_h is its matching high-half
+ // Check this is the low half, and that type_h is its matching high-half.
inline bool CheckWidePair(const RegType& type_h) const {
if (IsLowHalf()) {
return ((IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
@@ -182,37 +117,36 @@
}
return false;
}
+ // The high half that corresponds to this low half
+ const RegType& HighHalf(RegTypeCache* cache) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
bool IsConstantBoolean() const {
return IsConstant() && (ConstantValue() >= 0) && (ConstantValue() <= 1);
}
- inline virtual bool IsConstantChar() const {
+ virtual bool IsConstantChar() const {
return false;
}
- inline virtual bool IsConstantByte() const {
+ virtual bool IsConstantByte() const {
return false;
}
- inline virtual bool IsConstantShort() const {
+ virtual bool IsConstantShort() const {
return false;
}
- inline virtual bool IsOne() const {
+ virtual bool IsOne() const {
return false;
}
- inline virtual bool IsZero() const {
+ virtual bool IsZero() const {
return false;
}
bool IsReferenceTypes() const {
return IsNonZeroReferenceTypes() || IsZero();
}
- bool IsNonZeroReferenceTypes() const {
- return IsReference() || IsPreciseReference() ||
- IsUninitializedReference() || IsUninitializedThisReference() ||
- IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
- IsUnresolvedAndUninitializedThisReference() ||
- IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
+ virtual bool IsNonZeroReferenceTypes() const {
+ return false;
}
bool IsCategory1Types() const {
- return (IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() ||
- IsShort() || IsBoolean() );
+ return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || IsShort() ||
+ IsBoolean();
}
bool IsCategory2Types() const {
return IsLowHalf(); // Don't expect explicit testing of high halves
@@ -230,20 +164,12 @@
return IsChar() || IsBooleanTypes() || IsConstantChar();
}
bool IsIntegralTypes() const {
- return (IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || IsBoolean() );
+ return IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || IsBoolean();
}
- inline virtual int32_t ConstantValue() const {
- DCHECK(IsConstant());
- return -1;
- }
- inline virtual int32_t ConstantValueLo() const {
- DCHECK(IsConstantLo());
- return -1;
- }
- inline virtual int32_t ConstantValueHi() const {
- DCHECK(IsConstantHi());
- return -1;
- }
+ // Give the constant value encoded, but this shouldn't be called in the general case.
+ virtual int32_t ConstantValue() const;
+ virtual int32_t ConstantValueLo() const;
+ virtual int32_t ConstantValueHi() const;
bool IsArrayIndexTypes() const {
return IsIntegralTypes();
}
@@ -265,7 +191,7 @@
bool IsDoubleHighTypes() const {
return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
}
- inline virtual bool IsLong() const {
+ virtual bool IsLong() const {
return false;
}
virtual bool HasClass() const {
@@ -278,34 +204,43 @@
bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsInstantiableTypes() const;
const std::string& GetDescriptor() const {
- DCHECK(IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass());
+ DCHECK(HasClass() || (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
+ !IsUnresolvedSuperClass()));
return descriptor_;
}
- uint16_t GetId() const {
- return cache_id_;
- }
- const RegType& GetSuperClass(RegTypeCache* cache) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- virtual std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
- // Can this type access other?
- bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Can this type access a member with the given properties?
- bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Can this type be assigned by src?
- bool IsAssignableFrom(const RegType& src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Equals(const RegType& other) const {
- return GetId() == other.GetId();
- }
- // Compute the merge of this register from one edge (path) with incoming_type from another.
- virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* GetClass() const {
DCHECK(!IsUnresolvedReference());
DCHECK(klass_ != NULL);
DCHECK(HasClass());
return klass_;
}
+ uint16_t GetId() const {
+ return cache_id_;
+ }
+ const RegType& GetSuperClass(RegTypeCache* cache) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ virtual std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+
+ // Can this type access other?
+ bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Can this type access a member with the given properties?
+ bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Can this type be assigned by src?
+ bool IsAssignableFrom(const RegType& src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Are these RegTypes the same?
+ bool Equals(const RegType& other) const {
+ return GetId() == other.GetId();
+ }
+
+ // Compute the merge of this register from one edge (path) with incoming_type from another.
+ virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
/*
* A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
* S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
@@ -325,62 +260,103 @@
static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ virtual ~RegType() {}
+
+ protected:
RegType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: descriptor_(descriptor), klass_(klass), cache_id_(cache_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
}
- inline virtual ~RegType() {
- }
- virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- friend class RegTypeCache;
- protected:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+
const std::string descriptor_;
- mirror::Class* klass_;
+ mirror::Class* const klass_;
const uint16_t cache_id_;
+ friend class RegTypeCache;
+
DISALLOW_COPY_AND_ASSIGN(RegType);
};
+// Bottom type.
class ConflictType : public RegType {
public:
bool IsConflict() const {
return true;
}
+
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Get the singleton Conflict instance.
+ static ConflictType* GetInstance();
+
+ // Create the singleton instance.
static ConflictType* CreateInstance(mirror::Class* klass, const std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static ConflictType* GetInstance();
+
+ // Destroy the singleton instance.
static void Destroy();
private:
ConflictType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : RegType(klass, descriptor, cache_id) {
+ }
+
static ConflictType* instance_;
};
+// A variant of the bottom type used to specify an undefined value in the incoming registers.
+// Merging with UndefinedType yields ConflictType which is the true bottom.
class UndefinedType : public RegType {
public:
bool IsUndefined() const {
return true;
}
+
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Get the singleton Undefined instance.
+ static UndefinedType* GetInstance();
+
+ // Create the singleton instance.
static UndefinedType* CreateInstance(mirror::Class* klass, const std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static UndefinedType* GetInstance();
+
+ // Destroy the singleton instance.
static void Destroy();
private:
UndefinedType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
}
+
virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static UndefinedType* instance_;
};
-class IntegerType : public RegType {
+class PrimitiveType : public RegType {
+ public:
+ PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class Cat1Type : public PrimitiveType {
+ public:
+ Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class IntegerType : public Cat1Type {
public:
bool IsInteger() const {
return true;
@@ -393,11 +369,13 @@
static void Destroy();
private:
IntegerType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
static IntegerType* instance_;
};
-class BooleanType : public RegType {
+class BooleanType : public Cat1Type {
public:
bool IsBoolean() const {
return true;
@@ -410,11 +388,14 @@
static void Destroy();
private:
BooleanType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
+
static BooleanType* instance;
};
-class ByteType : public RegType {
+class ByteType : public Cat1Type {
public:
bool IsByte() const {
return true;
@@ -427,11 +408,13 @@
static void Destroy();
private:
ByteType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
static ByteType* instance_;
};
-class ShortType : public RegType {
+class ShortType : public Cat1Type {
public:
bool IsShort() const {
return true;
@@ -444,11 +427,13 @@
static void Destroy();
private:
ShortType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
static ShortType* instance_;
};
-class CharType : public RegType {
+class CharType : public Cat1Type {
public:
bool IsChar() const {
return true;
@@ -461,11 +446,13 @@
static void Destroy();
private:
CharType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
static CharType* instance_;
};
-class FloatType : public RegType {
+class FloatType : public Cat1Type {
public:
bool IsFloat() const {
return true;
@@ -478,11 +465,19 @@
static void Destroy();
private:
FloatType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat1Type(klass, descriptor, cache_id) {
+ }
static FloatType* instance_;
};
-class LongLoType : public RegType {
+class Cat2Type : public PrimitiveType {
+ public:
+ Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class LongLoType : public Cat2Type {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsLongLo() const {
@@ -498,11 +493,13 @@
static void Destroy();
private:
LongLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat2Type(klass, descriptor, cache_id) {
+ }
static LongLoType* instance_;
};
-class LongHiType : public RegType {
+class LongHiType : public Cat2Type {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsLongHi() const {
@@ -515,11 +512,13 @@
static void Destroy();
private:
LongHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat2Type(klass, descriptor, cache_id) {
+ }
static LongHiType* instance_;
};
-class DoubleLoType : public RegType {
+class DoubleLoType : public Cat2Type {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsDoubleLo() const {
@@ -535,11 +534,13 @@
static void Destroy();
private:
DoubleLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat2Type(klass, descriptor, cache_id) {
+ }
static DoubleLoType* instance_;
};
-class DoubleHiType : public RegType {
+class DoubleHiType : public Cat2Type {
public:
std::string Dump() const;
virtual bool IsDoubleHi() const {
@@ -552,7 +553,9 @@
static void Destroy();
private:
DoubleHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : Cat2Type(klass, descriptor, cache_id) {
+ }
static DoubleHiType* instance_;
};
@@ -560,9 +563,6 @@
public:
ConstantType(uint32_t constat, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- inline virtual ~ConstantType() {
- }
- const uint32_t constant_;
// If this is a 32-bit constant, what is the value? This value may be imprecise in which case
// the value represents part of the integer range of values that may be held in the register.
virtual int32_t ConstantValue() const;
@@ -590,7 +590,10 @@
ConstantValue() >= std::numeric_limits<jshort>::min() &&
ConstantValue() <= std::numeric_limits<jshort>::max();
}
- inline virtual bool IsConstantTypes() const { return true; }
+ virtual bool IsConstantTypes() const { return true; }
+
+ private:
+ const uint32_t constant_;
};
class PreciseConstType : public ConstantType {
@@ -662,159 +665,254 @@
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
+// Common parent of all uninitialized types. Uninitialized types are created by "new" dex
+// instructions and must be passed to a constructor.
class UninitializedType : public RegType {
public:
UninitializedType(mirror::Class* klass, const std::string& descriptor, uint32_t allocation_pc,
- uint16_t cache_id);
- inline virtual ~UninitializedType() {
+ uint16_t cache_id)
+ : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
}
+ bool IsUninitializedTypes() const;
+ bool IsNonZeroReferenceTypes() const;
+
uint32_t GetAllocationPc() const {
DCHECK(IsUninitializedTypes());
return allocation_pc_;
}
- virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
const uint32_t allocation_pc_;
};
+// Similar to ReferenceType but not yet having been passed to a constructor.
class UninitializedReferenceType : public UninitializedType {
public:
- UninitializedReferenceType(mirror::Class* klass, const std::string& descriptor, uint32_t allocation_pc,
- uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ UninitializedReferenceType(mirror::Class* klass, const std::string& descriptor,
+ uint32_t allocation_pc, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
+ }
bool IsUninitializedReference() const {
return true;
}
+
bool HasClass() const {
return true;
}
+
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
+// Similar to UnresolvedReferenceType but not yet having been passed to a constructor.
class UnresolvedUninitializedRefType : public UninitializedType {
public:
UnresolvedUninitializedRefType(const std::string& descriptor, uint32_t allocation_pc,
- uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
+ }
+
bool IsUnresolvedAndUninitializedReference() const {
return true;
}
+
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
+// Similar to UninitializedReferenceType but special case for the this argument of a constructor.
class UninitializedThisReferenceType : public UninitializedType {
public:
- UninitializedThisReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ UninitializedThisReferenceType(mirror::Class* klass, const std::string& descriptor,
+ uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : UninitializedType(klass, descriptor, 0, cache_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
+ }
+
virtual bool IsUninitializedThisReference() const {
return true;
}
+
bool HasClass() const {
return true;
}
+
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class UnresolvedUninitializedThisRefType : public UninitializedType {
public:
UnresolvedUninitializedThisRefType(const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : UninitializedType(NULL, descriptor, 0, cache_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
+ }
+
bool IsUnresolvedAndUninitializedThisReference() const {
return true;
}
+
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
+// A type of register holding a reference to an Object of type GetClass or a sub-class.
class ReferenceType : public RegType {
public:
ReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : RegType(klass, descriptor, cache_id) {
+ }
+
bool IsReference() const {
return true;
}
+
+ bool IsNonZeroReferenceTypes() const {
+ return true;
+ }
+
bool HasClass() const {
return true;
}
+
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
+// A type of register holding a reference to an Object of type GetClass and only an object of that
+// type.
class PreciseReferenceType : public RegType {
public:
PreciseReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
bool IsPreciseReference() const {
return true;
}
+
+ bool IsNonZeroReferenceTypes() const {
+ return true;
+ }
+
bool HasClass() const {
return true;
}
+
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
-class UnresolvedReferenceType : public RegType {
+// Common parent of unresolved types.
+class UnresolvedType : public RegType {
+ public:
+ UnresolvedType(const std::string& descriptor, uint16_t cache_id)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : RegType(NULL, descriptor, cache_id) {
+ }
+
+ bool IsNonZeroReferenceTypes() const;
+};
+
+// Similar to ReferenceType except the Class couldn't be loaded. Assignability and other tests made
+// of this type must be conservative.
+class UnresolvedReferenceType : public UnresolvedType {
public:
UnresolvedReferenceType(const std::string& descriptor, uint16_t cache_id)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : RegType(NULL, descriptor, cache_id) {
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : UnresolvedType(descriptor, cache_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
}
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
bool IsUnresolvedReference() const {
return true;
}
+
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
-class UnresolvedSuperClass : public RegType {
+// Type representing the super-class of an unresolved type.
+class UnresolvedSuperClass : public UnresolvedType {
public:
UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : RegType(NULL, "", cache_id), unresolved_child_id_(child_id),
+ : UnresolvedType("", cache_id), unresolved_child_id_(child_id),
reg_type_cache_(reg_type_cache) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
}
+
bool IsUnresolvedSuperClass() const {
return true;
}
+
uint16_t GetUnresolvedSuperClassChildId() const {
DCHECK(IsUnresolvedSuperClass());
return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF);
}
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
const uint16_t unresolved_child_id_;
const RegTypeCache* const reg_type_cache_;
};
-class UnresolvedMergedType : public RegType {
+// A merge of two unresolved types. If the types were resolved this may be Conflict or another
+// known ReferenceType.
+class UnresolvedMergedType : public UnresolvedType {
public:
- UnresolvedMergedType(uint16_t left_id, uint16_t right_id, const RegTypeCache* reg_type_cache, uint16_t cache_id)
+ UnresolvedMergedType(uint16_t left_id, uint16_t right_id, const RegTypeCache* reg_type_cache,
+ uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : RegType(NULL, "", cache_id), reg_type_cache_(reg_type_cache) ,merged_types_(left_id, right_id) {
+ : UnresolvedType("", cache_id), reg_type_cache_(reg_type_cache) ,merged_types_(left_id, right_id) {
+ if (kIsDebugBuild) {
+ CheckInvariants();
+ }
}
+
// The top of a tree of merged types.
std::pair<uint16_t, uint16_t> GetTopMergedTypes() const {
DCHECK(IsUnresolvedMergedReference());
return merged_types_;
}
+
// The complete set of merged types.
std::set<uint16_t> GetMergedTypes() const;
+
bool IsUnresolvedMergedReference() const {
return true;
}
- void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
+ void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
const RegTypeCache* const reg_type_cache_;
const std::pair<uint16_t, uint16_t> merged_types_;
};
std::ostream& operator<<(std::ostream& os, const RegType& rhs)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
} // namespace verifier
} // namespace art
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 57a825b..a575f77 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -108,29 +108,14 @@
}
bool RegTypeCache::MatchDescriptor(size_t idx, const char* descriptor, bool precise) {
- RegType* cur_entry = entries_[idx];
- if (cur_entry->HasClass()) {
- // Check the descriptor in the reg_type if available.
- if(!cur_entry->descriptor_.empty()) {
- if (cur_entry->descriptor_ == descriptor && MatchingPrecisionForClass(cur_entry, precise)) {
- return true;
- }
- } else {
- // TODO: maintain an invariant that when we have a Class the descriptor is computed from that.
- // Descriptor not found in reg_type, maybe available in Class object.
- // So we might have cases where we have the class but not the descriptor
- // for that class we need the class helper to get the descriptor
- // and match it with the one we are given.
- ClassHelper kh(cur_entry->GetClass());
- if ((strcmp(descriptor, kh.GetDescriptor()) == 0) &&
- MatchingPrecisionForClass(cur_entry, precise)) {
- return true;
- }
- }
- } else if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
+ RegType* entry = entries_[idx];
+ if (entry->descriptor_ != descriptor) {
+ return false;
+ }
+ if (entry->HasClass() && MatchingPrecisionForClass(entry, precise)) {
return true;
}
- return false;
+ return entry->IsUnresolvedReference();
}
mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) {
@@ -206,24 +191,23 @@
}
}
-const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
+const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
if (klass->IsPrimitive()) {
return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
} else {
// Look for the reference in the list of entries to have.
for (size_t i = primitive_count_; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
- if ((cur_entry->HasClass()) && cur_entry->GetClass() == klass &&
- MatchingPrecisionForClass(cur_entry, precise)) {
+ if (cur_entry->klass_ == klass && MatchingPrecisionForClass(cur_entry, precise)) {
return *cur_entry;
}
}
// No reference to the class was found, create new reference.
RegType* entry;
if (precise) {
- entry = new PreciseReferenceType(klass, "", entries_.size());
+ entry = new PreciseReferenceType(klass, descriptor, entries_.size());
} else {
- entry = new ReferenceType(klass, "", entries_.size());
+ entry = new ReferenceType(klass, descriptor, entries_.size());
}
entries_.push_back(entry);
return *entry;
@@ -335,8 +319,8 @@
const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
RegType* entry = NULL;
RegType* cur_entry = NULL;
+ const std::string& descriptor(type.GetDescriptor());
if (type.IsUnresolvedTypes()) {
- const std::string& descriptor(type.GetDescriptor());
for (size_t i = primitive_count_; i < entries_.size(); i++) {
cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedReference() &&
@@ -345,7 +329,7 @@
return *cur_entry;
}
}
- entry = new UnresolvedUninitializedRefType(descriptor.c_str(), allocation_pc, entries_.size());
+ entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
} else {
mirror::Class* klass = type.GetClass();
for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -357,7 +341,7 @@
return *cur_entry;
}
}
- entry = new UninitializedReferenceType(klass, "", allocation_pc, entries_.size());
+ entry = new UninitializedReferenceType(klass, descriptor, allocation_pc, entries_.size());
}
entries_.push_back(entry);
return *entry;
@@ -432,8 +416,8 @@
const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
RegType* entry;
+ const std::string& descriptor(type.GetDescriptor());
if (type.IsUnresolvedTypes()) {
- const std::string& descriptor(type.GetDescriptor());
for (size_t i = primitive_count_; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
@@ -451,7 +435,7 @@
return *cur_entry;
}
}
- entry = new UninitializedThisReferenceType(klass, "", entries_.size());
+ entry = new UninitializedThisReferenceType(klass, descriptor, entries_.size());
}
entries_.push_back(entry);
return *entry;
@@ -460,7 +444,8 @@
const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
for (size_t i = primitive_count_; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
- if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
+ if (cur_entry->klass_ == NULL && cur_entry->IsConstant() &&
+ cur_entry->IsPreciseConstant() == precise &&
(down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
return *cur_entry;
}
@@ -519,7 +504,7 @@
return FromDescriptor(loader, component.c_str(), false);
} else {
mirror::Class* klass = array.GetClass()->GetComponentType();
- return FromClass(klass, klass->IsFinal());
+ return FromClass(ClassHelper(klass).GetDescriptor(), klass, klass->IsFinal());
}
}
diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h
index a5304db..d70123c 100644
--- a/src/verifier/reg_type_cache.h
+++ b/src/verifier/reg_type_cache.h
@@ -39,6 +39,7 @@
class RegTypeCache {
public:
explicit RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) {
+ entries_.reserve(64);
FillPrimitiveTypes();
}
~RegTypeCache();
@@ -58,7 +59,7 @@
static Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FillPrimitiveTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const RegType& FromClass(mirror::Class* klass, bool precise)
+ const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const RegType& FromCat1Const(int32_t value, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/verifier/reg_type_test.cc b/src/verifier/reg_type_test.cc
index 9b46a7f..f37edff 100644
--- a/src/verifier/reg_type_test.cc
+++ b/src/verifier/reg_type_test.cc
@@ -74,7 +74,6 @@
}
TEST_F(RegTypeTest, Primitives) {
-
ScopedObjectAccess soa(Thread::Current());
RegTypeCache cache(true);
@@ -108,6 +107,7 @@
EXPECT_FALSE(bool_reg_type.IsLongTypes());
EXPECT_FALSE(bool_reg_type.IsDoubleTypes());
EXPECT_TRUE(bool_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(bool_reg_type.IsNonZeroReferenceTypes());
const RegType& byte_reg_type = cache.Byte();
EXPECT_FALSE(byte_reg_type.IsUndefined());
@@ -139,6 +139,7 @@
EXPECT_FALSE(byte_reg_type.IsLongTypes());
EXPECT_FALSE(byte_reg_type.IsDoubleTypes());
EXPECT_TRUE(byte_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(byte_reg_type.IsNonZeroReferenceTypes());
const RegType& char_reg_type = cache.Char();
EXPECT_FALSE(char_reg_type.IsUndefined());
@@ -170,6 +171,7 @@
EXPECT_FALSE(char_reg_type.IsLongTypes());
EXPECT_FALSE(char_reg_type.IsDoubleTypes());
EXPECT_TRUE(char_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(char_reg_type.IsNonZeroReferenceTypes());
const RegType& short_reg_type = cache.Short();
EXPECT_FALSE(short_reg_type.IsUndefined());
@@ -201,6 +203,7 @@
EXPECT_FALSE(short_reg_type.IsLongTypes());
EXPECT_FALSE(short_reg_type.IsDoubleTypes());
EXPECT_TRUE(short_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(short_reg_type.IsNonZeroReferenceTypes());
const RegType& int_reg_type = cache.Integer();
EXPECT_FALSE(int_reg_type.IsUndefined());
@@ -232,6 +235,7 @@
EXPECT_FALSE(int_reg_type.IsLongTypes());
EXPECT_FALSE(int_reg_type.IsDoubleTypes());
EXPECT_TRUE(int_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(int_reg_type.IsNonZeroReferenceTypes());
const RegType& long_reg_type = cache.LongLo();
EXPECT_FALSE(long_reg_type.IsUndefined());
@@ -263,6 +267,7 @@
EXPECT_TRUE(long_reg_type.IsLongTypes());
EXPECT_FALSE(long_reg_type.IsDoubleTypes());
EXPECT_FALSE(long_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(long_reg_type.IsNonZeroReferenceTypes());
const RegType& float_reg_type = cache.Float();
EXPECT_FALSE(float_reg_type.IsUndefined());
@@ -294,6 +299,7 @@
EXPECT_FALSE(float_reg_type.IsLongTypes());
EXPECT_FALSE(float_reg_type.IsDoubleTypes());
EXPECT_FALSE(float_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(float_reg_type.IsNonZeroReferenceTypes());
const RegType& double_reg_type = cache.DoubleLo();
EXPECT_FALSE(double_reg_type.IsUndefined());
@@ -325,6 +331,7 @@
EXPECT_FALSE(double_reg_type.IsLongTypes());
EXPECT_TRUE(double_reg_type.IsDoubleTypes());
EXPECT_FALSE(double_reg_type.IsArrayIndexTypes());
+ EXPECT_FALSE(double_reg_type.IsNonZeroReferenceTypes());
}
@@ -352,12 +359,14 @@
RegTypeCache cache(true);
const RegType& ref_type_0 = cache.FromDescriptor(NULL, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
+ EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
const RegType& ref_type_1 = cache.FromDescriptor(NULL, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.Equals(ref_type_1));
const RegType& unresolved_super_class = cache.FromUnresolvedSuperClass(ref_type_0);
EXPECT_TRUE(unresolved_super_class.IsUnresolvedSuperClass());
+ EXPECT_TRUE(unresolved_super_class.IsNonZeroReferenceTypes());
}
TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
@@ -372,6 +381,7 @@
const RegType& unresolved_unintialised = cache.Uninitialized(ref_type, 1101ull);
EXPECT_TRUE(unresolved_unintialised.IsUnresolvedAndUninitializedReference());
EXPECT_TRUE(unresolved_unintialised.IsUninitializedTypes());
+ EXPECT_TRUE(unresolved_unintialised.IsNonZeroReferenceTypes());
// Create an uninitialized type of this unresolved type with different PC
const RegType& ref_type_unresolved_unintialised_1 = cache.Uninitialized(ref_type, 1102ull);
EXPECT_TRUE(unresolved_unintialised.IsUnresolvedAndUninitializedReference());