| // Copyright 2011 Google Inc. All Rights Reserved. |
| |
| #include "src/globals.h" |
| #include "src/logging.h" |
| #include "src/object.h" |
| #include "src/dex_file.h" |
| #include "src/raw_dex_file.h" |
| |
| #include <algorithm> |
| |
| namespace art { |
| |
| bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) { |
| size_t i = 0; |
| while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) { |
| ++i; |
| } |
| if (descriptor1.find('/', i) != StringPiece::npos || |
| descriptor2.find('/', i) != StringPiece::npos) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| #if 0 |
| bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) { |
| size_t size = std::min(descriptor1.size(), descriptor2.size()); |
| std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos; |
| pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size, descriptor2.begin()); |
| return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos); |
| } |
| #endif |
| |
| bool Class::IsInSamePackage(const Class* that) const { |
| const Class* klass1 = this; |
| const Class* klass2 = that; |
| if (klass1 == klass2) { |
| return true; |
| } |
| // Class loaders must match. |
| if (klass1->GetClassLoader() != klass2->GetClassLoader()) { |
| return false; |
| } |
| // Arrays are in the same package when their element classes are. |
| if (klass1->IsArray()) { |
| klass1 = klass1->GetComponentType(); |
| } |
| if (klass2->IsArray()) { |
| klass2 = klass2->GetComponentType(); |
| } |
| // Compare the package part of the descriptor string. |
| return IsInSamePackage(klass1->descriptor_, klass2->descriptor_); |
| } |
| |
| uint32_t Method::NumArgRegisters() { |
| CHECK(shorty_ != NULL); |
| uint32_t num_registers = 0; |
| for (int i = 1; i < shorty_.length(); ++i) { |
| char ch = shorty_[i]; |
| if (ch == 'D' || ch == 'J') { |
| num_registers += 2; |
| } else { |
| num_registers += 1; |
| } |
| } |
| return num_registers; |
| } |
| |
| bool Method::HasSameArgumentTypes(const Method* that) const { |
| const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw(); |
| const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_); |
| const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw(); |
| const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_); |
| |
| // TODO: compare ProtoId objects for equality and exit early |
| |
| const RawDexFile::TypeList* type_list1 = raw1->GetProtoParameters(proto1); |
| size_t arity1 = (type_list1 == NULL) ? 0 : type_list1->Size(); |
| const RawDexFile::TypeList* type_list2 = raw2->GetProtoParameters(proto2); |
| size_t arity2 = (type_list2 == NULL) ? 0 : type_list2->Size(); |
| |
| if (arity1 != arity2) { |
| return false; |
| } |
| |
| for (size_t i = 0; i < arity1; ++i) { |
| uint32_t type_idx1 = type_list1->GetTypeItem(i).type_idx_; |
| const char* type1 = raw1->dexStringByTypeIdx(type_idx1); |
| |
| uint32_t type_idx2 = type_list2->GetTypeItem(i).type_idx_; |
| const char* type2 = raw2->dexStringByTypeIdx(type_idx2); |
| |
| if (strcmp(type1, type2) != 0) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool Method::HasSameReturnType(const Method* that) const { |
| const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw(); |
| const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_); |
| const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_); |
| |
| const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw(); |
| const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_); |
| const char* type2 = raw2->dexStringByTypeIdx(proto2.return_type_idx_); |
| |
| return (strcmp(type1, type2) == 0); |
| } |
| |
| Method* Class::FindDirectMethodLocally(const StringPiece& name, |
| const StringPiece& descriptor) const { |
| return NULL; // TODO |
| } |
| |
| static const char* kClassStatusNames[] = { |
| "Error", |
| "NotReady", |
| "Idx", |
| "Loaded", |
| "Resolved", |
| "Verifying", |
| "Verified", |
| "Initializing", |
| "Initialized" |
| }; |
| std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) { |
| if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) { |
| os << kClassStatusNames[rhs - 1]; |
| } else { |
| os << "Class::Status[" << int(rhs) << "]"; |
| } |
| return os; |
| } |
| |
| } // namespace art |