diff options
-rw-r--r-- | compiler/dex/quick/codegen_util.cc | 12 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 4 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 5 | ||||
-rw-r--r-- | runtime/class_linker.cc | 22 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 21 | ||||
-rw-r--r-- | runtime/common_throws.cc | 2 | ||||
-rw-r--r-- | runtime/common_throws.h | 3 | ||||
-rw-r--r-- | runtime/debugger.cc | 2 | ||||
-rw-r--r-- | runtime/dex_file-inl.h | 4 | ||||
-rw-r--r-- | runtime/dex_file.cc | 66 | ||||
-rw-r--r-- | runtime/dex_file.h | 95 | ||||
-rw-r--r-- | runtime/dex_file_test.cc | 27 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 1 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 64 | ||||
-rw-r--r-- | runtime/mirror/class.h | 35 | ||||
-rw-r--r-- | runtime/object_utils.h | 41 | ||||
-rw-r--r-- | runtime/trace.cc | 2 | ||||
-rw-r--r-- | runtime/utils.cc | 22 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 4 | ||||
-rw-r--r-- | test/Android.mk | 2 | ||||
-rw-r--r-- | test/GetMethodSignature/GetMethodSignature.java (renamed from test/CreateMethodSignature/CreateMethodSignature.java) | 4 |
21 files changed, 283 insertions, 155 deletions
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index 4ce752fb39..6e49f0bc54 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -248,12 +248,12 @@ void Mir2Lir::DumpPromotionMap() { } /* Dump a mapping table */ -void Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor, - const std::string& name, const std::string& signature, +void Mir2Lir::DumpMappingTable(const char* table_name, const char* descriptor, + const char* name, const Signature& signature, const std::vector<uint32_t>& v) { if (v.size() > 0) { std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name, - descriptor.c_str(), name.c_str(), signature.c_str(), v.size())); + descriptor, name, signature.ToString().c_str(), v.size())); std::replace(line.begin(), line.end(), ';', '_'); LOG(INFO) << line; for (uint32_t i = 0; i < v.size(); i+=2) { @@ -293,9 +293,9 @@ void Mir2Lir::CodegenDump() { const DexFile::MethodId& method_id = cu_->dex_file->GetMethodId(cu_->method_idx); - std::string signature(cu_->dex_file->GetMethodSignature(method_id)); - std::string name(cu_->dex_file->GetMethodName(method_id)); - std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id)); + const Signature signature = cu_->dex_file->GetMethodSignature(method_id); + const char* name = cu_->dex_file->GetMethodName(method_id); + const char* descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id)); // Dump mapping tables DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_); diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 401e3d5f93..7d6f968da5 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -283,8 +283,8 @@ class Mir2Lir : public Backend { bool EvaluateBranch(Instruction::Code opcode, int src1, int src2); bool IsInexpensiveConstant(RegLocation rl_src); ConditionCode FlipComparisonOrder(ConditionCode before); - void DumpMappingTable(const char* table_name, const std::string& descriptor, - const std::string& name, const std::string& signature, + void DumpMappingTable(const char* table_name, const char* descriptor, + const char* name, const Signature& signature, const std::vector<uint32_t>& v); void InstallLiteralPools(); void InstallSwitchTables(); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index e227715605..056be1fb04 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1227,8 +1227,9 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui if (name != NULL) { uint16_t return_type_idx; std::vector<uint16_t> param_type_idxs; - bool success = dexfile->CreateTypeList(&return_type_idx, ¶m_type_idxs, - cm_dexfile->GetMethodSignature(cm_method_id)); + bool success = + dexfile->CreateTypeList(cm_dexfile->GetMethodSignature(cm_method_id).ToString(), + &return_type_idx, ¶m_type_idxs); if (success) { const DexFile::ProtoId* sig = dexfile->FindProtoId(return_type_idx, param_type_idxs); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 6aae63ee2c..17a179f2d9 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2823,12 +2823,12 @@ static void CheckProxyConstructor(mirror::ArtMethod* constructor) CHECK(constructor->IsConstructor()); MethodHelper mh(constructor); CHECK_STREQ(mh.GetName(), "<init>"); - CHECK_EQ(mh.GetSignature(), std::string("(Ljava/lang/reflect/InvocationHandler;)V")); + CHECK_STREQ(mh.GetSignature().ToString().c_str(), "(Ljava/lang/reflect/InvocationHandler;)V"); DCHECK(constructor->IsPublic()); } mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass, - SirtRef<mirror::ArtMethod>& prototype) { + SirtRef<mirror::ArtMethod>& prototype) { // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden // prototype method prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(), @@ -2892,7 +2892,7 @@ static bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, } if (!can_init_statics) { // Check if there's a class initializer. - mirror::ArtMethod* clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V"); + mirror::ArtMethod* clinit = klass->FindClassInitializer(); if (clinit != NULL) { return false; } @@ -3039,7 +3039,7 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics, } } - mirror::ArtMethod* clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V"); + mirror::ArtMethod* clinit = klass->FindClassInitializer(); if (clinit != NULL) { CHECK(can_init_statics); if (LIKELY(Runtime::Current()->IsStarted())) { @@ -3992,11 +3992,11 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, } mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, - uint32_t method_idx, - mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, - const mirror::ArtMethod* referrer, - InvokeType type) { + uint32_t method_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + const mirror::ArtMethod* referrer, + InvokeType type) { DCHECK(dex_cache != NULL); // Check for hit in the dex cache. mirror::ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx); @@ -4031,7 +4031,7 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, if (resolved == NULL) { // Search by name, which works across dex files. const char* name = dex_file.StringDataByIdx(method_id.name_idx_); - std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL)); + const Signature signature = dex_file.GetMethodSignature(method_id); switch (type) { case kDirect: // Fall-through. case kStatic: @@ -4061,7 +4061,7 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, // We failed to find the method which means either an access error, an incompatible class // change, or no such method. First try to find the method among direct and virtual methods. const char* name = dex_file.StringDataByIdx(method_id.name_idx_); - std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL)); + const Signature signature = dex_file.GetMethodSignature(method_id); switch (type) { case kDirect: case kStatic: diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index bea1139679..ad9347fee1 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -152,7 +152,7 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(method != NULL); EXPECT_TRUE(method->GetClass() != NULL); EXPECT_TRUE(mh.GetName() != NULL); - EXPECT_TRUE(mh.GetSignature() != NULL); + EXPECT_TRUE(mh.GetSignature() != Signature::NoSignature()); EXPECT_TRUE(method->GetDexCacheStrings() != NULL); EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL); @@ -942,15 +942,16 @@ TEST_F(ClassLinkerTest, Interfaces) { EXPECT_TRUE(K->IsAssignableFrom(B)); EXPECT_TRUE(J->IsAssignableFrom(B)); - mirror::ArtMethod* Ii = I->FindVirtualMethod("i", "()V"); - mirror::ArtMethod* Jj1 = J->FindVirtualMethod("j1", "()V"); - mirror::ArtMethod* Jj2 = J->FindVirtualMethod("j2", "()V"); - mirror::ArtMethod* Kj1 = K->FindInterfaceMethod("j1", "()V"); - mirror::ArtMethod* Kj2 = K->FindInterfaceMethod("j2", "()V"); - mirror::ArtMethod* Kk = K->FindInterfaceMethod("k", "()V"); - mirror::ArtMethod* Ai = A->FindVirtualMethod("i", "()V"); - mirror::ArtMethod* Aj1 = A->FindVirtualMethod("j1", "()V"); - mirror::ArtMethod* Aj2 = A->FindVirtualMethod("j2", "()V"); + const Signature void_sig = I->GetDexCache()->GetDexFile()->CreateSignature("()V"); + mirror::ArtMethod* Ii = I->FindVirtualMethod("i", void_sig); + mirror::ArtMethod* Jj1 = J->FindVirtualMethod("j1", void_sig); + mirror::ArtMethod* Jj2 = J->FindVirtualMethod("j2", void_sig); + mirror::ArtMethod* Kj1 = K->FindInterfaceMethod("j1", void_sig); + mirror::ArtMethod* Kj2 = K->FindInterfaceMethod("j2", void_sig); + mirror::ArtMethod* Kk = K->FindInterfaceMethod("k", void_sig); + mirror::ArtMethod* Ai = A->FindVirtualMethod("i", void_sig); + mirror::ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig); + mirror::ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig); ASSERT_TRUE(Ii != NULL); ASSERT_TRUE(Jj1 != NULL); ASSERT_TRUE(Jj2 != NULL); diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 26ce5be1ec..189e3edc0f 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -265,7 +265,7 @@ void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, // NoSuchMethodError void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, - const StringPiece& signature) { + const Signature& signature) { std::ostringstream msg; ClassHelper kh(c); msg << "No " << type << " method " << name << signature diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 99c6343cdd..1d77e2d625 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -27,6 +27,7 @@ class ArtMethod; class Class; class Object; } // namespace mirror +class Signature; class StringPiece; class ThrowLocation; @@ -140,7 +141,7 @@ void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, // NoSuchMethodError void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, - const StringPiece& signature) + const Signature& signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void ThrowNoSuchMethodError(uint32_t method_idx) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index e57137fb96..ae57aa34ec 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -1287,7 +1287,7 @@ JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_g MethodHelper mh(m); expandBufAddMethodId(pReply, ToMethodId(m)); expandBufAddUtf8String(pReply, mh.GetName()); - expandBufAddUtf8String(pReply, mh.GetSignature()); + expandBufAddUtf8String(pReply, mh.GetSignature().ToString()); if (with_generic) { static const char genericSignature[1] = ""; expandBufAddUtf8String(pReply, genericSignature); diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h index 2ee9244bf2..c57a1e7582 100644 --- a/runtime/dex_file-inl.h +++ b/runtime/dex_file-inl.h @@ -47,6 +47,10 @@ inline StringPiece DexFile::StringDataAsStringPieceByIdx(uint32_t idx) const { return StringPiece(data, static_cast<int>(length)); } +inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) const { + return Signature(this, GetProtoId(method_id.proto_idx_)); +} + 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.cc b/runtime/dex_file.cc index 098ab674f4..275dcc5a03 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -503,8 +503,8 @@ const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx, } // Given a signature place the type ids into the given vector -bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs, - const std::string& signature) const { +bool DexFile::CreateTypeList(const StringPiece& signature, uint16_t* return_type_idx, + std::vector<uint16_t>* param_type_idxs) const { if (signature[0] != '(') { return false; } @@ -518,6 +518,7 @@ bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* p process_return = true; continue; } + // TODO: avoid building a string. std::string descriptor; descriptor += c; while (c == '[') { // process array prefix @@ -557,35 +558,18 @@ bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* p return false; // failed to correctly parse return type } -// Materializes the method descriptor for a method prototype. Method -// descriptors are not stored directly in the dex file. Instead, one -// must assemble the descriptor from references in the prototype. -std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const { - const ProtoId& proto_id = GetProtoId(proto_idx); - std::string descriptor; - descriptor.push_back('('); - const TypeList* type_list = GetProtoParameters(proto_id); - size_t parameter_length = 0; - if (type_list != NULL) { - // A non-zero number of arguments. Append the type names. - for (size_t i = 0; i < type_list->Size(); ++i) { - const TypeItem& type_item = type_list->GetTypeItem(i); - uint32_t type_idx = type_item.type_idx_; - uint32_t type_length; - const char* name = StringByTypeIdx(type_idx, &type_length); - parameter_length += type_length; - descriptor.append(name); - } +const Signature DexFile::CreateSignature(const StringPiece& signature) const { + uint16_t return_type_idx; + std::vector<uint16_t> param_type_indices; + bool success = CreateTypeList(signature, &return_type_idx, ¶m_type_indices); + if (!success) { + return Signature::NoSignature(); } - descriptor.push_back(')'); - uint32_t return_type_idx = proto_id.return_type_idx_; - uint32_t return_type_length; - const char* name = StringByTypeIdx(return_type_idx, &return_type_length); - descriptor.append(name); - if (unicode_length != NULL) { - *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and ) + const ProtoId* proto_id = FindProtoId(return_type_idx, param_type_indices); + if (proto_id == NULL) { + return Signature::NoSignature(); } - return descriptor; + return Signature(this, *proto_id); } int32_t DexFile::GetLineNumFromPC(const mirror::ArtMethod* method, uint32_t rel_pc) const { @@ -831,6 +815,30 @@ bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_ } } +std::string Signature::ToString() const { + if (dex_file_ == nullptr) { + CHECK(proto_id_ == nullptr); + return "<no signature>"; + } + const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); + std::string result; + if (params == nullptr) { + result += "()"; + } else { + result += "("; + for (uint32_t i = 0; i < params->Size(); ++i) { + result += dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_); + } + result += ")"; + } + result += dex_file_->StringByTypeIdx(proto_id_->return_type_idx_); + return result; +} + +std::ostream& operator<<(std::ostream& os, const Signature& sig) { + return os << sig.ToString(); +} + // Decodes the header section from the class data bytes. void ClassDataItemIterator::ReadClassDataHeader() { CHECK(ptr_pos_ != NULL); diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 4534b41e92..40e4c72772 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -40,6 +40,7 @@ namespace mirror { class DexCache; } // namespace mirror class ClassLinker; +class Signature; class StringPiece; class ZipArchive; @@ -559,10 +560,8 @@ class DexFile { return GetProtoId(method_id.proto_idx_); } - // Returns the signature of a method id. - const std::string GetMethodSignature(const MethodId& method_id) const { - return CreateMethodSignature(method_id.proto_idx_, NULL); - } + // Returns a representation of the signature of a method id. + const Signature GetMethodSignature(const MethodId& method_id) const; // Returns the name of a method id. const char* GetMethodName(const MethodId& method_id) const { @@ -656,15 +655,16 @@ class DexFile { } // Looks up a proto id for a given return type and signature type list - const ProtoId* FindProtoId(uint16_t return_type_id, + const ProtoId* FindProtoId(uint16_t return_type_idx, const std::vector<uint16_t>& signature_type_idxs_) const; // Given a signature place the type ids into the given vector, returns true on success - bool CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs, - const std::string& signature) const; + bool CreateTypeList(const StringPiece& signature, uint16_t* return_type_idx, + std::vector<uint16_t>* param_type_idxs) const; - // Given a proto_idx decode the type list and return type into a method signature - std::string CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const; + // Create a Signature from the given string signature or return Signature::NoSignature if not + // possible. + const Signature CreateSignature(const StringPiece& signature) const; // Returns the short form method descriptor for the given prototype. const char* GetShorty(uint32_t proto_idx) const { @@ -942,6 +942,83 @@ class DexFileParameterIterator { DISALLOW_IMPLICIT_CONSTRUCTORS(DexFileParameterIterator); }; +// Abstract the signature of a method. +class Signature { + public: + std::string ToString() const; + + static Signature NoSignature() { + return Signature(); + } + + bool operator==(const Signature& rhs) const { + if (dex_file_ == nullptr) { + return rhs.dex_file_ == nullptr; + } + if (rhs.dex_file_ == nullptr) { + return false; + } + if (dex_file_ == rhs.dex_file_) { + return proto_id_ == rhs.proto_id_; + } + StringPiece shorty(dex_file_->StringDataAsStringPieceByIdx(proto_id_->shorty_idx_)); + if (shorty != rhs.dex_file_->StringDataAsStringPieceByIdx(rhs.proto_id_->shorty_idx_)) { + return false; // Shorty mismatch. + } + if (shorty[0] == 'L') { + const DexFile::TypeId& return_type_id = dex_file_->GetTypeId(proto_id_->return_type_idx_); + const DexFile::TypeId& rhs_return_type_id = + rhs.dex_file_->GetTypeId(rhs.proto_id_->return_type_idx_); + if (dex_file_->StringDataAsStringPieceByIdx(return_type_id.descriptor_idx_) != + rhs.dex_file_->StringDataAsStringPieceByIdx(rhs_return_type_id.descriptor_idx_)) { + return false; // Return type mismatch. + } + } + if (shorty.find('L', 1) != StringPiece::npos) { + const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); + const DexFile::TypeList* rhs_params = rhs.dex_file_->GetProtoParameters(*rhs.proto_id_); + // Both lists are empty or have contents, or else shorty is broken. + DCHECK_EQ(params == nullptr, rhs_params == nullptr); + if (params != nullptr) { + uint32_t params_size = params->Size(); + DCHECK_EQ(params_size, rhs_params->Size()); // Parameter list size must match. + 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& rhs_param_id = + rhs.dex_file_->GetTypeId(rhs_params->GetTypeItem(i).type_idx_); + if (dex_file_->StringDataAsStringPieceByIdx(param_id.descriptor_idx_) != + rhs.dex_file_->StringDataAsStringPieceByIdx(rhs_param_id.descriptor_idx_)) { + return false; // Parameter type mismatch. + } + } + } + } + return true; + } + + bool operator!=(const Signature& rhs) const { + return !(*this == rhs); + } + + bool operator==(const StringPiece& rhs) const { + // TODO: Avoid temporary string allocation. + return ToString() == rhs; + } + + private: + Signature(const DexFile* dex, const DexFile::ProtoId& proto) : dex_file_(dex), proto_id_(&proto) { + } + + Signature() : dex_file_(nullptr), proto_id_(nullptr) { + } + + friend class DexFile; + + const DexFile* const dex_file_; + const DexFile::ProtoId* const proto_id_; +}; +std::ostream& operator<<(std::ostream& os, const Signature& sig); + // Iterate and decode class_data_item class ClassDataItemIterator { public: diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 32a8354d01..1b40529a08 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -137,14 +137,14 @@ TEST_F(DexFileTest, ClassDefs) { EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1)); } -TEST_F(DexFileTest, CreateMethodSignature) { +TEST_F(DexFileTest, GetMethodSignature) { ScopedObjectAccess soa(Thread::Current()); - const DexFile* raw(OpenTestDexFile("CreateMethodSignature")); + const DexFile* raw(OpenTestDexFile("GetMethodSignature")); ASSERT_TRUE(raw != NULL); EXPECT_EQ(1U, raw->NumClassDefs()); const DexFile::ClassDef& class_def = raw->GetClassDef(0); - ASSERT_STREQ("LCreateMethodSignature;", raw->GetClassDescriptor(class_def)); + ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def)); const byte* class_data = raw->GetClassData(class_def); ASSERT_TRUE(class_data != NULL); @@ -156,11 +156,9 @@ TEST_F(DexFileTest, CreateMethodSignature) { { ASSERT_EQ(1U, it.NumDirectMethods()); const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex()); - uint32_t proto_idx = method_id.proto_idx_; const char* name = raw->StringDataByIdx(method_id.name_idx_); ASSERT_STREQ("<init>", name); - int32_t length; - std::string signature(raw->CreateMethodSignature(proto_idx, &length)); + std::string signature(raw->GetMethodSignature(method_id).ToString()); ASSERT_EQ("()V", signature); } @@ -173,9 +171,7 @@ TEST_F(DexFileTest, CreateMethodSignature) { const char* name = raw->StringDataByIdx(method_id.name_idx_); ASSERT_STREQ("m1", name); - uint32_t proto_idx = method_id.proto_idx_; - int32_t length; - std::string signature(raw->CreateMethodSignature(proto_idx, &length)); + std::string signature(raw->GetMethodSignature(method_id).ToString()); ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature); } @@ -186,20 +182,18 @@ TEST_F(DexFileTest, CreateMethodSignature) { const char* name = raw->StringDataByIdx(method_id.name_idx_); ASSERT_STREQ("m2", name); - uint32_t proto_idx = method_id.proto_idx_; - int32_t length; - std::string signature(raw->CreateMethodSignature(proto_idx, &length)); - ASSERT_EQ("(ZSC)LCreateMethodSignature;", signature); + std::string signature(raw->GetMethodSignature(method_id).ToString()); + ASSERT_EQ("(ZSC)LGetMethodSignature;", signature); } } TEST_F(DexFileTest, FindStringId) { ScopedObjectAccess soa(Thread::Current()); - const DexFile* raw(OpenTestDexFile("CreateMethodSignature")); + const DexFile* raw(OpenTestDexFile("GetMethodSignature")); ASSERT_TRUE(raw != NULL); EXPECT_EQ(1U, raw->NumClassDefs()); - const char* strings[] = { "LCreateMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;", + const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;", "D", "I", "J", NULL }; for (size_t i = 0; strings[i] != NULL; i++) { const char* str = strings[i]; @@ -245,11 +239,10 @@ TEST_F(DexFileTest, FindMethodId) { const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_); const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_); const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature); - int32_t length; ASSERT_TRUE(found != NULL) << "Didn't find method " << i << ": " << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "." << java_lang_dex_file_->GetStringData(name) - << java_lang_dex_file_->CreateMethodSignature(to_find.proto_idx_, &length); + << java_lang_dex_file_->GetMethodSignature(to_find); EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i); } } diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 60fad6ee48..8be9b21cdf 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -228,6 +228,7 @@ static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class, const char* name, const char* sig, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Class* c = soa.Decode<Class*>(jni_class); + DCHECK(c != nullptr); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) { return NULL; } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 287e8b0959..c6db5b9a61 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -325,7 +325,7 @@ void Class::SetClassLoader(ClassLoader* new_class_loader) { SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false); } -ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature) const { +ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) const { // Check the current class before checking the interfaces. ArtMethod* method = FindDeclaredVirtualMethod(name, signature); if (method != NULL) { @@ -361,12 +361,23 @@ ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_me return NULL; } - ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const { MethodHelper mh; for (size_t i = 0; i < NumDirectMethods(); ++i) { ArtMethod* method = GetDirectMethod(i); mh.ChangeMethod(method); + if (name == mh.GetNameAsStringPiece() && mh.GetSignature() == signature) { + return method; + } + } + return NULL; +} + +ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const { + MethodHelper mh; + for (size_t i = 0; i < NumDirectMethods(); ++i) { + ArtMethod* method = GetDirectMethod(i); + mh.ChangeMethod(method); if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) { return method; } @@ -396,6 +407,16 @@ ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& s return NULL; } +ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature); + if (method != NULL) { + return method; + } + } + return NULL; +} + ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { ArtMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx); @@ -406,8 +427,20 @@ ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_metho return NULL; } +ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const { + MethodHelper mh; + for (size_t i = 0; i < NumVirtualMethods(); ++i) { + ArtMethod* method = GetVirtualMethod(i); + mh.ChangeMethod(method); + if (name == mh.GetNameAsStringPiece() && mh.GetSignature() == signature) { + return method; + } + } + return NULL; +} + ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, - const StringPiece& signature) const { + const Signature& signature) const { MethodHelper mh; for (size_t i = 0; i < NumVirtualMethods(); ++i) { ArtMethod* method = GetVirtualMethod(i); @@ -441,6 +474,16 @@ ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& return NULL; } +ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature); + if (method != NULL) { + return method; + } + } + return NULL; +} + ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { ArtMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx); @@ -451,6 +494,21 @@ ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_meth return NULL; } +ArtMethod* Class::FindClassInitializer() const { + for (size_t i = 0; i < NumDirectMethods(); ++i) { + ArtMethod* method = GetDirectMethod(i); + if (method->IsConstructor() && method->IsStatic()) { + if (kIsDebugBuild) { + MethodHelper mh(method); + CHECK_STREQ(mh.GetName(), "<clinit>"); + CHECK_STREQ(mh.GetSignature().ToString().c_str(), "()V"); + } + return method; + } + } + return NULL; +} + ArtField* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) { // Is the field in this class? // Interfaces are not relevant because they can't contain instance fields. diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 4f8ab7d90a..586151de45 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -59,6 +59,7 @@ namespace art { struct ClassClassOffsets; struct ClassOffsets; +class Signature; class StringPiece; namespace mirror { @@ -565,39 +566,53 @@ class MANAGED Class : public StaticStorageBase { ArtMethod* FindVirtualMethodForInterface(ArtMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE; - ArtMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const + ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const + ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const + ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const + ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const + ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const + ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ArtMethod* FindClassInitializer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int32_t GetIfTableCount() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); IfTable* GetIfTable() const; diff --git a/runtime/object_utils.h b/runtime/object_utils.h index 9e107a46d5..f83db903ff 100644 --- a/runtime/object_utils.h +++ b/runtime/object_utils.h @@ -504,13 +504,13 @@ class MethodHelper { return shorty_len_; } - const std::string GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const Signature GetSignature() 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.GetMethodSignature(dex_file.GetMethodId(dex_method_idx)); } else { - return "<no signature>"; + return Signature::NoSignature(); } } @@ -638,42 +638,7 @@ class MethodHelper { 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; + return dex_file.GetMethodSignature(mid) == other_dex_file.GetMethodSignature(other_mid); } const DexFile::CodeItem* GetCodeItem() diff --git a/runtime/trace.cc b/runtime/trace.cc index 7b25306177..ec95a87146 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -667,7 +667,7 @@ void Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& mh.ChangeMethod(method); os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method, PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(), - mh.GetSignature().c_str(), mh.GetDeclaringClassSourceFile()); + mh.GetSignature().ToString().c_str(), mh.GetDeclaringClassSourceFile()); } } diff --git a/runtime/utils.cc b/runtime/utils.cc index 23dcde3065..b97239fd18 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -367,11 +367,13 @@ std::string PrettyMethod(const mirror::ArtMethod* m, bool with_signature) { result += '.'; result += mh.GetName(); if (with_signature) { - std::string signature(mh.GetSignature()); - if (signature == "<no signature>") { - return result + signature; + const Signature signature = mh.GetSignature(); + std::string sig_as_string(signature.ToString()); + if (signature == Signature::NoSignature()) { + return result + sig_as_string; } - result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str()); + result = PrettyReturnType(sig_as_string.c_str()) + " " + result + + PrettyArguments(sig_as_string.c_str()); } return result; } @@ -385,11 +387,13 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with result += '.'; result += dex_file.GetMethodName(method_id); if (with_signature) { - std::string signature(dex_file.GetMethodSignature(method_id)); - if (signature == "<no signature>") { - return result + signature; + const Signature signature = dex_file.GetMethodSignature(method_id); + std::string sig_as_string(signature.ToString()); + if (signature == Signature::NoSignature()) { + return result + sig_as_string; } - result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str()); + result = PrettyReturnType(sig_as_string.c_str()) + " " + result + + PrettyArguments(sig_as_string.c_str()); } return result; } @@ -641,7 +645,7 @@ std::string JniLongName(const mirror::ArtMethod* m) { long_name += JniShortName(m); long_name += "__"; - std::string signature(MethodHelper(m).GetSignature()); + std::string signature(MethodHelper(m).GetSignature().ToString()); signature.erase(0, 1); signature.erase(signature.begin() + signature.find(')'), signature.end()); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 6b13517fdc..36b409d142 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2910,7 +2910,7 @@ const RegType& MethodVerifier::GetCaughtExceptionType() { } mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx, - MethodType method_type) { + MethodType method_type) { const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx); const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_); if (klass_type.IsConflict()) { @@ -2927,7 +2927,7 @@ mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_meth mirror::ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx); if (res_method == NULL) { const char* name = dex_file_->GetMethodName(method_id); - std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL)); + const Signature signature = dex_file_->GetMethodSignature(method_id); if (method_type == METHOD_DIRECT || method_type == METHOD_STATIC) { res_method = klass->FindDirectMethod(name, signature); diff --git a/test/Android.mk b/test/Android.mk index 6f498e8c02..08ec03a01a 100644 --- a/test/Android.mk +++ b/test/Android.mk @@ -23,8 +23,8 @@ include art/build/Android.common.mk TEST_DEX_DIRECTORIES := \ AbstractMethod \ AllFields \ - CreateMethodSignature \ ExceptionHandle \ + GetMethodSignature \ Interfaces \ Main \ MyClass \ diff --git a/test/CreateMethodSignature/CreateMethodSignature.java b/test/GetMethodSignature/GetMethodSignature.java index f6cd6ae6fd..c2ba948d60 100644 --- a/test/CreateMethodSignature/CreateMethodSignature.java +++ b/test/GetMethodSignature/GetMethodSignature.java @@ -14,7 +14,7 @@ * limitations under the License. */ -class CreateMethodSignature { +class GetMethodSignature { Float m1(int a, double b, long c, Object d) { return null; } - CreateMethodSignature m2(boolean x, short y, char z) { return null; } + GetMethodSignature m2(boolean x, short y, char z) { return null; } } |