summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/quick/gen_invoke.cc4
-rw-r--r--compiler/driver/compiler_driver.cc27
-rw-r--r--compiler/driver/compiler_driver.h2
-rw-r--r--compiler/image_writer.cc4
-rw-r--r--oatdump/oatdump.cc2
-rw-r--r--runtime/class_linker.cc107
-rw-r--r--runtime/debugger.cc13
-rw-r--r--runtime/debugger.h2
-rw-r--r--runtime/dex_file-inl.h11
-rw-r--r--runtime/dex_file.h3
-rw-r--r--runtime/gc/heap.cc2
-rw-r--r--runtime/interpreter/interpreter.cc2
-rw-r--r--runtime/jdwp/jdwp_handler.cc4
-rw-r--r--runtime/mirror/class.cc14
-rw-r--r--runtime/object_utils.h167
-rw-r--r--runtime/reflection.cc4
-rw-r--r--runtime/verifier/method_verifier.cc155
-rw-r--r--runtime/verifier/method_verifier.h1
-rw-r--r--runtime/verifier/reg_type.cc5
-rw-r--r--runtime/verifier/reg_type.h9
-rw-r--r--runtime/verifier/reg_type_cache.cc1
21 files changed, 350 insertions, 189 deletions
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 72ae91e..ed83863 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1219,8 +1219,10 @@ bool Mir2Lir::GenIntrinsic(CallInfo* info) {
* method. By doing this during basic block construction, we can also
* take advantage of/generate new useful dataflow info.
*/
+ const DexFile::MethodId& target_mid = cu_->dex_file->GetMethodId(info->index);
+ const DexFile::TypeId& declaring_type = cu_->dex_file->GetTypeId(target_mid.class_idx_);
StringPiece tgt_methods_declaring_class(
- cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index)));
+ cu_->dex_file->StringDataAsStringPieceByIdx(declaring_type.descriptor_idx_));
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)") {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index c12a7d9..e227715 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -600,12 +600,11 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De
UpdateImageClasses(timings);
}
-bool CompilerDriver::IsImageClass(const char* descriptor) const {
- DCHECK(descriptor != NULL);
+bool CompilerDriver::IsImageClass(const StringPiece& descriptor) const {
if (!IsImage()) {
return true;
} else {
- return image_classes_->find(descriptor) != image_classes_->end();
+ return image_classes_->find(descriptor.data()) != image_classes_->end();
}
}
@@ -780,7 +779,8 @@ void CompilerDriver::UpdateImageClasses(base::TimingLogger& timings) {
bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file,
uint32_t type_idx) {
- if (IsImage() && IsImageClass(dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx)))) {
+ if (IsImage() &&
+ IsImageClass(dex_file.StringDataAsStringPieceByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
@@ -1098,7 +1098,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType s
if (compiling_boot) {
if (support_boot_image_fixup_) {
MethodHelper mh(method);
- if (IsImageClass(mh.GetDeclaringClassDescriptor())) {
+ if (IsImageClass(mh.GetDeclaringClassDescriptorAsStringPiece())) {
// We can only branch directly to Methods that are resolved in the DexCache.
// Otherwise we won't invoke the resolution trampoline.
*direct_method = -1;
@@ -1572,8 +1572,8 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i
CHECK(soa.Self()->IsExceptionPending());
mirror::Throwable* exception = soa.Self()->GetException(NULL);
VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
- if (strcmp(ClassHelper(exception->GetClass()).GetDescriptor(),
- "Ljava/lang/OutOfMemoryError;") == 0) {
+ if (ClassHelper(exception->GetClass()).GetDescriptorAsStringPiece() ==
+ "Ljava/lang/OutOfMemoryError;") {
// There's little point continuing compilation if the heap is exhausted.
LOG(FATAL) << "Out of memory during type resolution for compilation";
}
@@ -2084,11 +2084,14 @@ static const char* class_initializer_black_list[] = {
static void InitializeClass(const ParallelCompilationManager* manager, size_t class_def_index)
LOCKS_EXCLUDED(Locks::mutator_lock_) {
ATRACE_CALL();
- const DexFile::ClassDef& class_def = manager->GetDexFile()->GetClassDef(class_def_index);
+ const DexFile* dex_file = manager->GetDexFile();
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+ const DexFile::TypeId& class_type_id = dex_file->GetTypeId(class_def.class_idx_);
+ StringPiece descriptor(dex_file->StringDataAsStringPieceByIdx(class_type_id.descriptor_idx_));
+
ScopedObjectAccess soa(Thread::Current());
mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader());
- const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def);
- mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
+ mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor.data(), class_loader);
if (klass != NULL) {
// Only try to initialize classes that were successfully verified.
if (klass->IsVerified()) {
@@ -2118,7 +2121,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
bool is_black_listed = StringPiece(descriptor).ends_with("$NoPreloadHolder;");
if (!is_black_listed) {
for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) {
- if (StringPiece(descriptor) == class_initializer_black_list[i]) {
+ if (descriptor == class_initializer_black_list[i]) {
is_black_listed = true;
break;
}
@@ -2126,7 +2129,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
}
if (!is_black_listed) {
VLOG(compiler) << "Initializing: " << descriptor;
- if (StringPiece(descriptor) == "Ljava/lang/Void;") {
+ if (descriptor == "Ljava/lang/Void;") {
// Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
ObjectLock lock(soa.Self(), klass);
mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 66c9cbf..7657af5 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -309,7 +309,7 @@ class CompilerDriver {
}
// Checks if class specified by type_idx is one of the image_classes_
- bool IsImageClass(const char* descriptor) const;
+ bool IsImageClass(const StringPiece& descriptor) const;
void RecordClassStatus(ClassReference ref, mirror::Class::Status status)
LOCKS_EXCLUDED(compiled_classes_lock_);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index f82c6fb..bcdc1c1 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -241,7 +241,7 @@ void ImageWriter::ComputeEagerResolvedStrings()
}
bool ImageWriter::IsImageClass(const Class* klass) {
- return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
+ return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptorAsStringPiece());
}
struct NonImageClasses {
@@ -296,7 +296,7 @@ void ImageWriter::PruneNonImageClasses() {
bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
if (!context->image_writer->IsImageClass(klass)) {
- context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
+ context->non_image_classes->insert(ClassHelper(klass).GetDescriptorAsStringPiece().as_string());
}
return true;
}
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index fc9e00c..cc6b5d7 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1119,7 +1119,7 @@ class ImageDumper {
typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
SizeAndCountTable sizes_and_counts;
- void Update(const std::string& descriptor, size_t object_bytes) {
+ void Update(const char* descriptor, size_t object_bytes) {
SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
if (it != sizes_and_counts.end()) {
it->second.bytes += object_bytes;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 91db883..6aae63e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1840,7 +1840,7 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file
SirtRef<mirror::Class>& klass) {
uint32_t dex_method_idx = it.GetMemberIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
- StringPiece method_name(dex_file.GetMethodName(method_id));
+ StringPiece method_name(dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_));
mirror::ArtMethod* dst = AllocArtMethod(self);
if (UNLIKELY(dst == NULL)) {
@@ -1869,7 +1869,7 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file
klass->SetFinalizable();
} else {
ClassHelper kh(klass.get());
- StringPiece klass_descriptor(kh.GetDescriptor());
+ StringPiece klass_descriptor(kh.GetDescriptorAsStringPiece());
// The Enum class declares a "final" finalize() method to prevent subclasses from
// introducing a finalizer. We don't want to set the finalizable flag for Enum or its
// subclasses, so we exclude it here.
@@ -2219,7 +2219,7 @@ bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader*
++it) {
mirror::Class* klass = it->second;
kh.ChangeClass(klass);
- if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
+ if (kh.GetDescriptorAsStringPiece() == descriptor && klass->GetClassLoader() == class_loader) {
class_table_.erase(it);
return true;
}
@@ -2265,15 +2265,16 @@ mirror::Class* ClassLinker::LookupClassFromTableLocked(const char* descriptor,
for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
kh.ChangeClass(klass);
- if (klass->GetClassLoader() == class_loader && strcmp(descriptor, kh.GetDescriptor()) == 0) {
+ if (klass->GetClassLoader() == class_loader && kh.GetDescriptorAsStringPiece() == descriptor) {
if (kIsDebugBuild) {
// Check for duplicates in the table.
for (++it; it != end && it->first == hash; ++it) {
mirror::Class* klass2 = it->second;
kh.ChangeClass(klass2);
- CHECK(!(strcmp(descriptor, kh.GetDescriptor()) == 0 && klass2->GetClassLoader() == class_loader))
- << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
- << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
+ CHECK(!(kh.GetDescriptorAsStringPiece() == descriptor &&
+ klass2->GetClassLoader() == class_loader))
+ << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
+ << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
}
}
return klass;
@@ -2379,7 +2380,7 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Clas
it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
kh.ChangeClass(klass);
- if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+ if (kh.GetDescriptorAsStringPiece() == descriptor) {
result.push_back(klass);
}
}
@@ -2538,11 +2539,11 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
- const char* descriptor = ClassHelper(klass).GetDescriptor();
uint16_t class_def_index = klass->GetDexClassDefIndex();
UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
CHECK(oat_class.get() != NULL)
- << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
+ << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
+ << ClassHelper(klass).GetDescriptor();
oat_file_class_status = oat_class->GetStatus();
if (oat_file_class_status == mirror::Class::kStatusVerified ||
oat_file_class_status == mirror::Class::kStatusInitialized) {
@@ -2581,7 +2582,8 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
return false;
}
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
- << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
+ << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
+ << ClassHelper(klass).GetDescriptor();
return false;
}
@@ -3727,10 +3729,10 @@ struct LinkFieldsComparator {
// same basic group? then sort by string.
fh_->ChangeField(field1);
- StringPiece name1(fh_->GetName());
+ const char* name1 = fh_->GetName();
fh_->ChangeField(field2);
- StringPiece name2(fh_->GetName());
- return name1 < name2;
+ const char* name2 = fh_->GetName();
+ return strcmp(name1, name2) < 0;
}
FieldHelper* fh_;
@@ -3764,7 +3766,9 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
// minimizes disruption of C++ version such as Class and Method.
std::deque<mirror::ArtField*> grouped_and_sorted_fields;
for (size_t i = 0; i < num_fields; i++) {
- grouped_and_sorted_fields.push_back(fields->Get(i));
+ mirror::ArtField* f = fields->Get(i);
+ CHECK(f != NULL);
+ grouped_and_sorted_fields.push_back(f);
}
FieldHelper fh(NULL, this);
std::sort(grouped_and_sorted_fields.begin(),
@@ -3831,7 +3835,7 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
if (!is_static &&
- StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;") {
+ (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;")) {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields);
@@ -3840,39 +3844,39 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
--num_reference_fields;
}
-#ifndef NDEBUG
- // Make sure that all reference fields appear before
- // non-reference fields, and all double-wide fields are aligned.
- bool seen_non_ref = false;
- for (size_t i = 0; i < num_fields; i++) {
- mirror::ArtField* field = fields->Get(i);
- if (false) { // enable to debug field layout
- LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
- << " class=" << PrettyClass(klass.get())
- << " field=" << PrettyField(field)
- << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()),
- false);
- }
- fh.ChangeField(field);
- Primitive::Type type = fh.GetTypeAsPrimitiveType();
- bool is_primitive = type != Primitive::kPrimNot;
- if (StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;" &&
- StringPiece(fh.GetName()) == "referent") {
- is_primitive = true; // We lied above, so we have to expect a lie here.
- }
- if (is_primitive) {
- if (!seen_non_ref) {
- seen_non_ref = true;
- DCHECK_EQ(num_reference_fields, i);
+ if (kIsDebugBuild) {
+ // Make sure that all reference fields appear before
+ // non-reference fields, and all double-wide fields are aligned.
+ bool seen_non_ref = false;
+ for (size_t i = 0; i < num_fields; i++) {
+ mirror::ArtField* field = fields->Get(i);
+ if (false) { // enable to debug field layout
+ LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
+ << " class=" << PrettyClass(klass.get())
+ << " field=" << PrettyField(field)
+ << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()),
+ false);
+ }
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
+ bool is_primitive = type != Primitive::kPrimNot;
+ if (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;" &&
+ fh.GetNameAsStringPiece() == "referent") {
+ is_primitive = true; // We lied above, so we have to expect a lie here.
+ }
+ if (is_primitive) {
+ if (!seen_non_ref) {
+ seen_non_ref = true;
+ DCHECK_EQ(num_reference_fields, i);
+ }
+ } else {
+ DCHECK(!seen_non_ref);
}
- } else {
- DCHECK(!seen_non_ref);
+ }
+ if (!seen_non_ref) {
+ DCHECK_EQ(num_fields, num_reference_fields);
}
}
- if (!seen_non_ref) {
- DCHECK_EQ(num_fields, num_reference_fields);
- }
-#endif
size = field_offset.Uint32Value();
// Update klass
if (is_static) {
@@ -4175,9 +4179,9 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file,
}
mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
- uint32_t field_idx,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader) {
+ uint32_t field_idx,
+ mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader) {
DCHECK(dex_cache != NULL);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
if (resolved != NULL) {
@@ -4190,8 +4194,9 @@ mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
return NULL;
}
- const char* name = dex_file.GetFieldName(field_id);
- const char* type = dex_file.GetFieldTypeDescriptor(field_id);
+ StringPiece name(dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_));
+ StringPiece type(dex_file.StringDataAsStringPieceByIdx(
+ dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
resolved = klass->FindField(name, type);
if (resolved != NULL) {
dex_cache->SetResolvedField(field_idx, resolved);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 88269e5..2eca734 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -891,7 +891,7 @@ JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* p
}
if (pDescriptor != NULL) {
- *pDescriptor = ClassHelper(c).GetDescriptor();
+ *pDescriptor = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
}
return JDWP::ERR_NONE;
}
@@ -928,13 +928,13 @@ JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf*
return JDWP::ERR_NONE;
}
-JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string& signature) {
+JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) {
JDWP::JdwpError status;
mirror::Class* c = DecodeClass(class_id, status);
if (c == NULL) {
return status;
}
- signature = ClassHelper(c).GetDescriptor();
+ *signature = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
return JDWP::ERR_NONE;
}
@@ -1065,8 +1065,8 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- std::string descriptor(ClassHelper(dst->GetClass()).GetDescriptor());
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
+ const char* descriptor = ClassHelper(dst->GetClass()).GetDescriptor();
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1);
if (IsPrimitiveTag(tag)) {
size_t width = GetTagWidth(tag);
@@ -2287,7 +2287,8 @@ void Dbg::PostClassPrepare(mirror::Class* c) {
// since the class may not yet be verified.
int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
JDWP::JdwpTypeTag tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
- gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), ClassHelper(c).GetDescriptor(), state);
+ gJdwpState->PostClassPrepare(tag, gRegistry->Add(c),
+ ClassHelper(c).GetDescriptorAsStringPiece().as_string(), state);
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
diff --git a/runtime/debugger.h b/runtime/debugger.h
index d0fe445..8574a33 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -149,7 +149,7 @@ class Dbg {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string& signature)
+ static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index dee8026..2ee9244 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_DEX_FILE_INL_H_
#include "base/logging.h"
+#include "base/stringpiece.h"
#include "dex_file.h"
#include "leb128.h"
#include "utils.h"
@@ -36,6 +37,16 @@ inline const char* DexFile::GetStringDataAndLength(const StringId& string_id, ui
return reinterpret_cast<const char*>(ptr);
}
+inline StringPiece DexFile::StringDataAsStringPieceByIdx(uint32_t idx) const {
+ if (idx == kDexNoIndex) {
+ return StringPiece();
+ }
+ const StringId& string_id = GetStringId(idx);
+ uint32_t length;
+ const char* data = GetStringDataAndLength(string_id, &length);
+ return StringPiece(data, static_cast<int>(length));
+}
+
inline const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) {
const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
return reinterpret_cast<const TryItem*>
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 7be5cb8..4534b41 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -40,6 +40,7 @@ namespace mirror {
class DexCache;
} // namespace mirror
class ClassLinker;
+class StringPiece;
class ZipArchive;
// TODO: move all of the macro functionality into the DexCache class.
@@ -432,6 +433,8 @@ class DexFile {
return GetStringDataAndLength(string_id, unicode_length);
}
+ StringPiece StringDataAsStringPieceByIdx(uint32_t idx) const;
+
const char* StringDataByIdx(uint32_t idx) const {
uint32_t unicode_length;
return StringDataAndLengthByIdx(idx, &unicode_length);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index ccd9aac..2ad6117 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -557,7 +557,7 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void*
mirror::Object* Heap::AllocObject(Thread* self, mirror::Class* c, size_t byte_count) {
DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
(c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
- strlen(ClassHelper(c).GetDescriptor()) == 0);
+ ClassHelper(c).GetDescriptorAsStringPiece().length() == 0);
DCHECK_GE(byte_count, sizeof(mirror::Object));
mirror::Object* obj = NULL;
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f35cfa3..fd92e06 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -82,7 +82,7 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
}
}
-static void InterpreterJni(Thread* self, ArtMethod* method, StringPiece shorty,
+static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
Object* receiver, uint32_t* args, JValue* result)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index a2efc48..523d892 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -47,7 +47,7 @@ std::string DescribeMethod(const MethodId& method_id) {
std::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
std::string signature("unknown");
- Dbg::GetSignature(ref_type_id, signature);
+ Dbg::GetSignature(ref_type_id, &signature);
return StringPrintf("%#llx (%s)", ref_type_id, signature.c_str());
}
@@ -547,7 +547,7 @@ static JdwpError RT_Signature(JdwpState*, Request& request, ExpandBuf* pReply, b
RefTypeId refTypeId = request.ReadRefTypeId();
std::string signature;
- JdwpError status = Dbg::GetSignature(refTypeId, signature);
+ JdwpError status = Dbg::GetSignature(refTypeId, &signature);
if (status != ERR_NONE) {
return status;
}
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index c128ede..287e8b0 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -135,7 +135,7 @@ String* Class::ComputeName() {
if (name != NULL) {
return name;
}
- std::string descriptor(ClassHelper(this).GetDescriptor());
+ std::string descriptor(ClassHelper(this).GetDescriptorAsStringPiece().as_string());
if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
// The descriptor indicates that this is the class for
// a primitive type; special-case the return value.
@@ -294,8 +294,8 @@ bool Class::IsInSamePackage(const Class* that) const {
return true;
}
// Compare the package part of the descriptor string.
- return IsInSamePackage(ClassHelper(klass1).GetDescriptor(),
- ClassHelper(klass2).GetDescriptor());
+ return IsInSamePackage(ClassHelper(klass1).GetDescriptorAsStringPiece(),
+ ClassHelper(klass2).GetDescriptorAsStringPiece());
}
bool Class::IsClassClass() const {
@@ -367,7 +367,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const String
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
mh.ChangeMethod(method);
- if (name == mh.GetName() && signature == mh.GetSignature()) {
+ if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
return method;
}
}
@@ -412,7 +412,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
mh.ChangeMethod(method);
- if (name == mh.GetName() && signature == mh.GetSignature()) {
+ if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
return method;
}
}
@@ -458,7 +458,7 @@ ArtField* Class::FindDeclaredInstanceField(const StringPiece& name, const String
for (size_t i = 0; i < NumInstanceFields(); ++i) {
ArtField* f = GetInstanceField(i);
fh.ChangeField(f);
- if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
+ if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
return f;
}
}
@@ -507,7 +507,7 @@ ArtField* Class::FindDeclaredStaticField(const StringPiece& name, const StringPi
for (size_t i = 0; i < NumStaticFields(); ++i) {
ArtField* f = GetStaticField(i);
fh.ChangeField(f);
- if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
+ if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
return f;
}
}
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 6ee3016..9e107a4 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -111,6 +111,17 @@ class ClassHelper {
}
}
+ StringPiece GetDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ CHECK(klass_ != NULL);
+ if (UNLIKELY(klass_->IsArrayClass() || klass_->IsPrimitive() || klass_->IsProxyClass())) {
+ return StringPiece(GetDescriptor());
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
+ return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
+ }
+ }
+
const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string result("[");
const mirror::Class* saved_klass = klass_;
@@ -182,7 +193,7 @@ class ClassHelper {
}
const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string descriptor(GetDescriptor());
+ std::string descriptor(GetDescriptorAsStringPiece().as_string());
const DexFile& dex_file = GetDexFile();
const DexFile::ClassDef* dex_class_def = GetClassDef();
CHECK(dex_class_def != NULL);
@@ -267,53 +278,77 @@ class FieldHelper {
}
field_ = new_f;
}
+
const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
- if (!field_->GetDeclaringClass()->IsProxyClass()) {
- const DexFile& dex_file = GetDexFile();
- return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
- } else {
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
DCHECK(field_->IsStatic());
DCHECK_LT(field_index, 2U);
return field_index == 0 ? "interfaces" : "throws";
}
+ const DexFile& dex_file = GetDexFile();
+ return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
}
+
+ StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t field_index = field_->GetDexFieldIndex();
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
+ return StringPiece(GetName());
+ }
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+ return dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_);
+ }
+
mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
- if (!field_->GetDeclaringClass()->IsProxyClass()) {
- const DexFile& dex_file = GetDexFile();
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
- mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
- if (resolve && (type == NULL)) {
- type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
- CHECK(type != NULL || Thread::Current()->IsExceptionPending());
- }
- return type;
- } else {
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
}
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+ mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
+ if (resolve && (type == NULL)) {
+ type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
+ CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ }
+ return type;
}
+
const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
- if (!field_->GetDeclaringClass()->IsProxyClass()) {
- const DexFile& dex_file = GetDexFile();
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
- return dex_file.GetFieldTypeDescriptor(field_id);
- } else {
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
DCHECK(field_->IsStatic());
DCHECK_LT(field_index, 2U);
// 0 == Class[] interfaces; 1 == Class[][] throws;
return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
}
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+ return dex_file.GetFieldTypeDescriptor(field_id);
+ }
+
+ StringPiece GetTypeDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t field_index = field_->GetDexFieldIndex();
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
+ return StringPiece(GetTypeDescriptor());
+ }
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(field_id.type_idx_);
+ return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
}
+
Primitive::Type GetTypeAsPrimitiveType()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return Primitive::GetType(GetTypeDescriptor()[0]);
}
+
bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Primitive::Type type = GetTypeAsPrimitiveType();
return type != Primitive::kPrimNot;
}
+
size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Primitive::Type type = GetTypeAsPrimitiveType();
return Primitive::FieldSize(type);
@@ -324,18 +359,17 @@ class FieldHelper {
const char* GetDeclaringClassDescriptor()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
- if (!field_->GetDeclaringClass()->IsProxyClass()) {
- const DexFile& dex_file = GetDexFile();
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
- return dex_file.GetFieldDeclaringClassDescriptor(field_id);
- } else {
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
DCHECK(field_->IsStatic());
DCHECK_LT(field_index, 2U);
// 0 == Class[] interfaces; 1 == Class[][] throws;
ClassHelper kh(field_->GetDeclaringClass());
- declaring_class_descriptor_ = kh.GetDescriptor();
+ declaring_class_descriptor_ = kh.GetDescriptorAsStringPiece().as_string();
return declaring_class_descriptor_.c_str();
}
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+ return dex_file.GetFieldDeclaringClassDescriptor(field_id);
}
private:
@@ -417,7 +451,7 @@ class MethodHelper {
const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
- if (dex_method_idx != DexFile::kDexNoIndex) {
+ if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
} else {
Runtime* runtime = Runtime::Current();
@@ -435,6 +469,16 @@ class MethodHelper {
}
}
+ StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const DexFile& dex_file = GetDexFile();
+ uint32_t dex_method_idx = method_->GetDexMethodIndex();
+ if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
+ return StringPiece(GetName());
+ }
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
+ return dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_);
+ }
+
mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
@@ -508,11 +552,22 @@ class MethodHelper {
const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
- if (dex_method_idx != DexFile::kDexNoIndex) {
- return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
- } else {
+ if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
return "<runtime method>";
}
+ return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
+ }
+
+ StringPiece GetDeclaringClassDescriptorAsStringPiece()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const DexFile& dex_file = GetDexFile();
+ uint32_t dex_method_idx = method_->GetDexMethodIndex();
+ if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
+ return StringPiece("<runtime method>");
+ }
+ const DexFile::MethodId& mid = dex_file.GetMethodId(dex_method_idx);
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(mid.class_idx_);
+ return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
}
const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -536,7 +591,7 @@ class MethodHelper {
}
bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return IsStatic() && StringPiece(GetName()) == "<clinit>";
+ return IsStatic() && GetNameAsStringPiece() == "<clinit>";
}
size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -569,16 +624,56 @@ class MethodHelper {
bool HasSameNameAndSignature(MethodHelper* other)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
if (GetDexCache() == other->GetDexCache()) {
- const DexFile& dex_file = GetDexFile();
- const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
const DexFile::MethodId& other_mid =
dex_file.GetMethodId(other->method_->GetDexMethodIndex());
return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
}
- StringPiece name(GetName());
- StringPiece other_name(other->GetName());
- return name == other_name && GetSignature() == other->GetSignature();
+ const DexFile& other_dex_file = other->GetDexFile();
+ const DexFile::MethodId& other_mid =
+ other_dex_file.GetMethodId(other->method_->GetDexMethodIndex());
+ if (dex_file.StringDataAsStringPieceByIdx(mid.name_idx_) !=
+ other_dex_file.StringDataAsStringPieceByIdx(other_mid.name_idx_)) {
+ return false; // Name mismatch.
+ }
+ const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(mid);
+ const DexFile::ProtoId& other_proto_id = other_dex_file.GetMethodPrototype(other_mid);
+ if (dex_file.StringDataAsStringPieceByIdx(proto_id.shorty_idx_) !=
+ other_dex_file.StringDataAsStringPieceByIdx(other_proto_id.shorty_idx_)) {
+ return false; // Shorty mismatch.
+ }
+ const DexFile::TypeId& return_type_id = dex_file.GetTypeId(proto_id.return_type_idx_);
+ const DexFile::TypeId& other_return_type_id =
+ other_dex_file.GetTypeId(other_proto_id.return_type_idx_);
+ if (dex_file.StringDataAsStringPieceByIdx(return_type_id.descriptor_idx_) !=
+ other_dex_file.StringDataAsStringPieceByIdx(other_return_type_id.descriptor_idx_)) {
+ return false; // Return type mismatch.
+ }
+ const DexFile::TypeList* params = dex_file.GetProtoParameters(proto_id);
+ const DexFile::TypeList* other_params = other_dex_file.GetProtoParameters(other_proto_id);
+ if (params == nullptr) {
+ return other_params == nullptr; // Check both lists are empty.
+ }
+ if (other_params == nullptr) {
+ return false; // Parameter list size mismatch.
+ }
+ uint32_t params_size = params->Size();
+ uint32_t other_params_size = other_params->Size();
+ if (params_size != other_params_size) {
+ return false; // Parameter list size mismatch.
+ }
+ for (uint32_t i = 0; i < params_size; ++i) {
+ const DexFile::TypeId& param_id = dex_file.GetTypeId(params->GetTypeItem(i).type_idx_);
+ const DexFile::TypeId& other_param_id =
+ other_dex_file.GetTypeId(other_params->GetTypeItem(i).type_idx_);
+ if (dex_file.StringDataAsStringPieceByIdx(param_id.descriptor_idx_) !=
+ other_dex_file.StringDataAsStringPieceByIdx(other_param_id.descriptor_idx_)) {
+ return false; // Parameter type mismatch.
+ }
+ }
+ return true;
}
const DexFile::CodeItem* GetCodeItem()
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3e58b4b..4ff7349 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -323,7 +323,7 @@ static bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object*
}
JValue boxed_value;
- std::string src_descriptor(ClassHelper(o->GetClass()).GetDescriptor());
+ const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptorAsStringPiece());
mirror::Class* src_class = NULL;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
@@ -356,7 +356,7 @@ static bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object*
StringPrintf("%s has type %s, got %s",
UnboxingFailureKind(m, index, f).c_str(),
PrettyDescriptor(dst_class).c_str(),
- PrettyDescriptor(src_descriptor.c_str()).c_str()).c_str());
+ PrettyDescriptor(src_descriptor.data()).c_str()).c_str());
return false;
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 924a1bb..4442ee1 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -80,7 +80,7 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* kla
return kNoFailure;
}
mirror::Class* super = klass->GetSuperClass();
- if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") {
+ if (super == NULL && ClassHelper(klass).GetDescriptorAsStringPiece() != "Ljava/lang/Object;") {
*error = "Verifier rejected class ";
*error += PrettyDescriptor(klass);
*error += " that has no super class";
@@ -293,6 +293,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca
dex_method_idx_(dex_method_idx),
mirror_method_(method),
method_access_flags_(method_access_flags),
+ return_type_(nullptr),
dex_file_(dex_file),
dex_cache_(dex_cache),
class_loader_(class_loader),
@@ -300,7 +301,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca
code_item_(code_item),
declaring_class_(NULL),
interesting_dex_pc_(-1),
- monitor_enter_dex_pcs_(NULL),
+ monitor_enter_dex_pcs_(nullptr),
have_pending_hard_failure_(false),
have_pending_runtime_throw_failure_(false),
new_instance_count_(0),
@@ -309,7 +310,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca
allow_soft_failures_(allow_soft_failures),
has_check_casts_(false),
has_virtual_or_interface_invokes_(false) {
- DCHECK(class_def != NULL);
+ DCHECK(class_def != nullptr);
}
void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
@@ -2131,20 +2132,30 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL,
is_range, is_super);
- const char* descriptor;
- if (called_method == NULL) {
+ const RegType* return_type = nullptr;
+ if (called_method != nullptr) {
+ MethodHelper mh(called_method);
+ mirror::Class* return_type_class = mh.GetReturnType();
+ if (return_type_class != nullptr) {
+ return_type = &reg_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
+ } else {
+ Thread* self = Thread::Current();
+ DCHECK(self->IsExceptionPending());
+ self->ClearException();
+ }
+ }
+ if (return_type == nullptr) {
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->StringByTypeIdx(return_type_idx);
- } else {
- descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
+ const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx);
+ return_type = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
- if (!return_type.IsLowHalf()) {
- work_line_->SetResultRegisterType(return_type);
+ if (!return_type->IsLowHalf()) {
+ work_line_->SetResultRegisterType(*return_type);
} else {
- work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
+ work_line_->SetResultRegisterTypeWide(*return_type, return_type->HighHalf(&reg_types_));
}
just_set_result = true;
break;
@@ -2159,7 +2170,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
if (called_method == NULL) {
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
- is_constructor = StringPiece(dex_file_->GetMethodName(method_id)) == "<init>";
+ is_constructor = dex_file_->StringDataAsStringPieceByIdx(method_id.name_idx_) == "<init>";
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
return_type_descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
@@ -3497,22 +3508,26 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty
const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
field = GetInstanceField(object_type, field_idx);
}
- const char* descriptor;
- mirror::ClassLoader* loader;
+ const RegType* field_type = nullptr;
if (field != NULL) {
- descriptor = FieldHelper(field).GetTypeDescriptor();
- loader = field->GetDeclaringClass()->GetClassLoader();
- } else {
+ FieldHelper fh(field);
+ mirror::Class* field_type_class = fh.GetType(false);
+ if (field_type_class != nullptr) {
+ field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+ field_type_class->CannotBeAssignedFromOtherTypes());
+ }
+ }
+ if (field_type == nullptr) {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
- descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
- loader = class_loader_;
+ const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
+ mirror::ClassLoader* loader = class_loader_;
+ field_type = &reg_types_.FromDescriptor(loader, descriptor, false);
}
- const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
if (is_primitive) {
- if (field_type.Equals(insn_type) ||
- (field_type.IsFloat() && insn_type.IsInteger()) ||
- (field_type.IsDouble() && insn_type.IsLong())) {
+ if (field_type->Equals(insn_type) ||
+ (field_type->IsFloat() && insn_type.IsInteger()) ||
+ (field_type->IsDouble() && insn_type.IsLong())) {
// expected that read is of the correct primitive type or that int reads are reading
// floats or long reads are reading doubles
} else {
@@ -3525,7 +3540,7 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty
return;
}
} else {
- if (!insn_type.IsAssignableFrom(field_type)) {
+ if (!insn_type.IsAssignableFrom(*field_type)) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
<< " to be compatible with type '" << insn_type
<< "' but found type '" << field_type
@@ -3534,10 +3549,10 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty
return;
}
}
- if (!field_type.IsLowHalf()) {
- work_line_->SetRegisterType(vregA, field_type);
+ if (!field_type->IsLowHalf()) {
+ work_line_->SetRegisterType(vregA, *field_type);
} else {
- work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
+ work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(&reg_types_));
}
}
@@ -3551,36 +3566,38 @@ void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_ty
const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
field = GetInstanceField(object_type, field_idx);
}
- const char* descriptor;
- mirror::ClassLoader* loader;
- if (field != NULL) {
- descriptor = FieldHelper(field).GetTypeDescriptor();
- loader = field->GetDeclaringClass()->GetClassLoader();
- } else {
- const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
- descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
- loader = class_loader_;
- }
- const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
+ const RegType* field_type = nullptr;
if (field != NULL) {
if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
<< " from other class " << GetDeclaringClass();
return;
}
+ FieldHelper fh(field);
+ mirror::Class* field_type_class = fh.GetType(false);
+ if (field_type_class != nullptr) {
+ field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+ field_type_class->CannotBeAssignedFromOtherTypes());
+ }
+ }
+ if (field_type == nullptr) {
+ const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
+ const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
+ mirror::ClassLoader* loader = class_loader_;
+ field_type = &reg_types_.FromDescriptor(loader, descriptor, false);
}
const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
if (is_primitive) {
- VerifyPrimitivePut(field_type, insn_type, vregA);
+ VerifyPrimitivePut(*field_type, insn_type, vregA);
} else {
- if (!insn_type.IsAssignableFrom(field_type)) {
+ if (!insn_type.IsAssignableFrom(*field_type)) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
<< " to be compatible with type '" << insn_type
<< "' but found type '" << field_type
<< "' in put-object";
return;
}
- work_line_->VerifyRegisterType(vregA, field_type);
+ work_line_->VerifyRegisterType(vregA, *field_type);
}
}
@@ -3648,14 +3665,21 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
return;
}
- const char* descriptor = FieldHelper(field).GetTypeDescriptor();
- mirror::ClassLoader* loader = field->GetDeclaringClass()->GetClassLoader();
- const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
+ FieldHelper fh(field);
+ mirror::Class* field_type_class = fh.GetType(false);
+ const RegType* field_type;
+ if (field_type_class != nullptr) {
+ field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+ field_type_class->CannotBeAssignedFromOtherTypes());
+ } else {
+ field_type = &reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
+ fh.GetTypeDescriptor(), false);
+ }
const uint32_t vregA = inst->VRegA_22c();
if (is_primitive) {
- if (field_type.Equals(insn_type) ||
- (field_type.IsFloat() && insn_type.IsIntegralTypes()) ||
- (field_type.IsDouble() && insn_type.IsLongTypes())) {
+ if (field_type->Equals(insn_type) ||
+ (field_type->IsFloat() && insn_type.IsIntegralTypes()) ||
+ (field_type->IsDouble() && insn_type.IsLongTypes())) {
// expected that read is of the correct primitive type or that int reads are reading
// floats or long reads are reading doubles
} else {
@@ -3668,7 +3692,7 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins
return;
}
} else {
- if (!insn_type.IsAssignableFrom(field_type)) {
+ if (!insn_type.IsAssignableFrom(*field_type)) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
<< " to be compatible with type '" << insn_type
<< "' but found type '" << field_type
@@ -3677,10 +3701,10 @@ void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& ins
return;
}
}
- if (!field_type.IsLowHalf()) {
- work_line_->SetRegisterType(vregA, field_type);
+ if (!field_type->IsLowHalf()) {
+ work_line_->SetRegisterType(vregA, *field_type);
} else {
- work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
+ work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(&reg_types_));
}
}
@@ -3822,11 +3846,28 @@ InstructionFlags* MethodVerifier::CurrentInsnFlags() {
}
const RegType& MethodVerifier::GetMethodReturnType() {
- const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
- 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, false);
+ if (return_type_ == nullptr) {
+ if (mirror_method_ != NULL) {
+ MethodHelper mh(mirror_method_);
+ mirror::Class* return_type_class = mh.GetReturnType();
+ if (return_type_class != nullptr) {
+ return_type_ =&reg_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
+ } else {
+ Thread* self = Thread::Current();
+ DCHECK(self->IsExceptionPending());
+ self->ClearException();
+ }
+ }
+ if (return_type_ == nullptr) {
+ const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
+ 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_type_ = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ }
+ }
+ return *return_type_;
}
const RegType& MethodVerifier::GetDeclaringClass() {
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 073a2f7..f143751 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -688,6 +688,7 @@ class MethodVerifier {
// Its object representation if known.
mirror::ArtMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_);
const uint32_t method_access_flags_; // Method's access flags.
+ const RegType* return_type_; // Lazily computed return type of the method.
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_);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 857acb8..50d1583 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -761,11 +761,6 @@ bool RegType::IsStrictlyAssignableFrom(const RegType& src) const {
return AssignableFrom(*this, src, true);
}
-int32_t ConstantType::ConstantValue() const {
- DCHECK(IsConstantTypes());
- return constant_;
-}
-
int32_t ConstantType::ConstantValueLo() const {
DCHECK(IsConstantLo());
return constant_;
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 865ba20..f371733 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -574,9 +574,12 @@ class ConstantType : public RegType {
// 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;
- virtual int32_t ConstantValueLo() const;
- virtual int32_t ConstantValueHi() const;
+ int32_t ConstantValue() const {
+ DCHECK(IsConstantTypes());
+ return constant_;
+ }
+ int32_t ConstantValueLo() const;
+ int32_t ConstantValueHi() const;
bool IsZero() const {
return IsPreciseConstant() && ConstantValue() == 0;
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index ce465a4..fd70300 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -210,6 +210,7 @@ const RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descr
}
const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
+ DCHECK(klass != nullptr);
if (klass->IsPrimitive()) {
// Note: precise isn't used for primitive classes. A char is assignable to an int. All
// primitive classes are final.