blob: c79271d07e3be0eac2e462666d2f8e95e066b2c7 [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 Rogers45a76cb2011-07-21 22:00:15 -0700132 case 'V': return 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700133 case '[': return kPointerSize;
134 case 'L': return kPointerSize;
135 case 'D': return 8;
136 case 'J': return 8;
137 default: return 4;
138 }
139}
140
Ian Rogersdf20fe02011-07-20 20:34:16 -0700141size_t Method::ParamSize(unsigned int param) const {
142 CHECK_LT(param, NumArgs());
143 if (IsStatic()) {
144 param++; // 0th argument must skip return value at start of the shorty
145 } else if (param == 0) {
146 return kPointerSize; // this argument
147 }
148 return ShortyCharToSize(shorty_[param]);
149}
150
151size_t Method::ReturnSize() const {
152 return ShortyCharToSize(shorty_[0]);
153}
154
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700155bool Method::HasSameArgumentTypes(const Method* that) const {
Brian Carlstrom934486c2011-07-12 23:42:50 -0700156 const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700157 const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700158 const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700159 const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
160
161 // TODO: compare ProtoId objects for equality and exit early
162
163 const RawDexFile::TypeList* type_list1 = raw1->GetProtoParameters(proto1);
164 size_t arity1 = (type_list1 == NULL) ? 0 : type_list1->Size();
165 const RawDexFile::TypeList* type_list2 = raw2->GetProtoParameters(proto2);
166 size_t arity2 = (type_list2 == NULL) ? 0 : type_list2->Size();
167
168 if (arity1 != arity2) {
169 return false;
170 }
171
172 for (size_t i = 0; i < arity1; ++i) {
173 uint32_t type_idx1 = type_list1->GetTypeItem(i).type_idx_;
174 const char* type1 = raw1->dexStringByTypeIdx(type_idx1);
175
176 uint32_t type_idx2 = type_list2->GetTypeItem(i).type_idx_;
177 const char* type2 = raw2->dexStringByTypeIdx(type_idx2);
178
179 if (strcmp(type1, type2) != 0) {
180 return false;
181 }
182 }
183
184 return true;
185}
186
187bool Method::HasSameReturnType(const Method* that) const {
Brian Carlstrom934486c2011-07-12 23:42:50 -0700188 const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700189 const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
190 const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_);
191
Brian Carlstrom934486c2011-07-12 23:42:50 -0700192 const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700193 const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
194 const char* type2 = raw2->dexStringByTypeIdx(proto2.return_type_idx_);
195
196 return (strcmp(type1, type2) == 0);
197}
198
Ian Rogersb033c752011-07-20 12:22:35 -0700199Method* Class::FindDirectMethod(const StringPiece& name) const {
200 Method* result = NULL;
201 for (size_t i = 0; i < NumDirectMethods(); i++) {
202 Method* method = GetDirectMethod(i);
203 if (method->GetName().compare(name) == 0) {
204 result = method;
205 break;
206 }
207 }
208 return result;
209}
210
211Method* Class::FindVirtualMethod(const StringPiece& name) const {
212 Method* result = NULL;
213 for (size_t i = 0; i < NumVirtualMethods(); i++) {
214 Method* method = GetVirtualMethod(i);
215 if (method->GetName().compare(name) == 0) {
216 result = method;
217 break;
218 }
219 }
220 return result;
221}
222
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700223Method* Class::FindDirectMethodLocally(const StringPiece& name,
224 const StringPiece& descriptor) const {
225 return NULL; // TODO
226}
227
Elliott Hughes1f359b02011-07-17 14:27:17 -0700228static const char* kClassStatusNames[] = {
229 "Error",
230 "NotReady",
231 "Idx",
232 "Loaded",
233 "Resolved",
234 "Verifying",
235 "Verified",
236 "Initializing",
237 "Initialized"
238};
239std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
240 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
241 os << kClassStatusNames[rhs - 1];
242 } else {
Ian Rogersb033c752011-07-20 12:22:35 -0700243 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -0700244 }
245 return os;
246}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700247
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700248} // namespace art