blob: c8bd353d71ae17cd059ff1defe7e533423de2808 [file] [log] [blame]
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Ian Rogersb033c752011-07-20 12:22:35 -07003#include "src/object.h"
Ian Rogersb033c752011-07-20 12:22:35 -07004#include <string.h>
Ian Rogersdf20fe02011-07-20 20:34:16 -07005#include <algorithm>
Carl Shapiro3ee755d2011-06-28 12:11:04 -07006#include "src/globals.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -07007#include "src/logging.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07008#include "src/dex_file.h"
9#include "src/raw_dex_file.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -070010
11namespace art {
12
Ian Rogersb033c752011-07-20 12:22:35 -070013bool Class::IsInSamePackage(const StringPiece& descriptor1,
14 const StringPiece& descriptor2) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070015 size_t i = 0;
16 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
17 ++i;
18 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -070019 if (descriptor1.find('/', i) != StringPiece::npos ||
20 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070021 return false;
22 } else {
23 return true;
24 }
25}
26
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070027#if 0
Ian Rogersb033c752011-07-20 12:22:35 -070028bool Class::IsInSamePackage(const StringPiece& descriptor1,
29 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070030 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -070031 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -070032 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
33 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070034 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
35}
36#endif
37
Carl Shapiro894d0fa2011-06-30 14:48:49 -070038bool Class::IsInSamePackage(const Class* that) const {
39 const Class* klass1 = this;
40 const Class* klass2 = that;
41 if (klass1 == klass2) {
42 return true;
43 }
44 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070045 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -070046 return false;
47 }
48 // Arrays are in the same package when their element classes are.
49 if (klass1->IsArray()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070050 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -070051 }
52 if (klass2->IsArray()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070053 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -070054 }
55 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -070056 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -070057}
58
Carl Shapiro3ee755d2011-06-28 12:11:04 -070059uint32_t Method::NumArgRegisters() {
60 CHECK(shorty_ != NULL);
61 uint32_t num_registers = 0;
Carl Shapiro565f5072011-07-10 13:39:43 -070062 for (int i = 1; i < shorty_.length(); ++i) {
Carl Shapiro3ee755d2011-06-28 12:11:04 -070063 char ch = shorty_[i];
64 if (ch == 'D' || ch == 'J') {
65 num_registers += 2;
66 } else {
67 num_registers += 1;
68 }
69 }
70 return num_registers;
71}
72
Ian Rogersb033c752011-07-20 12:22:35 -070073// The number of reference arguments to this method including implicit this
74// pointer
75size_t Method::NumReferenceArgs() const {
76 size_t result = IsStatic() ? 0 : 1;
77 for (int i = 1; i < shorty_.length(); i++) {
78 if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
79 result++;
80 }
81 }
82 return result;
83}
84
85// The number of long or double arguments
86size_t Method::NumLongOrDoubleArgs() const {
87 size_t result = 0;
88 for (int i = 1; i < shorty_.length(); i++) {
89 if ((shorty_[i] == 'D') || (shorty_[i] == 'J')) {
90 result++;
91 }
92 }
93 return result;
94}
95
96// The number of reference arguments to this method before the given parameter
97// index
98size_t Method::NumReferenceArgsBefore(unsigned int param) const {
99 CHECK_LT(param, NumArgs());
100 unsigned int result = IsStatic() ? 0 : 1;
101 for (unsigned int i = 1; (i < (unsigned int)shorty_.length()) &&
102 (i < (param + 1)); i++) {
103 if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
104 result++;
105 }
106 }
107 return result;
108}
109
110// Is the given method parameter a reference?
111bool Method::IsParamAReference(unsigned int param) const {
112 CHECK_LT(param, NumArgs());
113 if (IsStatic()) {
114 param++; // 0th argument must skip return value at start of the shorty
115 } else if (param == 0) {
116 return true; // this argument
117 }
118 return ((shorty_[param] == 'L') || (shorty_[param] == '['));
119}
120
121// Is the given method parameter a long or double?
122bool Method::IsParamALongOrDouble(unsigned int param) const {
123 CHECK_LT(param, NumArgs());
124 if (IsStatic()) {
125 param++; // 0th argument must skip return value at start of the shorty
126 }
127 return (shorty_[param] == 'J') || (shorty_[param] == 'D');
128}
129
Ian Rogersdf20fe02011-07-20 20:34:16 -0700130static size_t ShortyCharToSize(char x) {
131 switch (x) {
Ian Rogersb033c752011-07-20 12:22:35 -0700132 case '[': return kPointerSize;
133 case 'L': return kPointerSize;
134 case 'D': return 8;
135 case 'J': return 8;
136 default: return 4;
137 }
138}
139
Ian Rogersdf20fe02011-07-20 20:34:16 -0700140size_t Method::ParamSize(unsigned int param) const {
141 CHECK_LT(param, NumArgs());
142 if (IsStatic()) {
143 param++; // 0th argument must skip return value at start of the shorty
144 } else if (param == 0) {
145 return kPointerSize; // this argument
146 }
147 return ShortyCharToSize(shorty_[param]);
148}
149
150size_t Method::ReturnSize() const {
151 return ShortyCharToSize(shorty_[0]);
152}
153
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700154bool Method::HasSameArgumentTypes(const Method* that) const {
Brian Carlstrom934486c2011-07-12 23:42:50 -0700155 const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700156 const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700157 const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700158 const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
159
160 // TODO: compare ProtoId objects for equality and exit early
161
162 const RawDexFile::TypeList* type_list1 = raw1->GetProtoParameters(proto1);
163 size_t arity1 = (type_list1 == NULL) ? 0 : type_list1->Size();
164 const RawDexFile::TypeList* type_list2 = raw2->GetProtoParameters(proto2);
165 size_t arity2 = (type_list2 == NULL) ? 0 : type_list2->Size();
166
167 if (arity1 != arity2) {
168 return false;
169 }
170
171 for (size_t i = 0; i < arity1; ++i) {
172 uint32_t type_idx1 = type_list1->GetTypeItem(i).type_idx_;
173 const char* type1 = raw1->dexStringByTypeIdx(type_idx1);
174
175 uint32_t type_idx2 = type_list2->GetTypeItem(i).type_idx_;
176 const char* type2 = raw2->dexStringByTypeIdx(type_idx2);
177
178 if (strcmp(type1, type2) != 0) {
179 return false;
180 }
181 }
182
183 return true;
184}
185
186bool Method::HasSameReturnType(const Method* that) const {
Brian Carlstrom934486c2011-07-12 23:42:50 -0700187 const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700188 const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
189 const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_);
190
Brian Carlstrom934486c2011-07-12 23:42:50 -0700191 const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700192 const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
193 const char* type2 = raw2->dexStringByTypeIdx(proto2.return_type_idx_);
194
195 return (strcmp(type1, type2) == 0);
196}
197
Ian Rogersb033c752011-07-20 12:22:35 -0700198Method* Class::FindDirectMethod(const StringPiece& name) const {
199 Method* result = NULL;
200 for (size_t i = 0; i < NumDirectMethods(); i++) {
201 Method* method = GetDirectMethod(i);
202 if (method->GetName().compare(name) == 0) {
203 result = method;
204 break;
205 }
206 }
207 return result;
208}
209
210Method* Class::FindVirtualMethod(const StringPiece& name) const {
211 Method* result = NULL;
212 for (size_t i = 0; i < NumVirtualMethods(); i++) {
213 Method* method = GetVirtualMethod(i);
214 if (method->GetName().compare(name) == 0) {
215 result = method;
216 break;
217 }
218 }
219 return result;
220}
221
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700222Method* Class::FindDirectMethodLocally(const StringPiece& name,
223 const StringPiece& descriptor) const {
224 return NULL; // TODO
225}
226
Elliott Hughes1f359b02011-07-17 14:27:17 -0700227static const char* kClassStatusNames[] = {
228 "Error",
229 "NotReady",
230 "Idx",
231 "Loaded",
232 "Resolved",
233 "Verifying",
234 "Verified",
235 "Initializing",
236 "Initialized"
237};
238std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
239 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
240 os << kClassStatusNames[rhs - 1];
241 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700242 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700243 }
244 return os;
245}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700246
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700247} // namespace art