blob: 27cbb412f09569c0815f779b4dd12e9e9e0c56a0 [file] [log] [blame]
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "object.h"
4
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <string.h>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07006
Ian Rogersdf20fe02011-07-20 20:34:16 -07007#include <algorithm>
Elliott Hughes9d5ccec2011-09-19 13:19:50 -07008#include <iostream>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07009#include <string>
10#include <utility>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070011
Elliott Hughesd8ddfd52011-08-15 14:32:53 -070012#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070013#include "class_loader.h"
Elliott Hughes54e7df12011-09-16 11:47:04 -070014#include "dex_cache.h"
15#include "dex_file.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070016#include "globals.h"
Brian Carlstroma40f9bc2011-07-26 21:26:07 -070017#include "heap.h"
Elliott Hughescf4c6c42011-09-01 15:16:42 -070018#include "intern_table.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070019#include "logging.h"
Elliott Hughes54e7df12011-09-16 11:47:04 -070020#include "monitor.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070021#include "runtime.h"
Elliott Hughes68e76522011-10-05 13:22:16 -070022#include "stack.h"
Ian Rogers0571d352011-11-03 19:51:38 -070023#include "utils.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -070024
25namespace art {
26
Elliott Hughes081be7f2011-09-18 16:50:26 -070027Object* Object::Clone() {
28 Class* c = GetClass();
29 DCHECK(!c->IsClassClass());
30
31 // Object::SizeOf gets the right size even if we're an array.
32 // Using c->AllocObject() here would be wrong.
33 size_t num_bytes = SizeOf();
Brian Carlstrom40381fb2011-10-19 14:13:40 -070034 SirtRef<Object> copy(Heap::AllocObject(c, num_bytes));
35 if (copy.get() == NULL) {
Elliott Hughes081be7f2011-09-18 16:50:26 -070036 return NULL;
37 }
38
39 // Copy instance data. We assume memcpy copies by words.
40 // TODO: expose and use move32.
41 byte* src_bytes = reinterpret_cast<byte*>(this);
Brian Carlstrom40381fb2011-10-19 14:13:40 -070042 byte* dst_bytes = reinterpret_cast<byte*>(copy.get());
Elliott Hughes081be7f2011-09-18 16:50:26 -070043 size_t offset = sizeof(Object);
44 memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
45
Elliott Hughes20cde902011-10-04 17:37:27 -070046 if (c->IsFinalizable()) {
Ian Rogers5d4bdc22011-11-02 22:15:43 -070047 Heap::AddFinalizerReference(Thread::Current(), copy.get());
Elliott Hughes20cde902011-10-04 17:37:27 -070048 }
Elliott Hughes081be7f2011-09-18 16:50:26 -070049
Brian Carlstrom40381fb2011-10-19 14:13:40 -070050 return copy.get();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070051}
52
Brian Carlstrom24a3c2e2011-10-17 18:07:52 -070053uint32_t Object::GetThinLockId() {
54 return Monitor::GetThinLockId(monitor_);
Elliott Hughes5f791332011-09-15 17:45:30 -070055}
56
Elliott Hughes081be7f2011-09-18 16:50:26 -070057bool Object::IsString() const {
58 // TODO use "klass_ == String::GetJavaLangString()" instead?
59 return GetClass() == GetClass()->GetDescriptor()->GetClass();
60}
61
Elliott Hughes5f791332011-09-15 17:45:30 -070062void Object::MonitorEnter(Thread* thread) {
63 Monitor::MonitorEnter(thread, this);
64}
65
Ian Rogersff1ed472011-09-20 13:46:24 -070066bool Object::MonitorExit(Thread* thread) {
67 return Monitor::MonitorExit(thread, this);
Elliott Hughes5f791332011-09-15 17:45:30 -070068}
69
70void Object::Notify() {
71 Monitor::Notify(Thread::Current(), this);
72}
73
74void Object::NotifyAll() {
75 Monitor::NotifyAll(Thread::Current(), this);
76}
77
78void Object::Wait(int64_t ms, int32_t ns) {
79 Monitor::Wait(Thread::Current(), this, ms, ns, true);
80}
81
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070082// TODO: get global references for these
83Class* Field::java_lang_reflect_Field_ = NULL;
84
85void Field::SetClass(Class* java_lang_reflect_Field) {
86 CHECK(java_lang_reflect_Field_ == NULL);
87 CHECK(java_lang_reflect_Field != NULL);
88 java_lang_reflect_Field_ = java_lang_reflect_Field;
89}
90
91void Field::ResetClass() {
92 CHECK(java_lang_reflect_Field_ != NULL);
93 java_lang_reflect_Field_ = NULL;
94}
95
96void Field::SetTypeIdx(uint32_t type_idx) {
97 SetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), type_idx, false);
98}
99
100Class* Field::GetTypeDuringLinking() const {
101 // We are assured that the necessary primitive types are in the dex cache
102 // early during class linking
103 return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
104}
105
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700106bool Field::IsPrimitiveType() const {
107 Class* type = GetTypeDuringLinking();
108 return (type == NULL || type->IsPrimitive());
109}
110
111Primitive::Type Field::GetPrimitiveType() const {
112 Class* type = GetTypeDuringLinking();
113 if (type == NULL) {
114 return Primitive::kPrimNot;
115 }
116 return type->GetPrimitiveType();
117}
118
119size_t Field::PrimitiveSize() const {
120 return Primitive::FieldSize(GetPrimitiveType());
121}
122
123const char* Field::GetTypeDescriptor() const {
124 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
125 const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
Ian Rogers0571d352011-11-03 19:51:38 -0700126 const char* descriptor = dex_file.StringByTypeIdx(GetTypeIdx());
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700127 DCHECK(descriptor != NULL);
128 return descriptor;
129}
130
Ian Rogers5d76c432011-10-31 21:42:49 -0700131Class* Field::GetType() {
132 Class* type = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, type_), false);
133 if (type == NULL) {
134 type = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
135 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, type_), type, false);
Elliott Hughes80609252011-09-23 17:24:51 -0700136 }
Ian Rogers5d76c432011-10-31 21:42:49 -0700137 return type;
Elliott Hughes80609252011-09-23 17:24:51 -0700138}
139
Ian Rogers0571d352011-11-03 19:51:38 -0700140void Field::SetOffset(MemberOffset num_bytes) {
141 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
142 Primitive::Type type = GetPrimitiveType();
143 if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
144 DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
145 }
146 SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
147}
148
Elliott Hughes80609252011-09-23 17:24:51 -0700149void Field::InitJavaFields() {
150 Thread* self = Thread::Current();
151 ScopedThreadStateChange tsc(self, Thread::kRunnable);
152 MonitorEnter(self);
153 if (type_ == NULL) {
154 InitJavaFieldsLocked();
155 }
156 MonitorExit(self);
157}
158
159void Field::InitJavaFieldsLocked() {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700160 GetType(); // Resolves type as a side-effect. May throw.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700161}
162
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700163uint32_t Field::Get32(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700164 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700165 if (IsStatic()) {
166 object = declaring_class_;
167 }
168 return object->GetField32(GetOffset(), IsVolatile());
Elliott Hughes68f4fa02011-08-21 10:46:59 -0700169}
170
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700171void Field::Set32(Object* object, uint32_t new_value) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700172 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700173 if (IsStatic()) {
174 object = declaring_class_;
175 }
176 object->SetField32(GetOffset(), new_value, IsVolatile());
177}
178
179uint64_t Field::Get64(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700180 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700181 if (IsStatic()) {
182 object = declaring_class_;
183 }
184 return object->GetField64(GetOffset(), IsVolatile());
185}
186
187void Field::Set64(Object* object, uint64_t new_value) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700188 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700189 if (IsStatic()) {
190 object = declaring_class_;
191 }
192 object->SetField64(GetOffset(), new_value, IsVolatile());
193}
194
195Object* Field::GetObj(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700196 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700197 if (IsStatic()) {
198 object = declaring_class_;
199 }
200 return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
201}
202
203void Field::SetObj(Object* object, const Object* new_value) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700204 CHECK((object == NULL) == IsStatic()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700205 if (IsStatic()) {
206 object = declaring_class_;
207 }
208 object->SetFieldObject(GetOffset(), new_value, IsVolatile());
209}
210
211bool Field::GetBoolean(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700212 DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700213 return Get32(object);
214}
215
216void Field::SetBoolean(Object* object, bool z) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700217 DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700218 Set32(object, z);
219}
220
221int8_t Field::GetByte(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700222 DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700223 return Get32(object);
224}
225
226void Field::SetByte(Object* object, int8_t b) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700227 DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700228 Set32(object, b);
229}
230
231uint16_t Field::GetChar(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700232 DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700233 return Get32(object);
234}
235
236void Field::SetChar(Object* object, uint16_t c) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700237 DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700238 Set32(object, c);
239}
240
Ian Rogers466bb252011-10-14 03:29:56 -0700241int16_t Field::GetShort(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700242 DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700243 return Get32(object);
244}
245
Ian Rogers466bb252011-10-14 03:29:56 -0700246void Field::SetShort(Object* object, int16_t s) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700247 DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700248 Set32(object, s);
249}
250
251int32_t Field::GetInt(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700252 DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700253 return Get32(object);
254}
255
256void Field::SetInt(Object* object, int32_t i) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700257 DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700258 Set32(object, i);
259}
260
261int64_t Field::GetLong(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700262 DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700263 return Get64(object);
264}
265
266void Field::SetLong(Object* object, int64_t j) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700267 DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700268 Set64(object, j);
269}
270
271float Field::GetFloat(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700272 DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700273 JValue float_bits;
274 float_bits.i = Get32(object);
275 return float_bits.f;
276}
277
278void Field::SetFloat(Object* object, float f) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700279 DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700280 JValue float_bits;
281 float_bits.f = f;
282 Set32(object, float_bits.i);
283}
284
285double Field::GetDouble(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700286 DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700287 JValue double_bits;
288 double_bits.j = Get64(object);
289 return double_bits.d;
290}
291
292void Field::SetDouble(Object* object, double d) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700293 DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700294 JValue double_bits;
295 double_bits.d = d;
296 Set64(object, double_bits.j);
297}
298
299Object* Field::GetObject(const Object* object) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700300 CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700301 return GetObj(object);
302}
303
304void Field::SetObject(Object* object, const Object* l) const {
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700305 CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700306 SetObj(object, l);
307}
308
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700309bool Method::IsClassInitializer() const {
310 return IsStatic() && GetName()->Equals("<clinit>");
311}
312
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700313// TODO: get global references for these
Elliott Hughes80609252011-09-23 17:24:51 -0700314Class* Method::java_lang_reflect_Constructor_ = NULL;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700315Class* Method::java_lang_reflect_Method_ = NULL;
316
Elliott Hughes80609252011-09-23 17:24:51 -0700317void Method::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) {
318 CHECK(java_lang_reflect_Constructor_ == NULL);
319 CHECK(java_lang_reflect_Constructor != NULL);
320 java_lang_reflect_Constructor_ = java_lang_reflect_Constructor;
321
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700322 CHECK(java_lang_reflect_Method_ == NULL);
323 CHECK(java_lang_reflect_Method != NULL);
324 java_lang_reflect_Method_ = java_lang_reflect_Method;
325}
326
Elliott Hughes80609252011-09-23 17:24:51 -0700327void Method::ResetClasses() {
328 CHECK(java_lang_reflect_Constructor_ != NULL);
329 java_lang_reflect_Constructor_ = NULL;
330
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700331 CHECK(java_lang_reflect_Method_ != NULL);
332 java_lang_reflect_Method_ = NULL;
333}
334
Elliott Hughes418d20f2011-09-22 14:00:39 -0700335Class* ExtractNextClassFromSignature(ClassLinker* class_linker, const ClassLoader* cl, const char*& p) {
336 if (*p == '[') {
337 // Something like "[[[Ljava/lang/String;".
338 const char* start = p;
339 while (*p == '[') {
340 ++p;
341 }
342 if (*p == 'L') {
343 while (*p != ';') {
344 ++p;
345 }
346 }
347 ++p; // Either the ';' or the primitive type.
348
Brian Carlstromaded5f72011-10-07 17:15:04 -0700349 std::string descriptor(start, (p - start));
Elliott Hughes418d20f2011-09-22 14:00:39 -0700350 return class_linker->FindClass(descriptor, cl);
351 } else if (*p == 'L') {
352 const char* start = p;
353 while (*p != ';') {
354 ++p;
355 }
356 ++p;
357 StringPiece descriptor(start, (p - start));
Brian Carlstromaded5f72011-10-07 17:15:04 -0700358 return class_linker->FindClass(descriptor.ToString(), cl);
Elliott Hughes418d20f2011-09-22 14:00:39 -0700359 } else {
360 return class_linker->FindPrimitiveClass(*p++);
361 }
362}
363
364void Method::InitJavaFieldsLocked() {
365 // Create the array.
366 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
367 size_t arg_count = GetShorty()->GetLength() - 1;
368 Class* array_class = class_linker->FindSystemClass("[Ljava/lang/Class;");
369 ObjectArray<Class>* parameters = ObjectArray<Class>::Alloc(array_class, arg_count);
370 if (parameters == NULL) {
371 return;
372 }
373
374 // Parse the signature, filling the array.
375 const ClassLoader* cl = GetDeclaringClass()->GetClassLoader();
376 std::string signature(GetSignature()->ToModifiedUtf8());
377 const char* p = signature.c_str();
378 DCHECK_EQ(*p, '(');
379 ++p;
380 for (size_t i = 0; i < arg_count; ++i) {
381 Class* c = ExtractNextClassFromSignature(class_linker, cl, p);
382 if (c == NULL) {
383 return;
384 }
385 parameters->Set(i, c);
386 }
387
388 DCHECK_EQ(*p, ')');
389 ++p;
390
Ian Rogers5d76c432011-10-31 21:42:49 -0700391 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, java_parameter_types_),
392 parameters, false);
393 Class* java_return_type = ExtractNextClassFromSignature(class_linker, cl, p);
394 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_),
395 java_return_type, false);
Elliott Hughes418d20f2011-09-22 14:00:39 -0700396}
397
398void Method::InitJavaFields() {
399 Thread* self = Thread::Current();
400 ScopedThreadStateChange tsc(self, Thread::kRunnable);
401 MonitorEnter(self);
402 if (java_parameter_types_ == NULL || java_return_type_ == NULL) {
403 InitJavaFieldsLocked();
404 }
405 MonitorExit(self);
406}
407
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700408ObjectArray<String>* Method::GetDexCacheStrings() const {
409 return GetFieldObject<ObjectArray<String>*>(
410 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
411}
412
413void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
414 SetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
415 new_return_type_idx, false);
416}
417
Ian Rogers0571d352011-11-03 19:51:38 -0700418uint32_t Method::GetDexMethodIndex() const {
419 // TODO: add the method index to Method - which will also mean a number of Method fields can
420 // become dex file lookups (which will then mean we may want faster access to the dex file)
421 // Find the dex file
422 const DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
423 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
424 // Find the class_def in the dex file
425 uint32_t class_def_idx;
426 bool found_class_def =
427 dex_file.FindClassDefIndex(GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8(),
428 class_def_idx);
429 CHECK(found_class_def);
430 const DexFile::TypeId& type_id =
431 dex_file.GetTypeId(dex_file.GetClassDef(class_def_idx).class_idx_);
432 const DexFile::StringId* name_str_id = dex_file.FindStringId(GetName()->ToModifiedUtf8());
433 CHECK(name_str_id != NULL); // Failed to find method's name?
434 uint16_t return_type_idx;
435 std::vector<uint16_t> param_type_idxs;
436 std::string signature = GetSignature()->ToModifiedUtf8();
437 bool found_type_list = dex_file.CreateTypeList(&return_type_idx, &param_type_idxs, signature);
438 CHECK(found_type_list); // Failed to parse signature
439 const DexFile::ProtoId* sig_proto_id = dex_file.FindProtoId(return_type_idx, param_type_idxs);
440 CHECK(sig_proto_id != NULL); // Failed to find method's prototype
441 const DexFile::MethodId* method_id =
442 dex_file.FindMethodId(type_id, *name_str_id, *sig_proto_id);
443 CHECK(method_id != NULL); // Failed to find method?
444 uint32_t method_idx = dex_file.GetIndexForMethodId(*method_id);
445 DCHECK_EQ(PrettyMethod(method_idx, dex_file), PrettyMethod(this));
446 return method_idx;
447}
448
Ian Rogers9074b992011-10-26 17:41:55 -0700449const char* Method::GetReturnTypeDescriptor() const {
450 Class* declaring_class = GetDeclaringClass();
451 DexCache* dex_cache = declaring_class->GetDexCache();
452 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
453 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
Ian Rogers0571d352011-11-03 19:51:38 -0700454 const char* descriptor = dex_file.StringByTypeIdx(GetReturnTypeIdx());
Ian Rogers9074b992011-10-26 17:41:55 -0700455 DCHECK(descriptor != NULL);
456 return descriptor;
457}
458
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700459Class* Method::GetReturnType() const {
Brian Carlstrom5de8fe52011-10-16 14:10:09 -0700460 DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous())
461 << PrettyMethod(this);
Jesse Wilsond81cdcc2011-10-17 14:36:48 -0400462 Class* java_return_type = java_return_type_;
463 if (java_return_type != NULL) {
464 return java_return_type;
465 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700466 // Short-cut
467 Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
468 if (result == NULL) {
469 // Do full linkage and set cache value for next call
470 result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
471 }
Elliott Hughes14134a12011-09-30 16:55:51 -0700472 CHECK(result != NULL) << PrettyMethod(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700473 return result;
474}
475
476void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
477 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
478 new_dex_cache_strings, false);
479}
480
481ObjectArray<Class>* Method::GetDexCacheResolvedTypes() const {
482 return GetFieldObject<ObjectArray<Class>*>(
483 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_), false);
484}
485
486void Method::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
487 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_),
488 new_dex_cache_classes, false);
489}
490
491ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
492 return GetFieldObject<ObjectArray<Method>*>(
493 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
494}
495
496void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
497 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
498 new_dex_cache_methods, false);
499}
500
501ObjectArray<Field>* Method::GetDexCacheResolvedFields() const {
502 return GetFieldObject<ObjectArray<Field>*>(
503 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_), false);
504}
505
506void Method::SetDexCacheResolvedFields(ObjectArray<Field>* new_dex_cache_fields) {
507 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_),
508 new_dex_cache_fields, false);
509}
510
511CodeAndDirectMethods* Method::GetDexCacheCodeAndDirectMethods() const {
512 return GetFieldPtr<CodeAndDirectMethods*>(
513 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
514 false);
515}
516
517void Method::SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value) {
518 SetFieldPtr<CodeAndDirectMethods*>(
519 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
520 new_value, false);
521}
522
523ObjectArray<StaticStorageBase>* Method::GetDexCacheInitializedStaticStorage() const {
524 return GetFieldObject<ObjectArray<StaticStorageBase>*>(
525 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
526 false);
527}
528
529void Method::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700530 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700531 new_value, false);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700532}
533
534size_t Method::NumArgRegisters(const StringPiece& shorty) {
535 CHECK_LE(1, shorty.length());
536 uint32_t num_registers = 0;
537 for (int i = 1; i < shorty.length(); ++i) {
538 char ch = shorty[i];
539 if (ch == 'D' || ch == 'J') {
540 num_registers += 2;
541 } else {
542 num_registers += 1;
Brian Carlstromb63ec392011-08-27 17:38:27 -0700543 }
544 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700545 return num_registers;
546}
547
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700548size_t Method::NumArgs() const {
549 // "1 +" because the first in Args is the receiver.
550 // "- 1" because we don't count the return type.
551 return (IsStatic() ? 0 : 1) + GetShorty()->GetLength() - 1;
552}
553
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700554// The number of reference arguments to this method including implicit this
555// pointer
556size_t Method::NumReferenceArgs() const {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700557 const String* shorty = GetShorty();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700558 size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700559 for (int i = 1; i < shorty->GetLength(); i++) {
560 char ch = shorty->CharAt(i);
561 if ((ch == 'L') || (ch == '[')) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700562 result++;
563 }
564 }
565 return result;
566}
567
568// The number of long or double arguments
569size_t Method::NumLongOrDoubleArgs() const {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700570 const String* shorty = GetShorty();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700571 size_t result = 0;
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700572 for (int i = 1; i < shorty->GetLength(); i++) {
573 char ch = shorty->CharAt(i);
574 if ((ch == 'D') || (ch == 'J')) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700575 result++;
576 }
577 }
578 return result;
579}
580
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700581// Is the given method parameter a reference?
582bool Method::IsParamAReference(unsigned int param) const {
583 CHECK_LT(param, NumArgs());
584 if (IsStatic()) {
585 param++; // 0th argument must skip return value at start of the shorty
586 } else if (param == 0) {
587 return true; // this argument
588 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700589 return GetShorty()->CharAt(param) == 'L';
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700590}
591
592// Is the given method parameter a long or double?
593bool Method::IsParamALongOrDouble(unsigned int param) const {
594 CHECK_LT(param, NumArgs());
595 if (IsStatic()) {
596 param++; // 0th argument must skip return value at start of the shorty
597 } else if (param == 0) {
598 return false; // this argument
599 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700600 char ch = GetShorty()->CharAt(param);
601 return (ch == 'J' || ch == 'D');
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700602}
603
604static size_t ShortyCharToSize(char x) {
605 switch (x) {
606 case 'V': return 0;
607 case '[': return kPointerSize;
608 case 'L': return kPointerSize;
609 case 'D': return 8;
610 case 'J': return 8;
611 default: return 4;
612 }
613}
614
615size_t Method::ParamSize(unsigned int param) const {
616 CHECK_LT(param, NumArgs());
617 if (IsStatic()) {
618 param++; // 0th argument must skip return value at start of the shorty
619 } else if (param == 0) {
620 return kPointerSize; // this argument
621 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700622 return ShortyCharToSize(GetShorty()->CharAt(param));
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700623}
624
625size_t Method::ReturnSize() const {
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700626 return ShortyCharToSize(GetShorty()->CharAt(0));
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700627}
628
Ian Rogers466bb252011-10-14 03:29:56 -0700629Method* Method::FindOverriddenMethod() const {
630 if (IsStatic()) {
631 return NULL;
632 }
633 Class* declaring_class = GetDeclaringClass();
634 Class* super_class = declaring_class->GetSuperClass();
635 uint16_t method_index = GetMethodIndex();
636 ObjectArray<Method>* super_class_vtable = super_class->GetVTable();
637 Method* result = NULL;
638 if (super_class_vtable != NULL && method_index < super_class_vtable->GetLength()) {
639 result = super_class_vtable->Get(method_index);
640 } else {
641 ObjectArray<Class>* interfaces = declaring_class->GetInterfaces();
642 String* name = GetName();
643 String* signature = GetSignature();
644 for (int32_t i = 0; i < interfaces->GetLength() && result == NULL; i++) {
645 Class* interface = interfaces->Get(i);
646 result = interface->FindInterfaceMethod(name, signature);
647 }
648 }
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700649 DCHECK(result == NULL || HasSameNameAndSignature(result));
Ian Rogers466bb252011-10-14 03:29:56 -0700650 return result;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700651}
652
Ian Rogersbdb03912011-09-14 00:55:44 -0700653uint32_t Method::ToDexPC(const uintptr_t pc) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700654 const uint32_t* mapping_table = GetMappingTable();
Ian Rogersbdb03912011-09-14 00:55:44 -0700655 if (mapping_table == NULL) {
Brian Carlstrom26c935a2011-10-16 14:52:35 -0700656 DCHECK(IsNative() || IsCalleeSaveMethod()) << PrettyMethod(this);
Ian Rogers67375ac2011-09-14 00:55:44 -0700657 return DexFile::kDexNoIndex; // Special no mapping case
Ian Rogersbdb03912011-09-14 00:55:44 -0700658 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700659 size_t mapping_table_length = GetMappingTableLength();
Ian Rogersbdb03912011-09-14 00:55:44 -0700660 uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetCode());
Ian Rogersbdb03912011-09-14 00:55:44 -0700661 uint32_t best_offset = 0;
662 uint32_t best_dex_offset = 0;
663 for (size_t i = 0; i < mapping_table_length; i += 2) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700664 uint32_t map_offset = mapping_table[i];
665 uint32_t map_dex_offset = mapping_table[i + 1];
Ian Rogersbdb03912011-09-14 00:55:44 -0700666 if (map_offset == sought_offset) {
667 best_offset = map_offset;
668 best_dex_offset = map_dex_offset;
669 break;
670 }
671 if (map_offset < sought_offset && map_offset > best_offset) {
672 best_offset = map_offset;
673 best_dex_offset = map_dex_offset;
674 }
675 }
676 return best_dex_offset;
677}
678
679uintptr_t Method::ToNativePC(const uint32_t dex_pc) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700680 const uint32_t* mapping_table = GetMappingTable();
Ian Rogersbdb03912011-09-14 00:55:44 -0700681 if (mapping_table == NULL) {
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700682 DCHECK_EQ(dex_pc, 0U);
Ian Rogersbdb03912011-09-14 00:55:44 -0700683 return 0; // Special no mapping/pc == 0 case
684 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700685 size_t mapping_table_length = GetMappingTableLength();
Ian Rogersbdb03912011-09-14 00:55:44 -0700686 for (size_t i = 0; i < mapping_table_length; i += 2) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700687 uint32_t map_offset = mapping_table[i];
688 uint32_t map_dex_offset = mapping_table[i + 1];
Ian Rogersbdb03912011-09-14 00:55:44 -0700689 if (map_dex_offset == dex_pc) {
Ian Rogersbdb03912011-09-14 00:55:44 -0700690 return reinterpret_cast<uintptr_t>(GetCode()) + map_offset;
691 }
692 }
693 LOG(FATAL) << "Looking up Dex PC not contained in method";
694 return 0;
695}
696
697uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
698 DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
Ian Rogersbdb03912011-09-14 00:55:44 -0700699 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
700 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
701 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
702 // Iterate over the catch handlers associated with dex_pc
Ian Rogers0571d352011-11-03 19:51:38 -0700703 for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
704 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
Ian Rogersbdb03912011-09-14 00:55:44 -0700705 // Catch all case
Ian Rogers0571d352011-11-03 19:51:38 -0700706 if (iter_type_idx == DexFile::kDexNoIndex16) {
707 return it.GetHandlerAddress();
Ian Rogersbdb03912011-09-14 00:55:44 -0700708 }
709 // Does this catch exception type apply?
Ian Rogers28ad40d2011-10-27 15:19:26 -0700710 Class* iter_exception_type = dex_cache->GetResolvedType(iter_type_idx);
711 if (iter_exception_type == NULL) {
712 // The verifier should take care of resolving all exception classes early
713 LOG(WARNING) << "Unresolved exception class when finding catch block: "
714 << dex_file.GetTypeDescriptor(dex_file.GetTypeId(iter_type_idx));
715 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
Ian Rogers0571d352011-11-03 19:51:38 -0700716 return it.GetHandlerAddress();
Ian Rogersbdb03912011-09-14 00:55:44 -0700717 }
718 }
719 // Handler not found
720 return DexFile::kDexNoIndex;
721}
722
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700723void Method::Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const {
724 // Push a transition back into managed code onto the linked list in thread.
725 CHECK_EQ(Thread::kRunnable, self->GetState());
726 NativeToManagedRecord record;
727 self->PushNativeToManagedRecord(&record);
728
729 // Call the invoke stub associated with the method.
730 // Pass everything as arguments.
731 const Method::InvokeStub* stub = GetInvokeStub();
Elliott Hughes1240dad2011-09-09 16:24:50 -0700732
733 bool have_executable_code = (GetCode() != NULL);
734#if !defined(__arm__)
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700735 // Currently we can only compile non-native methods for ARM.
736 have_executable_code = IsNative();
Elliott Hughes1240dad2011-09-09 16:24:50 -0700737#endif
738
Jesse Wilson9a6bae82011-11-14 14:57:30 -0500739 if (Runtime::Current()->IsStarted() && have_executable_code && stub != NULL) {
Elliott Hughes9f865372011-10-11 15:04:19 -0700740 bool log = false;
741 if (log) {
742 LOG(INFO) << "invoking " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
743 }
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700744 (*stub)(this, receiver, self, args, result);
Elliott Hughes9f865372011-10-11 15:04:19 -0700745 if (log) {
746 LOG(INFO) << "returned " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
747 }
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700748 } else {
Jesse Wilson9a6bae82011-11-14 14:57:30 -0500749 LOG(INFO) << "not invoking " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub
750 << " started=" << Runtime::Current()->IsStarted();
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700751 if (result != NULL) {
752 result->j = 0;
753 }
754 }
755
756 // Pop transition.
757 self->PopNativeToManagedRecord(record);
758}
759
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700760bool Method::IsRegistered() const {
Brian Carlstrom16192862011-09-12 17:50:06 -0700761 void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_), false);
Ian Rogers169c9a72011-11-13 20:13:17 -0800762 void* jni_stub = Runtime::Current()->GetJniDlsymLookupStub()->GetData();
Brian Carlstrom16192862011-09-12 17:50:06 -0700763 return native_method != jni_stub;
764}
765
766void Method::RegisterNative(const void* native_method) {
Brian Carlstrom5de8fe52011-10-16 14:10:09 -0700767 CHECK(IsNative()) << PrettyMethod(this);
768 CHECK(native_method != NULL) << PrettyMethod(this);
Brian Carlstrom16192862011-09-12 17:50:06 -0700769 SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
770 native_method, false);
771}
772
773void Method::UnregisterNative() {
Brian Carlstrom5de8fe52011-10-16 14:10:09 -0700774 CHECK(IsNative()) << PrettyMethod(this);
Brian Carlstrom16192862011-09-12 17:50:06 -0700775 // restore stub to lookup native pointer via dlsym
Ian Rogers169c9a72011-11-13 20:13:17 -0800776 RegisterNative(Runtime::Current()->GetJniDlsymLookupStub()->GetData());
Brian Carlstrom16192862011-09-12 17:50:06 -0700777}
778
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700779void Class::SetStatus(Status new_status) {
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700780 CHECK(new_status > GetStatus() || new_status == kStatusError || !Runtime::Current()->IsStarted())
781 << PrettyClass(this) << " " << GetStatus() << " -> " << new_status;
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700782 CHECK(sizeof(Status) == sizeof(uint32_t)) << PrettyClass(this);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700783 return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status, false);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700784}
785
786DexCache* Class::GetDexCache() const {
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700787 return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700788}
789
790void Class::SetDexCache(DexCache* new_dex_cache) {
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700791 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700792}
793
Brian Carlstrom1f870082011-08-23 16:02:11 -0700794Object* Class::AllocObject() {
Brian Carlstrom96a253a2011-10-27 18:38:10 -0700795 DCHECK(!IsArrayClass()) << PrettyClass(this);
Ian Rogers28ad40d2011-10-27 15:19:26 -0700796 DCHECK(IsInstantiable()) << PrettyClass(this);
Jesse Wilson9a6bae82011-11-14 14:57:30 -0500797 // TODO: decide whether we want this check. It currently fails during bootstrap.
798 // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this);
Brian Carlstrom96a253a2011-10-27 18:38:10 -0700799 DCHECK_GE(this->object_size_, sizeof(Object));
Brian Carlstrom1f870082011-08-23 16:02:11 -0700800 return Heap::AllocObject(this, this->object_size_);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700801}
802
Ian Rogers0571d352011-11-03 19:51:38 -0700803void Class::SetClassSize(size_t new_class_size) {
804 DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
805 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false);
806}
807
Elliott Hughes4681c802011-09-25 18:04:37 -0700808void Class::DumpClass(std::ostream& os, int flags) const {
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700809 if ((flags & kDumpClassFullDetail) == 0) {
810 os << PrettyClass(this);
811 if ((flags & kDumpClassClassLoader) != 0) {
812 os << ' ' << GetClassLoader();
813 }
814 if ((flags & kDumpClassInitialized) != 0) {
815 os << ' ' << GetStatus();
816 }
Elliott Hughese0918552011-10-28 17:18:29 -0700817 os << "\n";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700818 return;
819 }
820
821 Class* super = GetSuperClass();
822 os << "----- " << (IsInterface() ? "interface" : "class") << " "
823 << "'" << GetDescriptor()->ToModifiedUtf8() << "' cl=" << GetClassLoader() << " -----\n",
824 os << " objectSize=" << SizeOf() << " "
825 << "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n",
826 os << StringPrintf(" access=0x%04x.%04x\n",
827 GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask);
828 if (super != NULL) {
829 os << " super='" << PrettyClass(super) << "' (cl=" << super->GetClassLoader() << ")\n";
830 }
831 if (IsArrayClass()) {
832 os << " componentType=" << PrettyClass(GetComponentType()) << "\n";
833 }
834 if (NumInterfaces() > 0) {
835 os << " interfaces (" << NumInterfaces() << "):\n";
836 for (size_t i = 0; i < NumInterfaces(); ++i) {
837 Class* interface = GetInterface(i);
838 const ClassLoader* cl = interface->GetClassLoader();
839 os << StringPrintf(" %2d: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl);
840 }
841 }
842 os << " vtable (" << NumVirtualMethods() << " entries, "
843 << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n";
844 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Elliott Hughes4681c802011-09-25 18:04:37 -0700845 os << StringPrintf(" %2d: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str());
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700846 }
847 os << " direct methods (" << NumDirectMethods() << " entries):\n";
848 for (size_t i = 0; i < NumDirectMethods(); ++i) {
849 os << StringPrintf(" %2d: %s\n", i, PrettyMethod(GetDirectMethod(i)).c_str());
850 }
851 if (NumStaticFields() > 0) {
852 os << " static fields (" << NumStaticFields() << " entries):\n";
Elliott Hughes03f03492011-09-26 13:38:08 -0700853 if (IsResolved() || IsErroneous()) {
Elliott Hughes4681c802011-09-25 18:04:37 -0700854 for (size_t i = 0; i < NumStaticFields(); ++i) {
Elliott Hughes03f03492011-09-26 13:38:08 -0700855 os << StringPrintf(" %2d: %s\n", i, PrettyField(GetStaticField(i)).c_str());
Elliott Hughes4681c802011-09-25 18:04:37 -0700856 }
857 } else {
858 os << " <not yet available>";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700859 }
860 }
861 if (NumInstanceFields() > 0) {
862 os << " instance fields (" << NumInstanceFields() << " entries):\n";
Elliott Hughes03f03492011-09-26 13:38:08 -0700863 if (IsResolved() || IsErroneous()) {
Elliott Hughes4681c802011-09-25 18:04:37 -0700864 for (size_t i = 0; i < NumInstanceFields(); ++i) {
Elliott Hughes03f03492011-09-26 13:38:08 -0700865 os << StringPrintf(" %2d: %s\n", i, PrettyField(GetInstanceField(i)).c_str());
Elliott Hughes4681c802011-09-25 18:04:37 -0700866 }
867 } else {
868 os << " <not yet available>";
Elliott Hughes9d5ccec2011-09-19 13:19:50 -0700869 }
870 }
871}
872
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700873void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
874 if (new_reference_offsets != CLASS_WALK_SUPER) {
875 // Sanity check that the number of bits set in the reference offset bitmap
876 // agrees with the number of references
877 Class* cur = this;
878 size_t cnt = 0;
879 while (cur) {
880 cnt += cur->NumReferenceInstanceFieldsDuringLinking();
881 cur = cur->GetSuperClass();
882 }
883 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
884 }
885 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
886 new_reference_offsets, false);
887}
888
889void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
890 if (new_reference_offsets != CLASS_WALK_SUPER) {
891 // Sanity check that the number of bits set in the reference offset bitmap
892 // agrees with the number of references
893 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets),
894 NumReferenceStaticFieldsDuringLinking());
895 }
896 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
897 new_reference_offsets, false);
898}
899
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700900bool Class::Implements(const Class* klass) const {
901 DCHECK(klass != NULL);
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700902 DCHECK(klass->IsInterface()) << PrettyClass(this);
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700903 // All interfaces implemented directly and by our superclass, and
904 // recursively all super-interfaces of those interfaces, are listed
905 // in iftable_, so we can just do a linear scan through that.
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700906 int32_t iftable_count = GetIfTableCount();
907 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
908 for (int32_t i = 0; i < iftable_count; i++) {
909 if (iftable->Get(i)->GetInterface() == klass) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700910 return true;
911 }
912 }
913 return false;
914}
915
916// Determine whether "this" is assignable from "klazz", where both of these
917// are array classes.
918//
919// Consider an array class, e.g. Y[][], where Y is a subclass of X.
920// Y[][] = Y[][] --> true (identity)
921// X[][] = Y[][] --> true (element superclass)
922// Y = Y[][] --> false
923// Y[] = Y[][] --> false
924// Object = Y[][] --> true (everything is an object)
925// Object[] = Y[][] --> true
926// Object[][] = Y[][] --> true
927// Object[][][] = Y[][] --> false (too many []s)
928// Serializable = Y[][] --> true (all arrays are Serializable)
929// Serializable[] = Y[][] --> true
930// Serializable[][] = Y[][] --> false (unless Y is Serializable)
931//
932// Don't forget about primitive types.
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700933// Object[] = int[] --> false
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700934//
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700935bool Class::IsArrayAssignableFromArray(const Class* src) const {
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700936 DCHECK(IsArrayClass()) << PrettyClass(this);
937 DCHECK(src->IsArrayClass()) << PrettyClass(src);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700938 return GetComponentType()->IsAssignableFrom(src->GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700939}
940
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700941bool Class::IsAssignableFromArray(const Class* src) const {
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700942 DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
943 DCHECK(src->IsArrayClass()) << PrettyClass(src);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700944 if (!IsArrayClass()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700945 // If "this" is not also an array, it must be Object.
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700946 // src's super should be java_lang_Object, since it is an array.
947 Class* java_lang_Object = src->GetSuperClass();
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700948 DCHECK(java_lang_Object != NULL) << PrettyClass(src);
949 DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src);
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700950 return this == java_lang_Object;
951 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700952 return IsArrayAssignableFromArray(src);
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700953}
954
955bool Class::IsSubClass(const Class* klass) const {
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700956 DCHECK(!IsInterface()) << PrettyClass(this);
957 DCHECK(!IsArrayClass()) << PrettyClass(this);
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700958 const Class* current = this;
959 do {
960 if (current == klass) {
961 return true;
962 }
963 current = current->GetSuperClass();
964 } while (current != NULL);
965 return false;
966}
967
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700968bool Class::IsInSamePackage(const String* descriptor_string_1,
969 const String* descriptor_string_2) {
970 const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
971 const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
972
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700973 size_t i = 0;
974 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
975 ++i;
976 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700977 if (descriptor1.find('/', i) != StringPiece::npos ||
978 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700979 return false;
980 } else {
981 return true;
982 }
983}
984
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700985#if 0
Ian Rogersb033c752011-07-20 12:22:35 -0700986bool Class::IsInSamePackage(const StringPiece& descriptor1,
987 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700988 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700989 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -0700990 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
991 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700992 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
993}
994#endif
995
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700996bool Class::IsInSamePackage(const Class* that) const {
997 const Class* klass1 = this;
998 const Class* klass2 = that;
999 if (klass1 == klass2) {
1000 return true;
1001 }
1002 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001003 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -07001004 return false;
1005 }
1006 // Arrays are in the same package when their element classes are.
jeffhao4a801a42011-09-23 13:53:40 -07001007 while (klass1->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001008 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -07001009 }
jeffhao4a801a42011-09-23 13:53:40 -07001010 while (klass2->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001011 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -07001012 }
1013 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -07001014 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -07001015}
1016
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001017const ClassLoader* Class::GetClassLoader() const {
Ian Rogersd81871c2011-10-03 13:57:23 -07001018 return GetFieldObject<const ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
Brian Carlstromb9edb842011-08-28 16:31:06 -07001019}
1020
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001021void Class::SetClassLoader(const ClassLoader* new_cl) {
1022 ClassLoader* new_class_loader = const_cast<ClassLoader*>(new_cl);
Ian Rogersd81871c2011-10-03 13:57:23 -07001023 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
Carl Shapiro8860c0e2011-08-04 17:36:16 -07001024}
1025
Ian Rogersb04f69f2011-10-17 00:40:54 -07001026Method* Class::FindVirtualMethodForInterface(Method* method, bool can_throw) {
Brian Carlstrom30b94452011-08-25 21:35:26 -07001027 Class* declaring_class = method->GetDeclaringClass();
Brian Carlstrom65ca0772011-09-24 16:03:08 -07001028 DCHECK(declaring_class != NULL) << PrettyClass(this);
1029 DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
Brian Carlstrom30b94452011-08-25 21:35:26 -07001030 // TODO cache to improve lookup speed
Brian Carlstrom4b620ff2011-09-11 01:11:01 -07001031 int32_t iftable_count = GetIfTableCount();
1032 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
1033 for (int32_t i = 0; i < iftable_count; i++) {
1034 InterfaceEntry* interface_entry = iftable->Get(i);
1035 if (interface_entry->GetInterface() == declaring_class) {
1036 return interface_entry->GetMethodArray()->Get(method->GetMethodIndex());
Brian Carlstrom30b94452011-08-25 21:35:26 -07001037 }
1038 }
Ian Rogersb04f69f2011-10-17 00:40:54 -07001039 if (can_throw) {
1040 Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
1041 "Class %s does not implement interface %s",
1042 PrettyDescriptor(GetDescriptor()).c_str(),
1043 PrettyDescriptor(declaring_class->GetDescriptor()).c_str());
1044 }
Brian Carlstrom30b94452011-08-25 21:35:26 -07001045 return NULL;
1046}
1047
Ian Rogers466bb252011-10-14 03:29:56 -07001048Method* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature) const {
jeffhaobdb76512011-09-07 11:43:16 -07001049 // Check the current class before checking the interfaces.
1050 Method* method = FindVirtualMethod(name, signature);
1051 if (method != NULL) {
1052 return method;
1053 }
1054
Brian Carlstrom4b620ff2011-09-11 01:11:01 -07001055 int32_t iftable_count = GetIfTableCount();
1056 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
1057 for (int32_t i = 0; i < iftable_count; i++) {
1058 method = iftable->Get(i)->GetInterface()->FindVirtualMethod(name, signature);
jeffhaobdb76512011-09-07 11:43:16 -07001059 if (method != NULL) {
1060 return method;
1061 }
1062 }
1063 return NULL;
1064}
1065
Ian Rogers466bb252011-10-14 03:29:56 -07001066Method* Class::FindInterfaceMethod(String* name, String* signature) const {
1067 // Check the current class before checking the interfaces.
1068 Method* method = FindVirtualMethod(name, signature);
1069 if (method != NULL) {
1070 return method;
1071 }
1072 int32_t iftable_count = GetIfTableCount();
1073 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
1074 for (int32_t i = 0; i < iftable_count; i++) {
1075 Class* interface = iftable->Get(i)->GetInterface();
1076 method = interface->FindVirtualMethod(name, signature);
1077 if (method != NULL) {
1078 return method;
1079 }
1080 }
1081 return NULL;
1082}
1083
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001084Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001085 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001086 for (size_t i = 0; i < NumDirectMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -07001087 Method* method = GetDirectMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -07001088 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001089 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001090 return method;
Ian Rogersb033c752011-07-20 12:22:35 -07001091 }
1092 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001093 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -07001094}
1095
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001096Method* Class::FindDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001097 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001098 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001099 Method* method = klass->FindDeclaredDirectMethod(name, signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001100 if (method != NULL) {
1101 return method;
1102 }
1103 }
1104 return NULL;
1105}
1106
1107Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
Ian Rogers466bb252011-10-14 03:29:56 -07001108 const StringPiece& signature) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001109 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -07001110 Method* method = GetVirtualMethod(i);
Ian Rogers466bb252011-10-14 03:29:56 -07001111 if (method->GetName()->Equals(name) && method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001112 return method;
Ian Rogersb033c752011-07-20 12:22:35 -07001113 }
1114 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001115 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -07001116}
1117
Ian Rogers466bb252011-10-14 03:29:56 -07001118Method* Class::FindDeclaredVirtualMethod(String* name, String* signature) const {
1119 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
1120 Method* method = GetVirtualMethod(i);
1121 if (method->GetName() == name && method->GetSignature() == signature) {
1122 return method;
Ian Rogers466bb252011-10-14 03:29:56 -07001123 }
1124 }
1125 return NULL;
1126}
1127
1128Method* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
1129 for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
1130 Method* method = klass->FindDeclaredVirtualMethod(name, signature);
1131 if (method != NULL) {
1132 return method;
1133 }
1134 }
1135 return NULL;
1136}
1137
1138Method* Class::FindVirtualMethod(String* name, String* signature) const {
1139 for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
Elliott Hughescc5f9a92011-09-28 19:17:29 -07001140 Method* method = klass->FindDeclaredVirtualMethod(name, signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -07001141 if (method != NULL) {
1142 return method;
1143 }
1144 }
1145 return NULL;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001146}
1147
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001148Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001149 // Is the field in this class?
1150 // Interfaces are not relevant because they can't contain instance fields.
1151 for (size_t i = 0; i < NumInstanceFields(); ++i) {
1152 Field* f = GetInstanceField(i);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001153 if (f->GetName()->Equals(name) &&
1154 StringPiece(f->GetTypeDescriptor()) == type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001155 return f;
1156 }
1157 }
1158 return NULL;
1159}
1160
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001161Field* Class::FindDeclaredInstanceField(String* name, String* type) {
1162 // Is the field in this class?
1163 // Interfaces are not relevant because they can't contain instance fields.
1164 for (size_t i = 0; i < NumInstanceFields(); ++i) {
1165 Field* f = GetInstanceField(i);
1166 if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
1167 return f;
1168 }
1169 }
1170 return NULL;
1171}
1172
1173Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001174 // Is the field in this class, or any of its superclasses?
1175 // Interfaces are not relevant because they can't contain instance fields.
1176 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001177 Field* f = c->FindDeclaredInstanceField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001178 if (f != NULL) {
1179 return f;
1180 }
1181 }
1182 return NULL;
1183}
1184
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001185Field* Class::FindInstanceField(String* name, String* type) {
1186 // Is the field in this class, or any of its superclasses?
1187 // Interfaces are not relevant because they can't contain instance fields.
1188 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
1189 Field* f = c->FindDeclaredInstanceField(name, type);
1190 if (f != NULL) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001191 return f;
1192 }
1193 }
1194 return NULL;
1195}
1196
Brian Carlstrom6b4ef022011-10-23 14:59:04 -07001197Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) {
1198 DCHECK(type != NULL);
1199 for (size_t i = 0; i < NumStaticFields(); ++i) {
1200 Field* f = GetStaticField(i);
1201 if (f->GetName()->Equals(name) && StringPiece(f->GetTypeDescriptor()) == type) {
1202 return f;
1203 }
1204 }
1205 return NULL;
1206}
1207
1208Field* Class::FindDeclaredStaticField(String* name, String* type) {
1209 DCHECK(type != NULL);
1210 for (size_t i = 0; i < NumStaticFields(); ++i) {
1211 Field* f = GetStaticField(i);
1212 if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
1213 return f;
1214 }
1215 }
1216 return NULL;
1217}
1218
1219Field* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
1220 // Is the field in this class (or its interfaces), or any of its
1221 // superclasses (or their interfaces)?
1222 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
1223 // Is the field in this class?
1224 Field* f = c->FindDeclaredStaticField(name, type);
1225 if (f != NULL) {
1226 return f;
1227 }
1228
1229 // Is this field in any of this class' interfaces?
1230 for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
1231 InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
1232 Class* interface = interface_entry->GetInterface();
1233 f = interface->FindDeclaredStaticField(name, type);
1234 if (f != NULL) {
1235 return f;
1236 }
1237 }
1238 }
1239 return NULL;
1240}
1241
1242Field* Class::FindStaticField(String* name, String* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001243 // Is the field in this class (or its interfaces), or any of its
1244 // superclasses (or their interfaces)?
1245 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
1246 // Is the field in this class?
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001247 Field* f = c->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001248 if (f != NULL) {
1249 return f;
1250 }
1251
1252 // Is this field in any of this class' interfaces?
jeffhaoe0cfb6f2011-09-22 16:42:56 -07001253 for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
1254 InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
1255 Class* interface = interface_entry->GetInterface();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001256 f = interface->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001257 if (f != NULL) {
1258 return f;
1259 }
1260 }
1261 }
1262 return NULL;
1263}
1264
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001265Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
Elliott Hughes0f4c41d2011-09-04 14:58:03 -07001266 DCHECK(array_class != NULL);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001267 DCHECK_GE(component_count, 0);
1268 DCHECK(array_class->IsArrayClass());
Elliott Hughesb408de72011-10-04 14:35:05 -07001269
1270 size_t header_size = sizeof(Array);
1271 size_t data_size = component_count * component_size;
1272 size_t size = header_size + data_size;
1273
1274 // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
1275 size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size);
1276 if (data_size >> component_shift != size_t(component_count) || size < data_size) {
1277 Thread::Current()->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;",
1278 "%s of length %zd exceeds the VM limit",
1279 PrettyDescriptor(array_class->GetDescriptor()).c_str(), component_count);
1280 return NULL;
1281 }
1282
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001283 Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
1284 if (array != NULL) {
1285 DCHECK(array->IsArrayInstance());
1286 array->SetLength(component_count);
1287 }
1288 return array;
1289}
1290
1291Array* Array::Alloc(Class* array_class, int32_t component_count) {
1292 return Alloc(array_class, component_count, array_class->GetComponentSize());
1293}
1294
Elliott Hughes80609252011-09-23 17:24:51 -07001295bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001296 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
Elliott Hughes80609252011-09-23 17:24:51 -07001297 "length=%i; index=%i", length_, index);
1298 return false;
1299}
1300
1301bool Array::ThrowArrayStoreException(Object* object) const {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001302 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
Elliott Hughes80609252011-09-23 17:24:51 -07001303 "Can't store an element of type %s into an array of type %s",
1304 PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
1305 return false;
1306}
1307
Elliott Hughesd8ddfd52011-08-15 14:32:53 -07001308template<typename T>
1309PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -07001310 DCHECK(array_class_ != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -07001311 Array* raw_array = Array::Alloc(array_class_, length, sizeof(T));
1312 return down_cast<PrimitiveArray<T>*>(raw_array);
1313}
1314
1315template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL;
1316
1317// Explicitly instantiate all the primitive array types.
1318template class PrimitiveArray<uint8_t>; // BooleanArray
1319template class PrimitiveArray<int8_t>; // ByteArray
1320template class PrimitiveArray<uint16_t>; // CharArray
1321template class PrimitiveArray<double>; // DoubleArray
1322template class PrimitiveArray<float>; // FloatArray
1323template class PrimitiveArray<int32_t>; // IntArray
1324template class PrimitiveArray<int64_t>; // LongArray
1325template class PrimitiveArray<int16_t>; // ShortArray
1326
Ian Rogers466bb252011-10-14 03:29:56 -07001327// Explicitly instantiate Class[][]
1328template class ObjectArray<ObjectArray<Class> >;
1329
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001330// TODO: get global references for these
1331Class* String::java_lang_String_ = NULL;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001332
Brian Carlstroma663ea52011-08-19 23:33:41 -07001333void String::SetClass(Class* java_lang_String) {
1334 CHECK(java_lang_String_ == NULL);
1335 CHECK(java_lang_String != NULL);
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001336 java_lang_String_ = java_lang_String;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001337}
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001338
Brian Carlstroma663ea52011-08-19 23:33:41 -07001339void String::ResetClass() {
1340 CHECK(java_lang_String_ != NULL);
1341 java_lang_String_ = NULL;
1342}
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001343
Brian Carlstromc74255f2011-09-11 22:47:39 -07001344String* String::Intern() {
Elliott Hughescf4c6c42011-09-01 15:16:42 -07001345 return Runtime::Current()->GetInternTable()->InternWeak(this);
1346}
1347
Brian Carlstrom395520e2011-09-25 19:35:00 -07001348int32_t String::GetHashCode() {
1349 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
1350 if (result == 0) {
1351 ComputeHashCode();
1352 }
1353 result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
1354 DCHECK(result != 0 || ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0)
1355 << ToModifiedUtf8() << " " << result;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001356 return result;
1357}
1358
1359int32_t String::GetLength() const {
1360 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
1361 DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
1362 return result;
1363}
1364
1365uint16_t String::CharAt(int32_t index) const {
1366 // TODO: do we need this? Equals is the only caller, and could
1367 // bounds check itself.
1368 if (index < 0 || index >= count_) {
1369 Thread* self = Thread::Current();
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001370 self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001371 "length=%i; index=%i", count_, index);
1372 return 0;
1373 }
1374 return GetCharArray()->Get(index + GetOffset());
1375}
1376
1377String* String::AllocFromUtf16(int32_t utf16_length,
1378 const uint16_t* utf16_data_in,
1379 int32_t hash_code) {
1380 String* string = Alloc(GetJavaLangString(), utf16_length);
Elliott Hughesb51036c2011-10-12 23:49:11 -07001381 if (string == NULL) {
1382 return NULL;
1383 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001384 // TODO: use 16-bit wide memset variant
1385 CharArray* array = const_cast<CharArray*>(string->GetCharArray());
Elliott Hughesb51036c2011-10-12 23:49:11 -07001386 if (array == NULL) {
1387 return NULL;
1388 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001389 for (int i = 0; i < utf16_length; i++) {
1390 array->Set(i, utf16_data_in[i]);
1391 }
1392 if (hash_code != 0) {
1393 string->SetHashCode(hash_code);
1394 } else {
1395 string->ComputeHashCode();
1396 }
1397 return string;
1398}
1399
1400String* String::AllocFromModifiedUtf8(const char* utf) {
1401 size_t char_count = CountModifiedUtf8Chars(utf);
1402 return AllocFromModifiedUtf8(char_count, utf);
1403}
1404
1405String* String::AllocFromModifiedUtf8(int32_t utf16_length,
1406 const char* utf8_data_in) {
1407 String* string = Alloc(GetJavaLangString(), utf16_length);
Elliott Hughesb51036c2011-10-12 23:49:11 -07001408 if (string == NULL) {
1409 return NULL;
1410 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001411 uint16_t* utf16_data_out =
1412 const_cast<uint16_t*>(string->GetCharArray()->GetData());
1413 ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
1414 string->ComputeHashCode();
1415 return string;
1416}
1417
1418String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001419 SirtRef<CharArray> array(CharArray::Alloc(utf16_length));
1420 if (array.get() == NULL) {
Elliott Hughesb51036c2011-10-12 23:49:11 -07001421 return NULL;
1422 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001423 return Alloc(java_lang_String, array.get());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001424}
1425
1426String* String::Alloc(Class* java_lang_String, CharArray* array) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001427 SirtRef<CharArray> array_ref(array); // hold reference in case AllocObject causes GC
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001428 String* string = down_cast<String*>(java_lang_String->AllocObject());
Elliott Hughesb51036c2011-10-12 23:49:11 -07001429 if (string == NULL) {
1430 return NULL;
1431 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001432 string->SetArray(array);
1433 string->SetCount(array->GetLength());
1434 return string;
1435}
1436
1437bool String::Equals(const String* that) const {
1438 if (this == that) {
1439 // Quick reference equality test
1440 return true;
1441 } else if (that == NULL) {
1442 // Null isn't an instanceof anything
1443 return false;
1444 } else if (this->GetLength() != that->GetLength()) {
1445 // Quick length inequality test
1446 return false;
1447 } else {
Elliott Hughes20cde902011-10-04 17:37:27 -07001448 // Note: don't short circuit on hash code as we're presumably here as the
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001449 // hash code was already equal
1450 for (int32_t i = 0; i < that->GetLength(); ++i) {
1451 if (this->CharAt(i) != that->CharAt(i)) {
1452 return false;
1453 }
1454 }
1455 return true;
1456 }
1457}
1458
1459bool String::Equals(const uint16_t* that_chars, int32_t that_offset,
1460 int32_t that_length) const {
1461 if (this->GetLength() != that_length) {
1462 return false;
1463 } else {
1464 for (int32_t i = 0; i < that_length; ++i) {
1465 if (this->CharAt(i) != that_chars[that_offset + i]) {
1466 return false;
1467 }
1468 }
1469 return true;
1470 }
1471}
1472
1473bool String::Equals(const char* modified_utf8) const {
1474 for (int32_t i = 0; i < GetLength(); ++i) {
1475 uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
1476 if (ch == '\0' || ch != CharAt(i)) {
1477 return false;
1478 }
1479 }
1480 return *modified_utf8 == '\0';
1481}
1482
1483bool String::Equals(const StringPiece& modified_utf8) const {
Elliott Hughes418d20f2011-09-22 14:00:39 -07001484 if (modified_utf8.size() != GetLength()) {
1485 return false;
1486 }
1487 const char* p = modified_utf8.data();
1488 for (int32_t i = 0; i < GetLength(); ++i) {
1489 uint16_t ch = GetUtf16FromUtf8(&p);
1490 if (ch != CharAt(i)) {
1491 return false;
1492 }
1493 }
1494 return true;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001495}
1496
1497// Create a modified UTF-8 encoded std::string from a java/lang/String object.
1498std::string String::ToModifiedUtf8() const {
1499 const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
1500 size_t byte_count(CountUtf8Bytes(chars, GetLength()));
1501 std::string result(byte_count, char(0));
1502 ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength());
1503 return result;
1504}
1505
Ian Rogers466bb252011-10-14 03:29:56 -07001506bool Throwable::IsCheckedException() const {
1507 Class* error = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Error;");
1508 if (InstanceOf(error)) {
1509 return false;
1510 }
1511 Class* jlre = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/RuntimeException;");
1512 return !InstanceOf(jlre);
1513}
1514
Ian Rogers9074b992011-10-26 17:41:55 -07001515std::string Throwable::Dump() const {
1516 Object* stack_state = GetStackState();
1517 if (stack_state == NULL || !stack_state->IsObjectArray()) {
1518 // missing or corrupt stack state
1519 return "";
1520 }
1521 // Decode the internal stack trace into the depth and method trace
1522 ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state);
1523 int32_t depth = method_trace->GetLength() - 1;
1524 std::string result;
1525 for (int32_t i = 0; i < depth; ++i) {
1526 Method* method = down_cast<Method*>(method_trace->Get(i));
1527 result += " at ";
1528 result += PrettyMethod(method, true);
1529 result += "\n";
1530 }
1531 return result;
1532}
1533
Shih-wei Liao55df06b2011-08-26 14:39:27 -07001534Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
1535
1536void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
1537 CHECK(java_lang_StackTraceElement_ == NULL);
1538 CHECK(java_lang_StackTraceElement != NULL);
1539 java_lang_StackTraceElement_ = java_lang_StackTraceElement;
1540}
1541
1542void StackTraceElement::ResetClass() {
1543 CHECK(java_lang_StackTraceElement_ != NULL);
1544 java_lang_StackTraceElement_ = NULL;
1545}
1546
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001547StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
1548 const String* method_name,
1549 const String* file_name,
1550 int32_t line_number) {
1551 StackTraceElement* trace =
1552 down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
1553 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
1554 const_cast<String*>(declaring_class), false);
1555 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
1556 const_cast<String*>(method_name), false);
1557 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
1558 const_cast<String*>(file_name), false);
1559 trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
1560 line_number, false);
1561 return trace;
1562}
1563
Elliott Hughes1f359b02011-07-17 14:27:17 -07001564static const char* kClassStatusNames[] = {
1565 "Error",
1566 "NotReady",
1567 "Idx",
1568 "Loaded",
1569 "Resolved",
1570 "Verifying",
1571 "Verified",
1572 "Initializing",
1573 "Initialized"
1574};
1575std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
1576 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
Brian Carlstromae3ac012011-07-27 01:30:28 -07001577 os << kClassStatusNames[rhs + 1];
Elliott Hughes1f359b02011-07-17 14:27:17 -07001578 } else {
Ian Rogersb033c752011-07-20 12:22:35 -07001579 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -07001580 }
1581 return os;
1582}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001583
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001584} // namespace art