Merge "Fix typo." into dalvik-dev
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index ad238b8..67507bc 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -1054,7 +1054,8 @@
os << "Native method\n";
return;
}
- DCHECK(code_item_ != NULL);
+ reg_types_.Dump(os);
+ os << "Dumping instructions and register lines:\n";
const Instruction* inst = Instruction::At(code_item_->insns_);
for (size_t dex_pc = 0; dex_pc < code_item_->insns_size_in_code_units_;
dex_pc += insn_flags_[dex_pc].GetLengthInCodeUnits()) {
@@ -1128,7 +1129,7 @@
// it's effectively considered initialized the instant we reach here (in the sense that we
// can return without doing anything or call virtual methods).
{
- const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor);
+ const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
}
break;
@@ -1527,7 +1528,8 @@
const RegType& res_type = ResolveClassAndCheckAccess(dec_insn.vB);
// Register holds class, ie its type is class, on error it will hold Conflict.
work_line_->SetRegisterType(dec_insn.vA,
- res_type.IsConflict() ? res_type : reg_types_.JavaLangClass());
+ res_type.IsConflict() ? res_type
+ : reg_types_.JavaLangClass(true));
break;
}
case Instruction::MONITOR_ENTER:
@@ -1667,7 +1669,7 @@
break;
case Instruction::THROW: {
const RegType& res_type = work_line_->GetRegisterType(dec_insn.vA);
- if (!reg_types_.JavaLangThrowable().IsAssignableFrom(res_type)) {
+ if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(res_type)) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "thrown class " << res_type << " not instanceof Throwable";
}
break;
@@ -1785,7 +1787,7 @@
VerifyAGet(dec_insn, reg_types_.Long(), true);
break;
case Instruction::AGET_OBJECT:
- VerifyAGet(dec_insn, reg_types_.JavaLangObject(), false);
+ VerifyAGet(dec_insn, reg_types_.JavaLangObject(false), false);
break;
case Instruction::APUT_BOOLEAN:
@@ -1807,7 +1809,7 @@
VerifyAPut(dec_insn, reg_types_.Long(), true);
break;
case Instruction::APUT_OBJECT:
- VerifyAPut(dec_insn, reg_types_.JavaLangObject(), false);
+ VerifyAPut(dec_insn, reg_types_.JavaLangObject(false), false);
break;
case Instruction::IGET_BOOLEAN:
@@ -1829,7 +1831,7 @@
VerifyISGet(dec_insn, reg_types_.Long(), true, false);
break;
case Instruction::IGET_OBJECT:
- VerifyISGet(dec_insn, reg_types_.JavaLangObject(), false, false);
+ VerifyISGet(dec_insn, reg_types_.JavaLangObject(false), false, false);
break;
case Instruction::IPUT_BOOLEAN:
@@ -1851,7 +1853,7 @@
VerifyISPut(dec_insn, reg_types_.Long(), true, false);
break;
case Instruction::IPUT_OBJECT:
- VerifyISPut(dec_insn, reg_types_.JavaLangObject(), false, false);
+ VerifyISPut(dec_insn, reg_types_.JavaLangObject(false), false, false);
break;
case Instruction::SGET_BOOLEAN:
@@ -1873,7 +1875,7 @@
VerifyISGet(dec_insn, reg_types_.Long(), true, true);
break;
case Instruction::SGET_OBJECT:
- VerifyISGet(dec_insn, reg_types_.JavaLangObject(), false, true);
+ VerifyISGet(dec_insn, reg_types_.JavaLangObject(false), false, true);
break;
case Instruction::SPUT_BOOLEAN:
@@ -1895,7 +1897,7 @@
VerifyISPut(dec_insn, reg_types_.Long(), true, true);
break;
case Instruction::SPUT_OBJECT:
- VerifyISPut(dec_insn, reg_types_.JavaLangObject(), false, true);
+ VerifyISPut(dec_insn, reg_types_.JavaLangObject(false), false, true);
break;
case Instruction::INVOKE_VIRTUAL:
@@ -1916,7 +1918,7 @@
} else {
descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
break;
@@ -1977,7 +1979,8 @@
*/
work_line_->MarkRefsAsInitialized(this_type);
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, return_type_descriptor);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_, return_type_descriptor,
+ false);
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
break;
@@ -1995,7 +1998,7 @@
} else {
descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
}
@@ -2045,7 +2048,7 @@
} else {
descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor();
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
work_line_->SetResultRegisterType(return_type);
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
@@ -2466,8 +2469,8 @@
const RegType& referrer = GetDeclaringClass();
Class* klass = dex_cache_->GetResolvedType(class_idx);
const RegType& result =
- klass != NULL ? reg_types_.FromClass(klass)
- : reg_types_.FromDescriptor(class_loader_, descriptor);
+ klass != NULL ? reg_types_.FromClass(klass, klass->IsFinal())
+ : reg_types_.FromDescriptor(class_loader_, descriptor, false);
if (result.IsConflict()) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
<< "' in " << referrer;
@@ -2495,14 +2498,14 @@
for (; iterator.HasNext(); iterator.Next()) {
if (iterator.GetHandlerAddress() == (uint32_t) work_insn_idx_) {
if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
- common_super = ®_types_.JavaLangThrowable();
+ common_super = ®_types_.JavaLangThrowable(false);
} else {
const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
if (common_super == NULL) {
// Unconditionally assign for the first handler. We don't assert this is a Throwable
// as that is caught at runtime
common_super = &exception;
- } else if (!reg_types_.JavaLangThrowable().IsAssignableFrom(exception)) {
+ } else if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
// We don't know enough about the type and the common path merge will result in
// Conflict. Fail here knowing the correct thing can be done at runtime.
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "unexpected non-exception class " << exception;
@@ -2511,7 +2514,7 @@
// odd case, but nothing to do
} else {
common_super = &common_super->Merge(exception, ®_types_);
- CHECK(reg_types_.JavaLangThrowable().IsAssignableFrom(*common_super));
+ CHECK(reg_types_.JavaLangThrowable(false).IsAssignableFrom(*common_super));
}
}
}
@@ -2677,7 +2680,8 @@
return NULL;
}
if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
- const RegType& res_method_class = reg_types_.FromClass(res_method->GetDeclaringClass());
+ Class* klass = res_method->GetDeclaringClass();
+ const RegType& res_method_class = reg_types_.FromClass(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 << "'";
@@ -2707,7 +2711,7 @@
<< " missing signature component";
return NULL;
}
- const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor);
+ const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
uint32_t get_reg = is_range ? dec_insn.vC + actual_args : dec_insn.arg[actual_args];
if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
return res_method;
@@ -2904,7 +2908,8 @@
// Cannot infer and check type, however, access will cause null pointer exception
return field;
} else {
- const RegType& field_klass = reg_types_.FromClass(field->GetDeclaringClass());
+ Class* klass = field->GetDeclaringClass();
+ const RegType& field_klass = reg_types_.FromClass(klass, klass->IsFinal());
if (obj_type.IsUninitializedTypes() &&
(!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
!field_klass.Equals(GetDeclaringClass()))) {
@@ -2947,7 +2952,7 @@
descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
loader = class_loader_;
}
- const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor);
+ const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
if (is_primitive) {
if (field_type.Equals(insn_type) ||
(field_type.IsFloat() && insn_type.IsIntegralTypes()) ||
@@ -2996,7 +3001,7 @@
descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
loader = class_loader_;
}
- const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor);
+ const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
if (field != NULL) {
if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
@@ -3104,16 +3109,17 @@
const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id);
uint16_t return_type_idx = proto_id.return_type_idx_;
const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx));
- return reg_types_.FromDescriptor(class_loader_, descriptor);
+ return reg_types_.FromDescriptor(class_loader_, descriptor, false);
}
const RegType& MethodVerifier::GetDeclaringClass() {
if (foo_method_ != NULL) {
- return reg_types_.FromClass(foo_method_->GetDeclaringClass());
+ Class* klass = foo_method_->GetDeclaringClass();
+ return reg_types_.FromClass(klass, klass->IsFinal());
} else {
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx_);
const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
- return reg_types_.FromDescriptor(class_loader_, descriptor);
+ return reg_types_.FromDescriptor(class_loader_, descriptor, false);
}
}
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
index f555223..e02fbf4 100644
--- a/src/verifier/reg_type.cc
+++ b/src/verifier/reg_type.cc
@@ -46,11 +46,12 @@
"Unresolved Merged References",
"Unresolved Super Class",
"Reference",
+ "Precise Reference",
};
std::string RegType::Dump(const RegTypeCache* reg_types) const {
- DCHECK(type_ >= kRegTypeUndefined && type_ <= kRegTypeReference);
- DCHECK(arraysize(type_strings) == (kRegTypeReference + 1));
+ DCHECK(type_ >= kRegTypeUndefined && type_ <= kRegTypePreciseReference);
+ DCHECK(arraysize(type_strings) == (kRegTypePreciseReference + 1));
std::string result;
if (IsUnresolvedMergedReference()) {
if (reg_types == NULL) {
@@ -142,7 +143,7 @@
if (!IsUnresolvedTypes()) {
Class* super_klass = GetClass()->GetSuperClass();
if (super_klass != NULL) {
- return cache->FromClass(super_klass);
+ return cache->FromClass(super_klass, IsPreciseReference());
} else {
return cache->Zero();
}
@@ -150,7 +151,7 @@
if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
GetDescriptor()->CharAt(0) == '[') {
// Super class of all arrays is Object.
- return cache->JavaLangObject();
+ return cache->JavaLangObject(true);
} else {
return cache->FromUnresolvedSuperClass(*this);
}
@@ -301,7 +302,7 @@
if (IsZero() || incoming_type.IsZero()) {
return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
} else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
- return reg_types->JavaLangObject(); // Object MERGE ref => Object
+ return reg_types->JavaLangObject(false); // Object MERGE ref => Object
} else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
// We know how to merge an unresolved type with itself, 0 or Object. In this case we
// have two sub-classes and don't know how to merge. Create a new string-based unresolved
@@ -319,12 +320,12 @@
DCHECK(c1 != NULL && !c1->IsPrimitive());
DCHECK(c2 != NULL && !c2->IsPrimitive());
Class* join_class = ClassJoin(c1, c2);
- if (c1 == join_class) {
+ if (c1 == join_class && !IsPreciseReference()) {
return *this;
- } else if (c2 == join_class) {
+ } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
- return reg_types->FromClass(join_class);
+ return reg_types->FromClass(join_class, false);
}
}
} else {
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
index 3064f30..205867d 100644
--- a/src/verifier/reg_type.h
+++ b/src/verifier/reg_type.h
@@ -65,6 +65,7 @@
kRegTypeUnresolvedMergedReference, // Tree of merged references (at least 1 is unresolved).
kRegTypeUnresolvedSuperClass, // Super class of an unresolved type.
kRegTypeReference, // Reference type.
+ kRegTypePreciseReference, // Precisely the given type.
};
Type GetType() const {
@@ -93,6 +94,8 @@
bool IsUnresolvedMergedReference() const { return type_ == kRegTypeUnresolvedMergedReference; }
bool IsUnresolvedSuperClass() const { return type_ == kRegTypeUnresolvedSuperClass; }
bool IsReference() const { return type_ == kRegTypeReference; }
+ bool IsPreciseReference() const { return type_ == kRegTypePreciseReference; }
+
bool IsUninitializedTypes() const {
return IsUninitializedReference() || IsUninitializedThisReference() ||
IsUnresolvedAndUninitializedReference() || IsUnresolvedAndUninitializedThisReference();
@@ -154,7 +157,7 @@
}
bool IsNonZeroReferenceTypes() const {
- return IsReference() || IsUnresolvedReference() ||
+ return IsReference() || IsPreciseReference() || IsUnresolvedReference() ||
IsUninitializedReference() || IsUninitializedThisReference() ||
IsUnresolvedAndUninitializedReference() || IsUnresolvedAndUninitializedThisReference() ||
IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
@@ -198,6 +201,10 @@
return allocation_pc_or_constant_or_merged_types_;
}
+ bool HasClass() const {
+ return IsReference() || IsPreciseReference();
+ }
+
Class* GetClass() const {
DCHECK(!IsUnresolvedReference());
DCHECK(klass_or_descriptor_ != NULL);
@@ -212,7 +219,7 @@
bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
return GetDescriptor()->CharAt(0) == '[';
- } else if (IsReference()) {
+ } else if (HasClass()) {
return GetClass()->IsArrayClass();
} else {
return false;
@@ -224,7 +231,7 @@
// Primitive arrays will always resolve
DCHECK(GetDescriptor()->CharAt(1) == 'L' || GetDescriptor()->CharAt(1) == '[');
return GetDescriptor()->CharAt(0) == '[';
- } else if (IsReference()) {
+ } else if (HasClass()) {
Class* type = GetClass();
return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
} else {
@@ -256,7 +263,7 @@
}
bool IsJavaLangObjectArray() const {
- if (IsReference()) {
+ if (HasClass()) {
Class* type = GetClass();
return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
}
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 37086c9..847cde9 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -57,11 +57,18 @@
}
}
-const RegType& RegTypeCache::FromDescriptor(ClassLoader* loader, const char* descriptor) {
- return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
+const RegType& RegTypeCache::FromDescriptor(ClassLoader* loader, const char* descriptor,
+ bool precise) {
+ return From(RegTypeFromDescriptor(descriptor), loader, descriptor, precise);
}
-const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const char* descriptor) {
+static bool MatchingPrecisionForClass(RegType* entry, bool precise)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise);
+}
+
+const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const char* descriptor,
+ bool precise) {
if (type <= RegType::kRegTypeLastFixedLocation) {
// entries should be sized greater than primitive types
DCHECK_GT(entries_.size(), static_cast<size_t>(type));
@@ -76,14 +83,15 @@
}
return *entry;
} else {
- DCHECK(type == RegType::kRegTypeReference);
+ DCHECK(type == RegType::kRegTypeReference || type == RegType::kRegTypePreciseReference);
ClassHelper kh;
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
// check resolved and unresolved references, ignore uninitialized references
- if (cur_entry->IsReference()) {
+ if (cur_entry->HasClass()) {
kh.ChangeClass(cur_entry->GetClass());
- if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+ if (MatchingPrecisionForClass(cur_entry, precise) &&
+ (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
return *cur_entry;
}
} else if (cur_entry->IsUnresolvedReference() &&
@@ -93,8 +101,11 @@
}
Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
if (klass != NULL) {
- // Able to resolve so create resolved register type
- RegType* entry = new RegType(type, klass, 0, entries_.size());
+ // Able to resolve so create resolved register type that is precise if we
+ // know the type is final.
+ RegType* entry = new RegType(klass->IsFinal() ? RegType::kRegTypePreciseReference
+ : RegType::kRegTypeReference,
+ klass, 0, entries_.size());
entries_.push_back(entry);
return *entry;
} else {
@@ -119,7 +130,7 @@
}
}
-const RegType& RegTypeCache::FromClass(Class* klass) {
+const RegType& RegTypeCache::FromClass(Class* klass, bool precise) {
if (klass->IsPrimitive()) {
RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
// entries should be sized greater than primitive types
@@ -133,11 +144,14 @@
} else {
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
- if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+ if ((cur_entry->HasClass()) &&
+ MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
return *cur_entry;
}
}
- RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+ RegType* entry = new RegType(precise ? RegType::kRegTypePreciseReference
+ : RegType::kRegTypeReference,
+ klass, 0, entries_.size());
entries_.push_back(entry);
return *entry;
}
@@ -243,11 +257,11 @@
Class* klass = uninit_type.GetClass();
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
- if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+ if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
return *cur_entry;
}
}
- entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+ entry = new RegType(RegType::kRegTypePreciseReference, klass, 0, entries_.size());
}
entries_.push_back(entry);
return *entry;
@@ -284,17 +298,17 @@
const RegType& RegTypeCache::FromType(RegType::Type type) {
CHECK(type < RegType::kRegTypeReference);
switch (type) {
- case RegType::kRegTypeBoolean: return From(type, NULL, "Z");
- case RegType::kRegTypeByte: return From(type, NULL, "B");
- case RegType::kRegTypeShort: return From(type, NULL, "S");
- case RegType::kRegTypeChar: return From(type, NULL, "C");
- case RegType::kRegTypeInteger: return From(type, NULL, "I");
- case RegType::kRegTypeFloat: return From(type, NULL, "F");
+ case RegType::kRegTypeBoolean: return From(type, NULL, "Z", true);
+ case RegType::kRegTypeByte: return From(type, NULL, "B", true);
+ case RegType::kRegTypeShort: return From(type, NULL, "S", true);
+ case RegType::kRegTypeChar: return From(type, NULL, "C", true);
+ case RegType::kRegTypeInteger: return From(type, NULL, "I", true);
+ case RegType::kRegTypeFloat: return From(type, NULL, "F", true);
case RegType::kRegTypeLongLo:
- case RegType::kRegTypeLongHi: return From(type, NULL, "J");
+ case RegType::kRegTypeLongHi: return From(type, NULL, "J", true);
case RegType::kRegTypeDoubleLo:
- case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
- default: return From(type, NULL, "");
+ case RegType::kRegTypeDoubleHi: return From(type, NULL, "D", true);
+ default: return From(type, NULL, "", true);
}
}
@@ -315,9 +329,20 @@
if (array.IsUnresolvedTypes()) {
std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
std::string component(descriptor.substr(1, descriptor.size() - 1));
- return FromDescriptor(loader, component.c_str());
+ return FromDescriptor(loader, component.c_str(), false);
} else {
- return FromClass(array.GetClass()->GetComponentType());
+ Class* klass = array.GetClass()->GetComponentType();
+ return FromClass(klass, klass->IsFinal());
+ }
+}
+
+void RegTypeCache::Dump(std::ostream& os) {
+ os << "Register Types:\n";
+ for (size_t i = 0; i < entries_.size(); i++) {
+ RegType* cur_entry = entries_[i];
+ if (cur_entry != NULL) {
+ os << "\t" << i << ": " << cur_entry->Dump() << "\n";
+ }
}
}
diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h
index 5a2c49c..36fd2c7 100644
--- a/src/verifier/reg_type_cache.h
+++ b/src/verifier/reg_type_cache.h
@@ -40,12 +40,12 @@
return *result;
}
- const RegType& From(RegType::Type type, ClassLoader* loader, const char* descriptor)
+ const RegType& From(RegType::Type type, ClassLoader* loader, const char* descriptor, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const RegType& FromClass(Class* klass)
+ const RegType& FromClass(Class* klass, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const RegType& FromCat1Const(int32_t value);
- const RegType& FromDescriptor(ClassLoader* loader, const char* descriptor)
+ const RegType& FromDescriptor(ClassLoader* loader, const char* descriptor, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const RegType& FromType(RegType::Type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -77,17 +77,24 @@
return FromType(RegType::kRegTypeDoubleLo);
}
- const RegType& JavaLangClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Class;");
+ const RegType& JavaLangClass(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return From(precise ? RegType::kRegTypeReference
+ : RegType::kRegTypePreciseReference,
+ NULL, "Ljava/lang/Class;", precise);
}
- const RegType& JavaLangObject() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Object;");
+ const RegType& JavaLangObject(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return From(precise ? RegType::kRegTypeReference
+ : RegType::kRegTypePreciseReference,
+ NULL, "Ljava/lang/Object;", precise);
}
const RegType& JavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return From(RegType::kRegTypeReference, NULL, "Ljava/lang/String;");
+ // String is final and therefore always precise.
+ return From(RegType::kRegTypePreciseReference, NULL, "Ljava/lang/String;", true);
}
- const RegType& JavaLangThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Throwable;");
+ const RegType& JavaLangThrowable(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return From(precise ? RegType::kRegTypeReference
+ : RegType::kRegTypePreciseReference,
+ NULL, "Ljava/lang/Throwable;", precise);
}
const RegType& Undefined() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -118,6 +125,8 @@
const RegType& GetComponentType(const RegType& array, ClassLoader* loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
// The allocated entries
std::vector<RegType*> entries_;