blob: 0c93b4383c21cc57ac203243bc34271163d0cb52 [file] [log] [blame]
Ian Rogers6d4d9fc2011-11-30 16:24:48 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_SRC_OBJECT_UTILS_H_
18#define ART_SRC_OBJECT_UTILS_H_
19
20#include "class_linker.h"
21#include "dex_cache.h"
22#include "dex_file.h"
23#include "object.h"
24#include "runtime.h"
Elliott Hughes91250e02011-12-13 22:30:35 -080025#include "UniquePtr.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080026
27#include <string>
28
29namespace art {
30
31class ClassHelper {
32 public:
Elliott Hughes91250e02011-12-13 22:30:35 -080033 ClassHelper(const Class* c = NULL, ClassLinker* l = NULL)
34 : class_def_(NULL),
35 class_linker_(l),
36 dex_cache_(NULL),
37 dex_file_(NULL),
38 interface_type_list_(NULL),
39 klass_(c) {
40 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080041
42 void ChangeClass(const Class* new_c) {
43 DCHECK(new_c != NULL);
44 if (dex_cache_ != NULL) {
45 DexCache* new_c_dex_cache = new_c->GetDexCache();
46 if (new_c_dex_cache != dex_cache_) {
47 dex_cache_ = new_c_dex_cache;
48 dex_file_ = NULL;
49 }
50 }
51 klass_ = new_c;
52 interface_type_list_ = NULL;
53 class_def_ = NULL;
54 }
55
Elliott Hughes91250e02011-12-13 22:30:35 -080056 // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
57 // If you need it longer, copy it into a std::string.
58 const char* GetDescriptor() {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080059 if (klass_->IsArrayClass()) {
Elliott Hughes95572412011-12-13 18:14:20 -080060 std::string result("[");
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080061 const Class* saved_klass = klass_;
62 ChangeClass(klass_->GetComponentType());
63 result += GetDescriptor();
64 ChangeClass(saved_klass);
Elliott Hughes91250e02011-12-13 22:30:35 -080065 descriptor_ = result;
66 return descriptor_.c_str();
67 } else if (klass_->IsPrimitive()) {
68 return Primitive::Descriptor(klass_->GetPrimitiveType());
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080069 } else if (klass_->IsProxyClass()) {
Elliott Hughes91250e02011-12-13 22:30:35 -080070 descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
71 return descriptor_.c_str();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080072 } else {
73 const DexFile& dex_file = GetDexFile();
74 const DexFile::TypeId& type_id = dex_file.GetTypeId(klass_->GetDexTypeIndex());
75 return dex_file.GetTypeDescriptor(type_id);
76 }
77 }
Elliott Hughes91250e02011-12-13 22:30:35 -080078
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080079 const DexFile::ClassDef* GetClassDef() {
80 const DexFile::ClassDef* result = class_def_;
81 if (result == NULL) {
82 result = GetDexFile().FindClassDef(GetDescriptor());
83 class_def_ = result;
84 }
85 return result;
86 }
Elliott Hughes91250e02011-12-13 22:30:35 -080087
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080088 uint32_t NumInterfaces() {
89 if (klass_->IsPrimitive()) {
90 return 0;
91 } else if (klass_->IsArrayClass()) {
92 return 2;
93 } else {
94 CHECK(!klass_->IsProxyClass());
95 const DexFile::TypeList* interfaces = GetInterfaceTypeList();
96 if (interfaces == NULL) {
97 return 0;
98 } else {
99 return interfaces->Size();
100 }
101 }
102 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800103
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800104 uint16_t GetInterfaceTypeIdx(uint32_t idx) {
105 DCHECK(!klass_->IsPrimitive());
106 DCHECK(!klass_->IsArrayClass());
107 return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
108 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800109
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800110 Class* GetInterface(uint32_t idx) {
111 DCHECK(!klass_->IsPrimitive());
112 if (klass_->IsArrayClass()) {
113 if (idx == 0) {
114 return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
115 } else {
116 DCHECK_EQ(1U, idx);
117 return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
118 }
119 } else {
120 uint16_t type_idx = GetInterfaceTypeIdx(idx);
121 Class* interface = GetDexCache()->GetResolvedType(type_idx);
122 if (interface == NULL) {
123 interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
124 CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
125 }
126 return interface;
127 }
128 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800129
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800130 const char* GetSourceFile() {
Elliott Hughes95572412011-12-13 18:14:20 -0800131 std::string descriptor(GetDescriptor());
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800132 const DexFile& dex_file = GetDexFile();
133 const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
134 if (dex_class_def == NULL) {
135 return NULL;
136 } else {
137 return dex_file.GetSourceFile(*dex_class_def);
138 }
139 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800140
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800141 std::string GetLocation() {
142 return GetDexCache()->GetLocation()->ToModifiedUtf8();
143 }
144
145 const DexFile& GetDexFile() {
146 const DexFile* result = dex_file_;
147 if (result == NULL) {
148 const DexCache* dex_cache = GetDexCache();
149 result = &GetClassLinker()->FindDexFile(dex_cache);
150 dex_file_ = result;
151 }
152 return *result;
153 }
154
155 private:
156 const DexFile::TypeList* GetInterfaceTypeList() {
157 const DexFile::TypeList* result = interface_type_list_;
158 if (result == NULL) {
159 const DexFile::ClassDef* class_def = GetClassDef();
160 if (class_def != NULL) {
161 result = GetDexFile().GetInterfacesList(*class_def);
162 interface_type_list_ = result;
163 }
164 }
165 return result;
166 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800167
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800168 DexCache* GetDexCache() {
169 DexCache* result = dex_cache_;
170 if (result == NULL) {
171 result = klass_->GetDexCache();
172 dex_cache_ = result;
173 }
174 return result;
175 }
Elliott Hughes91250e02011-12-13 22:30:35 -0800176
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800177 ClassLinker* GetClassLinker() {
178 ClassLinker* result = class_linker_;
179 if (result == NULL) {
180 result = Runtime::Current()->GetClassLinker();
181 class_linker_ = result;
182 }
183 return result;
184 }
185
186 const DexFile::ClassDef* class_def_;
187 ClassLinker* class_linker_;
188 DexCache* dex_cache_;
189 const DexFile* dex_file_;
190 const DexFile::TypeList* interface_type_list_;
191 const Class* klass_;
Elliott Hughes91250e02011-12-13 22:30:35 -0800192 std::string descriptor_;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800193
194 DISALLOW_COPY_AND_ASSIGN(ClassHelper);
195};
196
197class FieldHelper {
198 public:
199 FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {}
200 FieldHelper(const Field* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
201 FieldHelper(const Field* f, ClassLinker* l) : class_linker_(l), dex_cache_(NULL), dex_file_(NULL),
202 field_(f) {}
203
204 void ChangeField(const Field* new_f) {
205 DCHECK(new_f != NULL);
206 if (dex_cache_ != NULL) {
207 DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache();
208 if (new_f_dex_cache != dex_cache_) {
209 dex_cache_ = new_f_dex_cache;
210 dex_file_ = NULL;
211 }
212 }
213 field_ = new_f;
214 }
215 const char* GetName() {
216 const DexFile& dex_file = GetDexFile();
217 return dex_file.GetFieldName(dex_file.GetFieldId(field_->GetDexFieldIndex()));
218 }
219 String* GetNameAsString() {
220 const DexFile& dex_file = GetDexFile();
221 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
222 return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache());
223 }
224 Class* GetType() {
225 const DexFile& dex_file = GetDexFile();
226 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
227 Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
228 if (type == NULL) {
229 type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
230 CHECK(type != NULL || Thread::Current()->IsExceptionPending());
231 }
232 return type;
233 }
234 const char* GetTypeDescriptor() {
235 const DexFile& dex_file = GetDexFile();
236 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
237 return dex_file.GetFieldTypeDescriptor(field_id);
238 }
239 Primitive::Type GetTypeAsPrimitiveType() {
240 return Primitive::GetType(GetTypeDescriptor()[0]);
241 }
242 bool IsPrimitiveType() {
243 Primitive::Type type = GetTypeAsPrimitiveType();
244 return type != Primitive::kPrimNot;
245 }
246 size_t FieldSize() {
247 Primitive::Type type = GetTypeAsPrimitiveType();
248 return Primitive::FieldSize(type);
249 }
250 const char* GetDeclaringClassDescriptor() {
251 uint16_t type_idx = field_->GetDeclaringClass()->GetDexTypeIndex();
252 const DexFile& dex_file = GetDexFile();
253 return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
254 }
255
256 private:
257 DexCache* GetDexCache() {
258 DexCache* result = dex_cache_;
259 if (result == NULL) {
260 result = field_->GetDeclaringClass()->GetDexCache();
261 dex_cache_ = result;
262 }
263 return result;
264 }
265 ClassLinker* GetClassLinker() {
266 ClassLinker* result = class_linker_;
267 if (result == NULL) {
268 result = Runtime::Current()->GetClassLinker();
269 class_linker_ = result;
270 }
271 return result;
272 }
273 const DexFile& GetDexFile() {
274 const DexFile* result = dex_file_;
275 if (result == NULL) {
276 const DexCache* dex_cache = GetDexCache();
277 result = &GetClassLinker()->FindDexFile(dex_cache);
278 dex_file_ = result;
279 }
280 return *result;
281 }
282
283 ClassLinker* class_linker_;
284 DexCache* dex_cache_;
285 const DexFile* dex_file_;
286 const Field* field_;
287
288 DISALLOW_COPY_AND_ASSIGN(FieldHelper);
289};
290
291class MethodHelper {
292 public:
293 MethodHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL),
294 shorty_(NULL), shorty_len_(0) {}
295 MethodHelper(const Method* m) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL),
296 method_(NULL), shorty_(NULL), shorty_len_(0) {
297 SetMethod(m);
298 }
299 MethodHelper(const Method* m, ClassLinker* l) : class_linker_(l), dex_cache_(NULL),
300 dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) {
301 SetMethod(m);
302 }
303
304 void ChangeMethod(Method* new_m) {
305 DCHECK(new_m != NULL);
306 if (dex_cache_ != NULL) {
307 Class* klass = new_m->GetDeclaringClass();
308 if (klass->IsProxyClass()) {
309 dex_cache_ = NULL;
310 dex_file_ = NULL;
311 } else {
312 DexCache* new_m_dex_cache = klass->GetDexCache();
313 if (new_m_dex_cache != dex_cache_) {
314 dex_cache_ = new_m_dex_cache;
315 dex_file_ = NULL;
316 }
317 }
318 }
319 SetMethod(new_m);
320 shorty_ = NULL;
321 }
322 const char* GetName() {
323 const DexFile& dex_file = GetDexFile();
324 return dex_file.GetMethodName(dex_file.GetMethodId(method_->GetDexMethodIndex()));
325 }
326 String* GetNameAsString() {
327 const DexFile& dex_file = GetDexFile();
328 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
329 return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
330 }
331 const char* GetShorty() {
332 const char* result = shorty_;
333 if (result == NULL) {
334 const DexFile& dex_file = GetDexFile();
335 result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
336 &shorty_len_);
337 shorty_ = result;
338 }
339 return result;
340 }
341 int32_t GetShortyLength() {
342 if (shorty_ == NULL) {
343 GetShorty();
344 }
345 return shorty_len_;
346 }
347 const std::string GetSignature() {
348 const DexFile& dex_file = GetDexFile();
349 return dex_file.GetMethodSignature(dex_file.GetMethodId(method_->GetDexMethodIndex()));
350 }
351 const DexFile::ProtoId& GetPrototype() {
352 const DexFile& dex_file = GetDexFile();
353 return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
354 }
355 const DexFile::TypeList* GetParameterTypeList() {
356 const DexFile::ProtoId& proto = GetPrototype();
357 return GetDexFile().GetProtoParameters(proto);
358 }
359 ObjectArray<Class>* GetParameterTypes() {
360 const DexFile::TypeList* params = GetParameterTypeList();
361 Class* array_class = GetClassLinker()->FindSystemClass("[Ljava/lang/Class;");
362 uint32_t num_params = params == NULL ? 0 : params->Size();
363 ObjectArray<Class>* result = ObjectArray<Class>::Alloc(array_class, num_params);
364 for (uint32_t i = 0; i < num_params; i++) {
365 Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_);
366 result->Set(i, param_type);
367 }
368 return result;
369 }
370 Class* GetReturnType() {
371 const DexFile& dex_file = GetDexFile();
372 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
373 const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
374 uint16_t return_type_idx = proto_id.return_type_idx_;
375 return GetClassFromTypeIdx(return_type_idx);
376 }
377 const char* GetReturnTypeDescriptor() {
378 const DexFile& dex_file = GetDexFile();
379 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
380 const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
381 uint16_t return_type_idx = proto_id.return_type_idx_;
382 return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
383 }
384 int32_t GetLineNumFromNativePC(uintptr_t raw_pc) {
385 const DexFile& dex_file = GetDexFile();
386 return dex_file.GetLineNumFromPC(method_, method_->ToDexPC(raw_pc));
387 }
388 const char* GetDeclaringClassDescriptor() {
389 Class* klass = method_->GetDeclaringClass();
390 CHECK(!klass->IsProxyClass());
391 uint16_t type_idx = klass->GetDexTypeIndex();
392 const DexFile& dex_file = GetDexFile();
393 return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
394 }
395 const char* GetDeclaringClassSourceFile() {
396 const char* descriptor = GetDeclaringClassDescriptor();
397 const DexFile& dex_file = GetDexFile();
398 const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
399 if (dex_class_def == NULL) {
400 return NULL;
401 } else {
402 return dex_file.GetSourceFile(*dex_class_def);
403 }
404 }
405 bool IsStatic() {
406 return method_->IsStatic();
407 }
408 bool IsClassInitializer() {
409 return IsStatic() && StringPiece(GetName()) == "<clinit>";
410 }
411 size_t NumArgs() {
412 // "1 +" because the first in Args is the receiver.
413 // "- 1" because we don't count the return type.
414 return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
415 }
416 // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods
417 bool IsParamALongOrDouble(size_t param) {
418 CHECK_LT(param, NumArgs());
419 if (IsStatic()) {
420 param++; // 0th argument must skip return value at start of the shorty
421 } else if (param == 0) {
422 return false; // this argument
423 }
424 char ch = GetShorty()[param];
425 return (ch == 'J' || ch == 'D');
426 }
427 // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods
428 bool IsParamAReference(size_t param) {
429 CHECK_LT(param, NumArgs());
430 if (IsStatic()) {
431 param++; // 0th argument must skip return value at start of the shorty
432 } else if (param == 0) {
433 return true; // this argument
434 }
435 return GetShorty()[param] == 'L'; // An array also has a shorty character of 'L' (not '[')
436 }
437 bool HasSameNameAndSignature(MethodHelper* other) {
438 StringPiece name(GetName());
439 StringPiece other_name(other->GetName());
440 if (name != other_name) {
441 return false;
442 }
443 if (GetDexCache() == other->GetDexCache()) {
444 const DexFile& dex_file = GetDexFile();
445 const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
446 const DexFile::MethodId& other_mid =
447 dex_file.GetMethodId(other->method_->GetDexMethodIndex());
448 return mid.proto_idx_ == other_mid.proto_idx_;
449 }
450 return GetSignature() == other->GetSignature();
451 }
452 const DexFile::CodeItem* GetCodeItem() {
453 return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
454 }
Ian Rogers6f1dfe42011-12-08 17:28:34 -0800455 bool IsResolvedTypeIdx(uint16_t type_idx) const {
456 return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
457 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800458 Class* GetClassFromTypeIdx(uint16_t type_idx) {
459 Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
460 if (type == NULL) {
461 type = GetClassLinker()->ResolveType(type_idx, method_);
462 CHECK(type != NULL || Thread::Current()->IsExceptionPending());
463 }
464 return type;
465 }
466 const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
467 const DexFile& dex_file = GetDexFile();
468 return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
469 }
470 Class* GetDexCacheResolvedType(uint16_t type_idx) {
471 return GetDexCache()->GetResolvedType(type_idx);
472 }
473 const DexFile& GetDexFile() {
474 const DexFile* result = dex_file_;
475 if (result == NULL) {
476 const DexCache* dex_cache = GetDexCache();
477 result = &GetClassLinker()->FindDexFile(dex_cache);
478 dex_file_ = result;
479 }
480 return *result;
481 }
482 private:
483 // Set the method_ field, for proxy methods looking up the interface method via the resolved
484 // methods table.
485 void SetMethod(const Method* method) {
486 if (method != NULL) {
487 Class* klass = method->GetDeclaringClass();
488 if (klass->IsProxyClass()) {
489 method = method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
490 CHECK(method != NULL);
491 }
492 }
493 method_ = method;
494 }
495 DexCache* GetDexCache() {
496 DexCache* result = dex_cache_;
497 if (result == NULL) {
498 Class* klass = method_->GetDeclaringClass();
499 result = klass->GetDexCache();
500 dex_cache_ = result;
501 }
502 return result;
503 }
504 ClassLinker* GetClassLinker() {
505 ClassLinker* result = class_linker_;
506 if (result == NULL) {
507 result = Runtime::Current()->GetClassLinker();
508 class_linker_ = result;
509 }
510 return result;
511 }
512
513 ClassLinker* class_linker_;
514 DexCache* dex_cache_;
515 const DexFile* dex_file_;
516 const Method* method_;
517 const char* shorty_;
518 int32_t shorty_len_;
519
520 DISALLOW_COPY_AND_ASSIGN(MethodHelper);
521};
522
523} // namespace art
524
525#endif // ART_SRC_OBJECT_UTILS_H_