diff options
author | 2013-01-24 12:42:14 -0800 | |
---|---|---|
committer | 2013-01-30 16:48:31 -0800 | |
commit | 2dd0e2cea360bc9206eb88ecc40d259e796c239d (patch) | |
tree | 9d619dc9508cbe73e4793bf6f08cbc761abfb48a | |
parent | ac21b797b3a425975d656d6b84a7b24401d35f42 (diff) |
Directory restructuring of object.h
Break object.h into constituent files.
Reduce number of #includes in other GC header files.
Introduce -inl.h files to avoid mirror files #include-ing each other.
Check invariants of verifier RegTypes for all constructors.
Change-Id: Iecf1171c02910ac152d52947330ef456df4043bc
240 files changed, 10461 insertions, 8413 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk index 16462649af..21e829ce6e 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -154,7 +154,6 @@ LIBART_COMMON_SRC_FILES := \ src/compiled_method.cc \ src/compiler.cc \ src/debugger.cc \ - src/dex_cache.cc \ src/dex_file.cc \ src/dex_file_verifier.cc \ src/dex_instruction.cc \ @@ -193,6 +192,15 @@ LIBART_COMMON_SRC_FILES := \ src/locks.cc \ src/mem_map.cc \ src/memory_region.cc \ + src/mirror/abstract_method.cc \ + src/mirror/array.cc \ + src/mirror/class.cc \ + src/mirror/dex_cache.cc \ + src/mirror/field.cc \ + src/mirror/object.cc \ + src/mirror/stack_trace_element.cc \ + src/mirror/string.cc \ + src/mirror/throwable.cc \ src/monitor.cc \ src/native/dalvik_system_DexFile.cc \ src/native/dalvik_system_VMDebug.cc \ @@ -229,7 +237,6 @@ LIBART_COMMON_SRC_FILES := \ src/oat/utils/x86/managed_register_x86.cc \ src/oat_file.cc \ src/oat_writer.cc \ - src/object.cc \ src/offsets.cc \ src/os_linux.cc \ src/primitive.cc \ @@ -242,6 +249,7 @@ LIBART_COMMON_SRC_FILES := \ src/thread.cc \ src/thread_list.cc \ src/thread_pool.cc \ + src/timing_logger.cc \ src/trace.cc \ src/utf.cc \ src/utils.cc \ @@ -354,6 +362,7 @@ LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \ src/compiler/compiler_enums.h \ src/dex_file.h \ src/dex_instruction.h \ + src/gc/gc_type.h \ src/gc/space.h \ src/heap.h \ src/indirect_reference_table.h \ @@ -362,8 +371,9 @@ LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \ src/jdwp/jdwp.h \ src/jdwp/jdwp_constants.h \ src/locks.h \ - src/object.h \ + src/mirror/class.h \ src/thread.h \ + src/thread_state.h \ src/verifier/method_verifier.h LIBARTTEST_COMMON_SRC_FILES := \ @@ -380,7 +390,6 @@ TEST_COMMON_SRC_FILES := \ src/base/unix_file/string_file_test.cc \ src/class_linker_test.cc \ src/compiler_test.cc \ - src/dex_cache_test.cc \ src/dex_file_test.cc \ src/dex_instruction_visitor_test.cc \ src/elf_writer_test.cc \ @@ -395,10 +404,11 @@ TEST_COMMON_SRC_FILES := \ src/intern_table_test.cc \ src/jni_compiler_test.cc \ src/jni_internal_test.cc \ + src/mirror/dex_cache_test.cc \ + src/mirror/object_test.cc \ src/oat/utils/arm/managed_register_arm_test.cc \ src/oat/utils/x86/managed_register_x86_test.cc \ src/oat_test.cc \ - src/object_test.cc \ src/output_stream_test.cc \ src/reference_table_test.cc \ src/runtime_support_test.cc \ diff --git a/src/barrier_test.cc b/src/barrier_test.cc index 284be57a98..bb7bcb3b17 100644 --- a/src/barrier_test.cc +++ b/src/barrier_test.cc @@ -20,6 +20,7 @@ #include "atomic_integer.h" #include "common_test.h" +#include "mirror/object_array-inl.h" #include "thread_pool.h" #include "UniquePtr.h" diff --git a/src/base/mutex.cc b/src/base/mutex.cc index e2ab51f2f9..d09a6a27f6 100644 --- a/src/base/mutex.cc +++ b/src/base/mutex.cc @@ -21,7 +21,6 @@ #include "base/logging.h" #include "cutils/atomic.h" -#include "cutils/atomic-inline.h" #include "runtime.h" #include "scoped_thread_state_change.h" #include "thread.h" diff --git a/src/check_jni.cc b/src/check_jni.cc index 8f4e92126a..e53e1c49e6 100644 --- a/src/check_jni.cc +++ b/src/check_jni.cc @@ -21,9 +21,16 @@ #include "base/logging.h" #include "class_linker.h" +#include "class_linker-inl.h" +#include "gc/space.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/throwable.h" #include "object_utils.h" #include "scoped_thread_state_change.h" -#include "gc/space.h" #include "thread.h" #include "runtime.h" @@ -36,7 +43,7 @@ namespace art { static void JniAbort(const char* jni_function_name, const char* msg) { Thread* self = Thread::Current(); ScopedObjectAccess soa(self); - AbstractMethod* current_method = self->GetCurrentMethod(); + mirror::AbstractMethod* current_method = self->GetCurrentMethod(); std::ostringstream os; os << "JNI DETECTED ERROR IN APPLICATION: " << msg; @@ -123,7 +130,7 @@ static const char* gBuiltInPrefixes[] = { NULL }; -static bool ShouldTrace(JavaVMExt* vm, const AbstractMethod* method) +static bool ShouldTrace(JavaVMExt* vm, const mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages // when a native method that matches the -Xjnitrace argument calls a JNI function @@ -196,14 +203,14 @@ class ScopedCheck { */ void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* f = CheckFieldID(fid); + mirror::Field* f = CheckFieldID(fid); if (f == NULL) { return; } - Class* field_type = FieldHelper(f).GetType(); + mirror::Class* field_type = FieldHelper(f).GetType(); if (!field_type->IsPrimitive()) { if (java_object != NULL) { - Object* obj = soa_.Decode<Object*>(java_object); + mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object); // If java_object is a weak global ref whose referent has been cleared, // obj will be NULL. Otherwise, obj should always be non-NULL // and valid. @@ -243,7 +250,7 @@ class ScopedCheck { */ void CheckInstanceFieldID(jobject java_object, jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = soa_.Decode<Object*>(java_object); + mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) { Runtime::Current()->GetHeap()->DumpSpaces(); JniAbortF(function_name_, "field operation on invalid %s: %p", @@ -251,11 +258,11 @@ class ScopedCheck { return; } - Field* f = CheckFieldID(fid); + mirror::Field* f = CheckFieldID(fid); if (f == NULL) { return; } - Class* c = o->GetClass(); + mirror::Class* c = o->GetClass(); FieldHelper fh(f); if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) { JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s", @@ -278,7 +285,7 @@ class ScopedCheck { */ void CheckSig(jmethodID mid, const char* expectedType, bool isStatic) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = CheckMethodID(mid); + mirror::AbstractMethod* m = CheckMethodID(mid); if (m == NULL) { return; } @@ -304,8 +311,8 @@ class ScopedCheck { */ void CheckStaticFieldID(jclass java_class, jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* c = soa_.Decode<Class*>(java_class); - const Field* f = CheckFieldID(fid); + mirror::Class* c = soa_.Decode<mirror::Class*>(java_class); + const mirror::Field* f = CheckFieldID(fid); if (f == NULL) { return; } @@ -326,11 +333,11 @@ class ScopedCheck { */ void CheckStaticMethod(jclass java_class, jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const AbstractMethod* m = CheckMethodID(mid); + const mirror::AbstractMethod* m = CheckMethodID(mid); if (m == NULL) { return; } - Class* c = soa_.Decode<Class*>(java_class); + mirror::Class* c = soa_.Decode<mirror::Class*>(java_class); if (!c->IsAssignableFrom(m->GetDeclaringClass())) { JniAbortF(function_name_, "can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); @@ -346,11 +353,11 @@ class ScopedCheck { */ void CheckVirtualMethod(jobject java_object, jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const AbstractMethod* m = CheckMethodID(mid); + const mirror::AbstractMethod* m = CheckMethodID(mid); if (m == NULL) { return; } - Object* o = soa_.Decode<Object*>(java_object); + mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); if (!o->InstanceOf(m->GetDeclaringClass())) { JniAbortF(function_name_, "can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str()); @@ -397,7 +404,7 @@ class ScopedCheck { SHARED_LOCKS_REQUIRED (Locks::mutator_lock_) { va_list ap; - const AbstractMethod* traceMethod = NULL; + const mirror::AbstractMethod* traceMethod = NULL; if ((!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni)) && has_method_) { // We need to guard some of the invocation interface's calls: a bad caller might // use DetachCurrentThread or GetEnv on a thread that's not yet attached. @@ -455,7 +462,7 @@ class ScopedCheck { msg += (b ? "JNI_TRUE" : "JNI_FALSE"); } else if (ch == 'c') { // jclass jclass jc = va_arg(ap, jclass); - Class* c = reinterpret_cast<Class*>(Thread::Current()->DecodeJObject(jc)); + mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc)); if (c == NULL) { msg += "NULL"; } else if (c == kInvalidIndirectRefObject || !Runtime::Current()->GetHeap()->IsHeapAddress(c)) { @@ -470,7 +477,7 @@ class ScopedCheck { } } else if (ch == 'f') { // jfieldID jfieldID fid = va_arg(ap, jfieldID); - Field* f = reinterpret_cast<Field*>(fid); + mirror::Field* f = reinterpret_cast<mirror::Field*>(fid); msg += PrettyField(f); if (!entry) { StringAppendF(&msg, " (%p)", fid); @@ -483,7 +490,7 @@ class ScopedCheck { StringAppendF(&msg, "%d", i); } else if (ch == 'm') { // jmethodID jmethodID mid = va_arg(ap, jmethodID); - AbstractMethod* m = reinterpret_cast<AbstractMethod*>(mid); + mirror::AbstractMethod* m = reinterpret_cast<mirror::AbstractMethod*>(mid); msg += PrettyMethod(m); if (!entry) { StringAppendF(&msg, " (%p)", mid); @@ -623,7 +630,7 @@ class ScopedCheck { return false; } - Object* obj = soa_.Decode<Object*>(java_object); + mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object); if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) { Runtime::Current()->GetHeap()->DumpSpaces(); JniAbortF(function_name_, "%s is an invalid %s: %p (%p)", @@ -677,7 +684,7 @@ class ScopedCheck { return; } - Array* a = soa_.Decode<Array*>(java_array); + mirror::Array* a = soa_.Decode<mirror::Array*>(java_array); if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) { Runtime::Current()->GetHeap()->DumpSpaces(); JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)", @@ -693,12 +700,12 @@ class ScopedCheck { } } - Field* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Field* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (fid == NULL) { JniAbortF(function_name_, "jfieldID was NULL"); return NULL; } - Field* f = soa_.DecodeField(fid); + mirror::Field* f = soa_.DecodeField(fid); if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsField()) { Runtime::Current()->GetHeap()->DumpSpaces(); JniAbortF(function_name_, "invalid jfieldID: %p", fid); @@ -707,12 +714,12 @@ class ScopedCheck { return f; } - AbstractMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::AbstractMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (mid == NULL) { JniAbortF(function_name_, "jmethodID was NULL"); return NULL; } - AbstractMethod* m = soa_.DecodeMethod(mid); + mirror::AbstractMethod* m = soa_.DecodeMethod(mid); if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) { Runtime::Current()->GetHeap()->DumpSpaces(); JniAbortF(function_name_, "invalid jmethodID: %p", mid); @@ -733,7 +740,7 @@ class ScopedCheck { return; } - Object* o = soa_.Decode<Object*>(java_object); + mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) { Runtime::Current()->GetHeap()->DumpSpaces(); // TODO: when we remove work_around_app_jni_bugs, this should be impossible. @@ -1084,7 +1091,7 @@ struct GuardedCopy { static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) { ScopedObjectAccess soa(env); - Array* a = soa.Decode<Array*>(java_array); + mirror::Array* a = soa.Decode<mirror::Array*>(java_array); size_t component_size = a->GetClass()->GetComponentSize(); size_t byte_count = a->GetLength() * component_size; void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true); @@ -1104,7 +1111,7 @@ static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, } ScopedObjectAccess soa(env); - Array* a = soa.Decode<Array*>(java_array); + mirror::Array* a = soa.Decode<mirror::Array*>(java_array); GuardedCopy::Check(__FUNCTION__, dataBuf, true); @@ -1467,7 +1474,7 @@ FIELD_ACCESSORS(jdouble, Double, "D"); #define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result) #define VOID_RETURN CHECK_JNI_EXIT_VOID() -CALL(jobject, Object, Object* result, result = reinterpret_cast<Object*>, NON_VOID_RETURN("L", jobject), "L"); +CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L"); CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z"); CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B"); CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C"); @@ -1492,7 +1499,7 @@ CALL(void, Void, , , VOID_RETURN, "V"); CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy); const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy); if (sc.ForceCopy() && result != NULL) { - String* s = sc.soa().Decode<String*>(java_string); + mirror::String* s = sc.soa().Decode<mirror::String*>(java_string); int byteCount = s->GetLength() * 2; result = (const jchar*) GuardedCopy::Create(result, byteCount, false); if (isCopy != NULL) { @@ -1719,7 +1726,7 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D'); CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy); const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy); if (sc.ForceCopy() && result != NULL) { - String* s = sc.soa().Decode<String*>(java_string); + mirror::String* s = sc.soa().Decode<mirror::String*>(java_string); int byteCount = s->GetLength() * 2; result = (const jchar*) GuardedCopy::Create(result, byteCount, false); if (isCopy != NULL) { diff --git a/src/class_linker-inl.h b/src/class_linker-inl.h new file mode 100644 index 0000000000..6cf49912a2 --- /dev/null +++ b/src/class_linker-inl.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_CLASS_LINKER_INL_H_ +#define ART_SRC_CLASS_LINKER_INL_H_ + +#include "class_linker.h" + +#include "mirror/dex_cache.h" +#include "mirror/field.h" +#include "mirror/iftable.h" +#include "mirror/object_array.h" + +namespace art { + +inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, + const mirror::AbstractMethod* referrer) { + mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx); + if (UNLIKELY(resolved_string == NULL)) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + resolved_string = ResolveString(dex_file, string_idx, dex_cache); + } + return resolved_string; +} + +inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, + const mirror::AbstractMethod* referrer) { + mirror::Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx); + if (UNLIKELY(resolved_type == NULL)) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); + mirror::ClassLoader* class_loader = declaring_class->GetClassLoader(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); + } + return resolved_type; +} + +inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, const mirror::Field* referrer) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); + mirror::Class* resolved_type = dex_cache->GetResolvedType(type_idx); + if (UNLIKELY(resolved_type == NULL)) { + mirror::ClassLoader* class_loader = declaring_class->GetClassLoader(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); + } + return resolved_type; +} + +inline mirror::AbstractMethod* ClassLinker::ResolveMethod(uint32_t method_idx, + const mirror::AbstractMethod* referrer, + InvokeType type) { + mirror::AbstractMethod* resolved_method = + referrer->GetDexCacheResolvedMethods()->Get(method_idx); + if (UNLIKELY(resolved_method == NULL || resolved_method->IsRuntimeMethod())) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); + mirror::ClassLoader* class_loader = declaring_class->GetClassLoader(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + resolved_method = ResolveMethod(dex_file, method_idx, dex_cache, class_loader, referrer, type); + } + return resolved_method; +} + +inline mirror::Field* ClassLinker::ResolveField(uint32_t field_idx, + const mirror::AbstractMethod* referrer, + bool is_static) { + mirror::Field* resolved_field = + referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); + if (UNLIKELY(resolved_field == NULL)) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); + mirror::ClassLoader* class_loader = declaring_class->GetClassLoader(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static); + } + return resolved_field; +} + +template <class T> +inline mirror::ObjectArray<T>* ClassLinker::AllocObjectArray(Thread* self, size_t length) { + return mirror::ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length); +} + +inline mirror::ObjectArray<mirror::Class>* ClassLinker::AllocClassArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::Class>::Alloc(self, GetClassRoot(kClassArrayClass), length); +} + +inline mirror::ObjectArray<mirror::String>* ClassLinker::AllocStringArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::String>::Alloc(self, GetClassRoot(kJavaLangStringArrayClass), + length); +} + +inline mirror::ObjectArray<mirror::AbstractMethod>* ClassLinker::AllocAbstractMethodArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::AbstractMethod>::Alloc(self, + GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length); +} + +inline mirror::ObjectArray<mirror::AbstractMethod>* ClassLinker::AllocMethodArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::AbstractMethod>::Alloc(self, + GetClassRoot(kJavaLangReflectMethodArrayClass), length); +} + +inline mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) { + return down_cast<mirror::IfTable*>( + mirror::IfTable::Alloc(self, GetClassRoot(kObjectArrayClass), ifcount * mirror::IfTable::kMax)); +} + +inline mirror::ObjectArray<mirror::Field>* ClassLinker::AllocFieldArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::Field>::Alloc(self, + GetClassRoot(kJavaLangReflectFieldArrayClass), + length); +} + +inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(class_roots_ != NULL); + mirror::Class* klass = class_roots_->Get(class_root); + DCHECK(klass != NULL); + return klass; +} + +} // namespace art + +#endif // ART_SRC_CLASS_LINKER_INL_H_ diff --git a/src/class_linker.cc b/src/class_linker.cc index c43c39778e..9aa4dda6f6 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -31,17 +31,28 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" -#include "class_loader.h" +#include "class_linker-inl.h" #include "debugger.h" -#include "dex_cache.h" #include "dex_file.h" +#include "gc/card_table-inl.h" #include "heap.h" #include "intern_table.h" #include "interpreter/interpreter.h" #include "leb128.h" #include "oat.h" #include "oat_file.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/dex_cache.h" +#include "mirror/field-inl.h" +#include "mirror/iftable-inl.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/proxy.h" +#include "mirror/stack_trace_element.h" #include "object_utils.h" #include "os.h" #include "runtime.h" @@ -58,6 +69,7 @@ #include "thread.h" #include "UniquePtr.h" #include "utils.h" +#include "verifier/method_verifier.h" #include "well_known_classes.h" namespace art { @@ -92,7 +104,7 @@ static void ThrowLinkageError(const char* fmt, ...) { va_end(args); } -static void ThrowNoSuchFieldError(const StringPiece& scope, Class* c, const StringPiece& type, +static void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, const StringPiece& type, const StringPiece& name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ClassHelper kh(c); @@ -116,7 +128,7 @@ static void ThrowNullPointerException(const char* fmt, ...) { va_end(args); } -static void ThrowEarlierClassFailure(Class* c) +static void ThrowEarlierClassFailure(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // The class failed to initialize on a previous attempt, so we want to throw // a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we @@ -239,45 +251,47 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class // java_lang_Class comes first, it's needed for AllocClass Thread* self = Thread::Current(); Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Class> - java_lang_Class(self, down_cast<Class*>(heap->AllocObject(self, NULL, sizeof(ClassClass)))); + SirtRef<mirror::Class> + java_lang_Class(self, + down_cast<mirror::Class*>(heap->AllocObject(self, NULL, + sizeof(mirror::ClassClass)))); CHECK(java_lang_Class.get() != NULL); - Class::SetClassClass(java_lang_Class.get()); + mirror::Class::SetClassClass(java_lang_Class.get()); java_lang_Class->SetClass(java_lang_Class.get()); - java_lang_Class->SetClassSize(sizeof(ClassClass)); - // AllocClass(Class*) can now be used + java_lang_Class->SetClassSize(sizeof(mirror::ClassClass)); + // AllocClass(mirror::Class*) can now be used // Class[] is used for reflection support. - SirtRef<Class> class_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> class_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); class_array_class->SetComponentType(java_lang_Class.get()); // java_lang_Object comes next so that object_array_class can be created. - SirtRef<Class> java_lang_Object(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> java_lang_Object(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); CHECK(java_lang_Object.get() != NULL); // backfill Object as the super class of Class. java_lang_Class->SetSuperClass(java_lang_Object.get()); - java_lang_Object->SetStatus(Class::kStatusLoaded); + java_lang_Object->SetStatus(mirror::Class::kStatusLoaded); // Object[] next to hold class roots. - SirtRef<Class> object_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> object_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); object_array_class->SetComponentType(java_lang_Object.get()); // Setup the char class to be used for char[]. - SirtRef<Class> char_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> char_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); // Setup the char[] class to be used for String. - SirtRef<Class> char_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> char_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); char_array_class->SetComponentType(char_class.get()); - CharArray::SetArrayClass(char_array_class.get()); + mirror::CharArray::SetArrayClass(char_array_class.get()); // Setup String. - SirtRef<Class> java_lang_String(self, AllocClass(self, java_lang_Class.get(), sizeof(StringClass))); - String::SetClass(java_lang_String.get()); - java_lang_String->SetObjectSize(sizeof(String)); - java_lang_String->SetStatus(Class::kStatusResolved); + SirtRef<mirror::Class> java_lang_String(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::StringClass))); + mirror::String::SetClass(java_lang_String.get()); + java_lang_String->SetObjectSize(sizeof(mirror::String)); + java_lang_String->SetStatus(mirror::Class::kStatusResolved); // Create storage for root classes, save away our work so far (requires descriptors). - class_roots_ = ObjectArray<Class>::Alloc(self, object_array_class.get(), kClassRootsMax); + class_roots_ = mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.get(), kClassRootsMax); CHECK(class_roots_ != NULL); SetClassRoot(kJavaLangClass, java_lang_Class.get()); SetClassRoot(kJavaLangObject, java_lang_Object.get()); @@ -300,68 +314,69 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class array_iftable_ = AllocIfTable(self, 2); // Create int array type for AllocDexCache (done in AppendToBootClassPath). - SirtRef<Class> int_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> int_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt)); - IntArray::SetArrayClass(int_array_class.get()); + mirror::IntArray::SetArrayClass(int_array_class.get()); SetClassRoot(kIntArrayClass, int_array_class.get()); // now that these are registered, we can use AllocClass() and AllocObjectArray // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache. - SirtRef<Class> - java_lang_DexCache(self, AllocClass(self, java_lang_Class.get(), sizeof(DexCacheClass))); + SirtRef<mirror::Class> + java_lang_DexCache(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::DexCacheClass))); SetClassRoot(kJavaLangDexCache, java_lang_DexCache.get()); - java_lang_DexCache->SetObjectSize(sizeof(DexCacheClass)); - java_lang_DexCache->SetStatus(Class::kStatusResolved); + java_lang_DexCache->SetObjectSize(sizeof(mirror::DexCacheClass)); + java_lang_DexCache->SetStatus(mirror::Class::kStatusResolved); // Constructor, Field, Method, and AbstractMethod are necessary so that FindClass can link members. - SirtRef<Class> java_lang_reflect_Field(self, AllocClass(self, java_lang_Class.get(), - sizeof(FieldClass))); + SirtRef<mirror::Class> java_lang_reflect_Field(self, AllocClass(self, java_lang_Class.get(), + sizeof(mirror::FieldClass))); CHECK(java_lang_reflect_Field.get() != NULL); - java_lang_reflect_Field->SetObjectSize(sizeof(Field)); + java_lang_reflect_Field->SetObjectSize(sizeof(mirror::Field)); SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field.get()); - java_lang_reflect_Field->SetStatus(Class::kStatusResolved); - Field::SetClass(java_lang_reflect_Field.get()); + java_lang_reflect_Field->SetStatus(mirror::Class::kStatusResolved); + mirror::Field::SetClass(java_lang_reflect_Field.get()); - SirtRef<Class> java_lang_reflect_AbstractMethod(self, AllocClass(self, java_lang_Class.get(), - sizeof(MethodClass))); + SirtRef<mirror::Class> java_lang_reflect_AbstractMethod(self, AllocClass(self, java_lang_Class.get(), + sizeof(mirror::AbstractMethodClass))); CHECK(java_lang_reflect_AbstractMethod.get() != NULL); - java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(AbstractMethod)); + java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(mirror::AbstractMethod)); SetClassRoot(kJavaLangReflectAbstractMethod, java_lang_reflect_AbstractMethod.get()); - java_lang_reflect_AbstractMethod->SetStatus(Class::kStatusResolved); + java_lang_reflect_AbstractMethod->SetStatus(mirror::Class::kStatusResolved); - SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(), - sizeof(MethodClass))); + SirtRef<mirror::Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(), + sizeof(mirror::AbstractMethodClass))); CHECK(java_lang_reflect_Constructor.get() != NULL); - java_lang_reflect_Constructor->SetObjectSize(sizeof(Constructor)); + java_lang_reflect_Constructor->SetObjectSize(sizeof(mirror::Constructor)); java_lang_reflect_Constructor->SetSuperClass(java_lang_reflect_AbstractMethod.get()); SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get()); - java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved); + java_lang_reflect_Constructor->SetStatus(mirror::Class::kStatusResolved); - SirtRef<Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(), - sizeof(MethodClass))); + SirtRef<mirror::Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(), + sizeof(mirror::AbstractMethodClass))); CHECK(java_lang_reflect_Method.get() != NULL); - java_lang_reflect_Method->SetObjectSize(sizeof(Method)); + java_lang_reflect_Method->SetObjectSize(sizeof(mirror::Method)); java_lang_reflect_Method->SetSuperClass(java_lang_reflect_AbstractMethod.get()); SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get()); - java_lang_reflect_Method->SetStatus(Class::kStatusResolved); + java_lang_reflect_Method->SetStatus(mirror::Class::kStatusResolved); - AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get()); + mirror::AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(), + java_lang_reflect_Method.get()); // Set up array classes for string, field, method - SirtRef<Class> object_array_string(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> object_array_string(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); object_array_string->SetComponentType(java_lang_String.get()); SetClassRoot(kJavaLangStringArrayClass, object_array_string.get()); - SirtRef<Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get()); SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get()); - SirtRef<Class> object_array_field(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> object_array_field(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); object_array_field->SetComponentType(java_lang_reflect_Field.get()); SetClassRoot(kJavaLangReflectFieldArrayClass, object_array_field.get()); - SirtRef<Class> object_array_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); + SirtRef<mirror::Class> object_array_method(self, AllocClass(self, java_lang_Class.get(), sizeof(mirror::Class))); object_array_method->SetComponentType(java_lang_reflect_Method.get()); SetClassRoot(kJavaLangReflectMethodArrayClass, object_array_method.get()); @@ -382,55 +397,55 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class SetClassRoot(kPrimitiveChar, char_class.get()); // needs descriptor // Object, String and DexCache need to be rerun through FindSystemClass to finish init - java_lang_Object->SetStatus(Class::kStatusNotReady); - Class* Object_class = FindSystemClass("Ljava/lang/Object;"); + java_lang_Object->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* Object_class = FindSystemClass("Ljava/lang/Object;"); CHECK_EQ(java_lang_Object.get(), Object_class); - CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(Object)); - java_lang_String->SetStatus(Class::kStatusNotReady); - Class* String_class = FindSystemClass("Ljava/lang/String;"); + CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(mirror::Object)); + java_lang_String->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* String_class = FindSystemClass("Ljava/lang/String;"); CHECK_EQ(java_lang_String.get(), String_class); - CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(String)); - java_lang_DexCache->SetStatus(Class::kStatusNotReady); - Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;"); + CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(mirror::String)); + java_lang_DexCache->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;"); CHECK_EQ(java_lang_String.get(), String_class); CHECK_EQ(java_lang_DexCache.get(), DexCache_class); - CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(DexCache)); + CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(mirror::DexCache)); // Setup the primitive array type classes - can't be done until Object has a vtable. SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z")); - BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); + mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); SetClassRoot(kByteArrayClass, FindSystemClass("[B")); - ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); + mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); - Class* found_char_array_class = FindSystemClass("[C"); + mirror::Class* found_char_array_class = FindSystemClass("[C"); CHECK_EQ(char_array_class.get(), found_char_array_class); SetClassRoot(kShortArrayClass, FindSystemClass("[S")); - ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); + mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); - Class* found_int_array_class = FindSystemClass("[I"); + mirror::Class* found_int_array_class = FindSystemClass("[I"); CHECK_EQ(int_array_class.get(), found_int_array_class); SetClassRoot(kLongArrayClass, FindSystemClass("[J")); - LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); + mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); SetClassRoot(kFloatArrayClass, FindSystemClass("[F")); - FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); + mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); SetClassRoot(kDoubleArrayClass, FindSystemClass("[D")); - DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); + mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); - Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;"); + mirror::Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;"); CHECK_EQ(class_array_class.get(), found_class_array_class); - Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;"); + mirror::Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;"); CHECK_EQ(object_array_class.get(), found_object_array_class); // Setup the single, global copy of "iftable". - Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;"); + mirror::Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;"); CHECK(java_lang_Cloneable != NULL); - Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;"); + mirror::Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;"); CHECK(java_io_Serializable != NULL); // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to // crawl up and explicitly list all of the supers as well. @@ -446,79 +461,79 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1)); // Run Class, Constructor, Field, and Method through FindSystemClass. This initializes their // dex_cache_ fields and register them in classes_. - Class* Class_class = FindSystemClass("Ljava/lang/Class;"); + mirror::Class* Class_class = FindSystemClass("Ljava/lang/Class;"); CHECK_EQ(java_lang_Class.get(), Class_class); - java_lang_reflect_AbstractMethod->SetStatus(Class::kStatusNotReady); - Class* Abstract_method_class = FindSystemClass("Ljava/lang/reflect/AbstractMethod;"); + java_lang_reflect_AbstractMethod->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* Abstract_method_class = FindSystemClass("Ljava/lang/reflect/AbstractMethod;"); CHECK_EQ(java_lang_reflect_AbstractMethod.get(), Abstract_method_class); // Method extends AbstractMethod so must reset after. - java_lang_reflect_Method->SetStatus(Class::kStatusNotReady); - Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;"); + java_lang_reflect_Method->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;"); CHECK_EQ(java_lang_reflect_Method.get(), Method_class); // Constructor extends AbstractMethod so must reset after. - java_lang_reflect_Constructor->SetStatus(Class::kStatusNotReady); - Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;"); + java_lang_reflect_Constructor->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;"); CHECK_EQ(java_lang_reflect_Constructor.get(), Constructor_class); - java_lang_reflect_Field->SetStatus(Class::kStatusNotReady); - Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;"); + java_lang_reflect_Field->SetStatus(mirror::Class::kStatusNotReady); + mirror::Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;"); CHECK_EQ(java_lang_reflect_Field.get(), Field_class); - Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]); + mirror::Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]); CHECK_EQ(object_array_string.get(), String_array_class); - Class* Abstract_method_array_class = + mirror::Class* Abstract_method_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]); CHECK_EQ(object_array_abstract_method.get(), Abstract_method_array_class); - Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]); + mirror::Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]); CHECK_EQ(object_array_field.get(), Field_array_class); - Class* Method_array_class = + mirror::Class* Method_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectMethodArrayClass]); CHECK_EQ(object_array_method.get(), Method_array_class); // End of special init trickery, subsequent classes may be loaded via FindSystemClass. // Create java.lang.reflect.Proxy root. - Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;"); + mirror::Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;"); SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy); // java.lang.ref classes need to be specially flagged, but otherwise are normal classes - Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;"); + mirror::Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;"); SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference); - Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;"); + mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;"); java_lang_ref_FinalizerReference->SetAccessFlags( java_lang_ref_FinalizerReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsFinalizerReference); - Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;"); + mirror::Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;"); java_lang_ref_PhantomReference->SetAccessFlags( java_lang_ref_PhantomReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsPhantomReference); - Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;"); + mirror::Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;"); java_lang_ref_SoftReference->SetAccessFlags( java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference); - Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;"); + mirror::Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;"); java_lang_ref_WeakReference->SetAccessFlags( java_lang_ref_WeakReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsWeakReference); // Setup the ClassLoader, verifying the object_size_. - Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;"); - CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(ClassLoader)); + mirror::Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;"); + CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(mirror::ClassLoader)); SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader); // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and // java.lang.StackTraceElement as a convenience. SetClassRoot(kJavaLangThrowable, FindSystemClass("Ljava/lang/Throwable;")); - Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); + mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass("Ljava/lang/ClassNotFoundException;")); SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;")); SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;")); - StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); + mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); FinishInit(); @@ -532,37 +547,37 @@ void ClassLinker::FinishInit() { // Note: we hard code the field indexes here rather than using FindInstanceField // as the types of the field can't be resolved prior to the runtime being // fully initialized - Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference); - Class* java_lang_ref_ReferenceQueue = FindSystemClass("Ljava/lang/ref/ReferenceQueue;"); - Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;"); + mirror::Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference); + mirror::Class* java_lang_ref_ReferenceQueue = FindSystemClass("Ljava/lang/ref/ReferenceQueue;"); + mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;"); const DexFile& java_lang_dex = *java_lang_ref_Reference->GetDexCache()->GetDexFile(); - Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0); + mirror::Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0); FieldHelper fh(pendingNext, this); CHECK_STREQ(fh.GetName(), "pendingNext"); CHECK_EQ(java_lang_dex.GetFieldId(pendingNext->GetDexFieldIndex()).type_idx_, java_lang_ref_Reference->GetDexTypeIndex()); - Field* queue = java_lang_ref_Reference->GetInstanceField(1); + mirror::Field* queue = java_lang_ref_Reference->GetInstanceField(1); fh.ChangeField(queue); CHECK_STREQ(fh.GetName(), "queue"); CHECK_EQ(java_lang_dex.GetFieldId(queue->GetDexFieldIndex()).type_idx_, java_lang_ref_ReferenceQueue->GetDexTypeIndex()); - Field* queueNext = java_lang_ref_Reference->GetInstanceField(2); + mirror::Field* queueNext = java_lang_ref_Reference->GetInstanceField(2); fh.ChangeField(queueNext); CHECK_STREQ(fh.GetName(), "queueNext"); CHECK_EQ(java_lang_dex.GetFieldId(queueNext->GetDexFieldIndex()).type_idx_, java_lang_ref_Reference->GetDexTypeIndex()); - Field* referent = java_lang_ref_Reference->GetInstanceField(3); + mirror::Field* referent = java_lang_ref_Reference->GetInstanceField(3); fh.ChangeField(referent); CHECK_STREQ(fh.GetName(), "referent"); CHECK_EQ(java_lang_dex.GetFieldId(referent->GetDexFieldIndex()).type_idx_, GetClassRoot(kJavaLangObject)->GetDexTypeIndex()); - Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2); + mirror::Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2); fh.ChangeField(zombie); CHECK_STREQ(fh.GetName(), "zombie"); CHECK_EQ(java_lang_dex.GetFieldId(zombie->GetDexFieldIndex()).type_idx_, @@ -578,7 +593,7 @@ void ClassLinker::FinishInit() { // ensure all class_roots_ are initialized for (size_t i = 0; i < kClassRootsMax; i++) { ClassRoot class_root = static_cast<ClassRoot>(i); - Class* klass = GetClassRoot(class_root); + mirror::Class* klass = GetClassRoot(class_root); CHECK(klass != NULL); DCHECK(klass->IsArrayClass() || klass->IsPrimitive() || klass->GetDexCache() != NULL); // note SetClassRoot does additional validation. @@ -597,7 +612,7 @@ void ClassLinker::FinishInit() { void ClassLinker::RunRootClinits() { Thread* self = Thread::Current(); for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) { - Class* c = GetClassRoot(ClassRoot(i)); + mirror::Class* c = GetClassRoot(ClassRoot(i)); if (!c->IsArrayClass() && !c->IsPrimitive()) { EnsureInitialized(GetClassRoot(ClassRoot(i)), true, true); self->AssertNoPendingException(); @@ -699,7 +714,8 @@ OatFile* ClassLinker::OpenOat(const ImageSpace* space) { const ImageHeader& image_header = space->GetImageHeader(); // Grab location but don't use Object::AsString as we haven't yet initialized the roots to // check the down cast - String* oat_location = down_cast<String*>(image_header.GetImageRoot(ImageHeader::kOatLocation)); + mirror::String* oat_location = + down_cast<mirror::String*>(image_header.GetImageRoot(ImageHeader::kOatLocation)); std::string oat_filename; oat_filename += runtime->GetHostPrefix(); oat_filename += oat_location->ToModifiedUtf8(); @@ -971,21 +987,22 @@ void ClassLinker::InitFromImage() { CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U); CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0U); CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty()); - Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); - ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>(); + mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); + mirror::ObjectArray<mirror::DexCache>* dex_caches = + dex_caches_object->AsObjectArray<mirror::DexCache>(); - ObjectArray<Class>* class_roots = - space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<Class>(); + mirror::ObjectArray<mirror::Class>* class_roots = + space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<mirror::Class>(); // Special case of setting up the String class early so that we can test arbitrary objects // as being Strings or not - String::SetClass(class_roots->Get(kJavaLangString)); + mirror::String::SetClass(class_roots->Get(kJavaLangString)); CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(), static_cast<uint32_t>(dex_caches->GetLength())); Thread* self = Thread::Current(); for (int i = 0; i < dex_caches->GetLength(); i++) { - SirtRef<DexCache> dex_cache(self, dex_caches->Get(i)); + SirtRef<mirror::DexCache> dex_cache(self, dex_caches->Get(i)); const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8()); const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location); CHECK(oat_dex_file != NULL) << oat_file->GetLocation() << " " << dex_file_location; @@ -1008,33 +1025,33 @@ void ClassLinker::InitFromImage() { } // reinit class_roots_ - Class::SetClassClass(class_roots->Get(kJavaLangClass)); + mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass)); class_roots_ = class_roots; // reinit array_iftable_ from any array class instance, they should be == array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable(); DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable()); // String class root was set above - Field::SetClass(GetClassRoot(kJavaLangReflectField)); - AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor), + mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField)); + mirror::AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod)); - BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); - ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); - CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); - DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); - FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); - IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); - LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); - ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); - Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); - StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); + mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); + mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); + mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); + mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); + mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); + mirror::IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); + mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); + mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); + mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); + mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); FinishInit(); VLOG(startup) << "ClassLinker::InitFromImage exiting"; } -void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { +void ClassLinker::InitFromImageCallback(mirror::Object* obj, void* arg) { DCHECK(obj != NULL); DCHECK(arg != NULL); ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg); @@ -1045,9 +1062,9 @@ void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { } if (obj->IsClass()) { // restore class to ClassLinker::classes_ table - Class* klass = obj->AsClass(); + mirror::Class* klass = obj->AsClass(); ClassHelper kh(klass, class_linker); - Class* existing = class_linker->InsertClass(kh.GetDescriptor(), klass, true); + mirror::Class* existing = class_linker->InsertClass(kh.GetDescriptor(), klass, true); DCHECK(existing == NULL) << kh.GetDescriptor(); return; } @@ -1056,7 +1073,7 @@ void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { // Keep in sync with InitCallback. Anything we visit, we need to // reinit references to when reinitializing a ClassLinker from a // mapped image. -void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void ClassLinker::VisitRoots(RootVisitor* visitor, void* arg) { visitor(class_roots_, arg); Thread* self = Thread::Current(); { @@ -1096,16 +1113,16 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const { } } -static bool GetClassesVisitor(Class* c, void* arg) { - std::set<Class*>* classes = reinterpret_cast<std::set<Class*>*>(arg); +static bool GetClassesVisitor(mirror::Class* c, void* arg) { + std::set<mirror::Class*>* classes = reinterpret_cast<std::set<mirror::Class*>*>(arg); classes->insert(c); return true; } void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) const { - std::set<Class*> classes; + std::set<mirror::Class*> classes; VisitClasses(GetClassesVisitor, &classes); - typedef std::set<Class*>::const_iterator It; // TODO: C++0x auto + typedef std::set<mirror::Class*>::const_iterator It; // TODO: C++0x auto for (It it = classes.begin(), end = classes.end(); it != end; ++it) { if (!visitor(*it, arg)) { return; @@ -1115,57 +1132,61 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* ar ClassLinker::~ClassLinker() { - Class::ResetClass(); - String::ResetClass(); - Field::ResetClass(); - AbstractMethod::ResetClasses(); - BooleanArray::ResetArrayClass(); - ByteArray::ResetArrayClass(); - CharArray::ResetArrayClass(); - DoubleArray::ResetArrayClass(); - FloatArray::ResetArrayClass(); - IntArray::ResetArrayClass(); - LongArray::ResetArrayClass(); - ShortArray::ResetArrayClass(); - Throwable::ResetClass(); - StackTraceElement::ResetClass(); + mirror::Class::ResetClass(); + mirror::String::ResetClass(); + mirror::Field::ResetClass(); + mirror::AbstractMethod::ResetClasses(); + mirror::BooleanArray::ResetArrayClass(); + mirror::ByteArray::ResetArrayClass(); + mirror::CharArray::ResetArrayClass(); + mirror::DoubleArray::ResetArrayClass(); + mirror::FloatArray::ResetArrayClass(); + mirror::IntArray::ResetArrayClass(); + mirror::LongArray::ResetArrayClass(); + mirror::ShortArray::ResetArrayClass(); + mirror::Throwable::ResetClass(); + mirror::StackTraceElement::ResetClass(); STLDeleteElements(&boot_class_path_); STLDeleteElements(&oat_files_); } -DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { +mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { Heap* heap = Runtime::Current()->GetHeap(); - Class* dex_cache_class = GetClassRoot(kJavaLangDexCache); - SirtRef<DexCache> dex_cache(self, - down_cast<DexCache*>(heap->AllocObject(self, dex_cache_class, - dex_cache_class->GetObjectSize()))); + mirror::Class* dex_cache_class = GetClassRoot(kJavaLangDexCache); + SirtRef<mirror::DexCache> dex_cache(self, + down_cast<mirror::DexCache*>(heap->AllocObject(self, dex_cache_class, + dex_cache_class->GetObjectSize()))); if (dex_cache.get() == NULL) { return NULL; } - SirtRef<String> location(self, intern_table_->InternStrong(dex_file.GetLocation().c_str())); + SirtRef<mirror::String> + location(self, intern_table_->InternStrong(dex_file.GetLocation().c_str())); if (location.get() == NULL) { return NULL; } - SirtRef<ObjectArray<String> > strings(self, AllocStringArray(self, dex_file.NumStringIds())); + SirtRef<mirror::ObjectArray<mirror::String> > + strings(self, AllocStringArray(self, dex_file.NumStringIds())); if (strings.get() == NULL) { return NULL; } - SirtRef<ObjectArray<Class> > types(self, AllocClassArray(self, dex_file.NumTypeIds())); + SirtRef<mirror::ObjectArray<mirror::Class> > + types(self, AllocClassArray(self, dex_file.NumTypeIds())); if (types.get() == NULL) { return NULL; } - SirtRef<ObjectArray<AbstractMethod> > + SirtRef<mirror::ObjectArray<mirror::AbstractMethod> > methods(self, AllocAbstractMethodArray(self, dex_file.NumMethodIds())); if (methods.get() == NULL) { return NULL; } - SirtRef<ObjectArray<Field> > fields(self, AllocFieldArray(self, dex_file.NumFieldIds())); + SirtRef<mirror::ObjectArray<mirror::Field> > + fields(self, AllocFieldArray(self, dex_file.NumFieldIds())); if (fields.get() == NULL) { return NULL; } - SirtRef<ObjectArray<StaticStorageBase> > + SirtRef<mirror::ObjectArray<mirror::StaticStorageBase> > initialized_static_storage(self, - AllocObjectArray<StaticStorageBase>(self, dex_file.NumTypeIds())); + AllocObjectArray<mirror::StaticStorageBase>(self, dex_file.NumTypeIds())); if (initialized_static_storage.get() == NULL) { return NULL; } @@ -1180,40 +1201,41 @@ DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { return dex_cache.get(); } -Class* ClassLinker::AllocClass(Thread* self, Class* java_lang_Class, size_t class_size) { - DCHECK_GE(class_size, sizeof(Class)); +mirror::Class* ClassLinker::AllocClass(Thread* self, mirror::Class* java_lang_Class, + size_t class_size) { + DCHECK_GE(class_size, sizeof(mirror::Class)); Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Class> klass(self, + SirtRef<mirror::Class> klass(self, heap->AllocObject(self, java_lang_Class, class_size)->AsClass()); klass->SetPrimitiveType(Primitive::kPrimNot); // default to not being primitive klass->SetClassSize(class_size); return klass.get(); } -Class* ClassLinker::AllocClass(Thread* self, size_t class_size) { +mirror::Class* ClassLinker::AllocClass(Thread* self, size_t class_size) { return AllocClass(self, GetClassRoot(kJavaLangClass), class_size); } -Field* ClassLinker::AllocField(Thread* self) { - return down_cast<Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject(self)); +mirror::Field* ClassLinker::AllocField(Thread* self) { + return down_cast<mirror::Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject(self)); } -Method* ClassLinker::AllocMethod(Thread* self) { - return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject(self)); +mirror::Method* ClassLinker::AllocMethod(Thread* self) { + return down_cast<mirror::Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject(self)); } -Constructor* ClassLinker::AllocConstructor(Thread* self) { - return down_cast<Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject(self)); +mirror::Constructor* ClassLinker::AllocConstructor(Thread* self) { + return down_cast<mirror::Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject(self)); } -ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(Thread* self, - size_t length) { - return ObjectArray<StackTraceElement>::Alloc(self, - GetClassRoot(kJavaLangStackTraceElementArrayClass), - length); +mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(Thread* self, + size_t length) { + return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(self, + GetClassRoot(kJavaLangStackTraceElementArrayClass), + length); } -static Class* EnsureResolved(Thread* self, Class* klass) +static mirror::Class* EnsureResolved(Thread* self, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(klass != NULL); // Wait for the class if it has not already been linked. @@ -1223,7 +1245,7 @@ static Class* EnsureResolved(Thread* self, Class* klass) if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) { self->ThrowNewException("Ljava/lang/ClassCircularityError;", PrettyDescriptor(klass).c_str()); - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return NULL; } // Wait for the pending initialization to complete. @@ -1243,11 +1265,11 @@ static Class* EnsureResolved(Thread* self, Class* klass) return klass; } -Class* ClassLinker::FindSystemClass(const char* descriptor) { +mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) { return FindClass(descriptor, NULL); } -Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) { +mirror::Class* ClassLinker::FindClass(const char* descriptor, mirror::ClassLoader* class_loader) { DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; Thread* self = Thread::Current(); DCHECK(self != NULL); @@ -1258,7 +1280,7 @@ Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) return FindPrimitiveClass(descriptor[0]); } // Find the class in the loaded classes table. - Class* klass = LookupClass(descriptor, class_loader); + mirror::Class* klass = LookupClass(descriptor, class_loader); if (klass != NULL) { return EnsureResolved(self, klass); } @@ -1274,7 +1296,7 @@ Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) } else if (Runtime::Current()->UseCompileTimeClassPath()) { // first try the boot class path - Class* system_class = FindSystemClass(descriptor); + mirror::Class* system_class = FindSystemClass(descriptor); if (system_class != NULL) { return system_class; } @@ -1321,8 +1343,8 @@ Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) class_name_string.c_str()); return NULL; } else { - // success, return Class* - return soa.Decode<Class*>(result.get()); + // success, return mirror::Class* + return soa.Decode<mirror::Class*>(result.get()); } } @@ -1330,12 +1352,12 @@ Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) return NULL; } -Class* ClassLinker::DefineClass(const StringPiece& descriptor, - ClassLoader* class_loader, - const DexFile& dex_file, - const DexFile::ClassDef& dex_class_def) { +mirror::Class* ClassLinker::DefineClass(const StringPiece& descriptor, + mirror::ClassLoader* class_loader, + const DexFile& dex_file, + const DexFile::ClassDef& dex_class_def) { Thread* self = Thread::Current(); - SirtRef<Class> klass(self, NULL); + SirtRef<mirror::Class> klass(self, NULL); // Load the class from the dex file. if (!init_done_) { // finish up init of hand crafted class_roots_ @@ -1365,13 +1387,13 @@ Class* ClassLinker::DefineClass(const StringPiece& descriptor, LoadClass(dex_file, dex_class_def, klass, class_loader); // Check for a pending exception during load if (self->IsExceptionPending()) { - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return NULL; } ObjectLock lock(self, klass.get()); klass->SetClinitThreadId(self->GetTid()); // Add the newly loaded class to the loaded classes table. - SirtRef<Class> existing(self, InsertClass(descriptor, klass.get(), false)); + SirtRef<mirror::Class> existing(self, InsertClass(descriptor, klass.get(), false)); if (existing.get() != NULL) { // We failed to insert because we raced with another thread. return EnsureResolved(self, existing.get()); @@ -1380,7 +1402,7 @@ Class* ClassLinker::DefineClass(const StringPiece& descriptor, CHECK(!klass->IsLoaded()); if (!LoadSuperAndInterfaces(klass, dex_file)) { // Loading failed. - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); lock.NotifyAll(); return NULL; } @@ -1389,7 +1411,7 @@ Class* ClassLinker::DefineClass(const StringPiece& descriptor, CHECK(!klass->IsResolved()); if (!LinkClass(klass, NULL)) { // Linking failed. - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); lock.NotifyAll(); return NULL; } @@ -1433,7 +1455,7 @@ size_t ClassLinker::SizeOfClass(const DexFile& dex_file, } } // start with generic class data - size_t size = sizeof(Class); + size_t size = sizeof(mirror::Class); // follow with reference fields which must be contiguous at start size += (num_ref * sizeof(uint32_t)); // if there are 64-bit fields to add, make sure they are aligned @@ -1502,10 +1524,10 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint32 return 0; } -const OatFile::OatMethod ClassLinker::GetOatMethodFor(const AbstractMethod* method) { +const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::AbstractMethod* method) { // Although we overwrite the trampoline of non-static methods, we may get here via the resolution // method for direct methods (or virtual methods made direct). - Class* declaring_class = method->GetDeclaringClass(); + mirror::Class* declaring_class = method->GetDeclaringClass(); size_t oat_method_index; if (method->IsStatic() || method->IsDirect()) { // Simple case where the oat method index was stashed at load time. @@ -1536,7 +1558,7 @@ const OatFile::OatMethod ClassLinker::GetOatMethodFor(const AbstractMethod* meth } // Special case to get oat code without overwriting a trampoline. -const void* ClassLinker::GetOatCodeFor(const AbstractMethod* method) { +const void* ClassLinker::GetOatCodeFor(const mirror::AbstractMethod* method) { CHECK(Runtime::Current()->IsCompiler() || method->GetDeclaringClass()->IsInitializing()); return GetOatMethodFor(method).GetCode(); } @@ -1550,7 +1572,7 @@ const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint32_t method_ return oat_class->GetOatMethod(oat_method_idx).GetCode(); } -void ClassLinker::FixupStaticTrampolines(Class* klass) { +void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { ClassHelper kh(klass); const DexFile::ClassDef* dex_class_def = kh.GetClassDef(); CHECK(dex_class_def != NULL); @@ -1577,7 +1599,7 @@ void ClassLinker::FixupStaticTrampolines(Class* klass) { // Link the code of methods skipped by LinkCode const void* trampoline = Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData(); for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) { - AbstractMethod* method = klass->GetDirectMethod(i); + mirror::AbstractMethod* method = klass->GetDirectMethod(i); if (Runtime::Current()->IsMethodTracingActive()) { Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (instrumentation->GetSavedCodeFromMap(method) == trampoline) { @@ -1596,7 +1618,7 @@ void ClassLinker::FixupStaticTrampolines(Class* klass) { } } -static void LinkCode(SirtRef<AbstractMethod>& method, const OatFile::OatClass* oat_class, +static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::OatClass* oat_class, uint32_t method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Every kind of method should at least get an invoke stub from the oat_method. @@ -1627,11 +1649,11 @@ static void LinkCode(SirtRef<AbstractMethod>& method, const OatFile::OatClass* o void ClassLinker::LoadClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - SirtRef<Class>& klass, - ClassLoader* class_loader) { + SirtRef<mirror::Class>& klass, + mirror::ClassLoader* class_loader) { CHECK(klass.get() != NULL); CHECK(klass->GetDexCache() != NULL); - CHECK_EQ(Class::kStatusNotReady, klass->GetStatus()); + CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus()); const char* descriptor = dex_file.GetClassDescriptor(dex_class_def); CHECK(descriptor != NULL); @@ -1643,7 +1665,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file, klass->SetAccessFlags(access_flags); klass->SetClassLoader(class_loader); DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot); - klass->SetStatus(Class::kStatusIdx); + klass->SetStatus(mirror::Class::kStatusIdx); klass->SetDexTypeIndex(dex_class_def.class_idx_); @@ -1661,12 +1683,12 @@ void ClassLinker::LoadClass(const DexFile& dex_file, klass->SetIFields(AllocFieldArray(self, it.NumInstanceFields())); } for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) { - SirtRef<Field> sfield(self, AllocField(self)); + SirtRef<mirror::Field> sfield(self, AllocField(self)); klass->SetStaticField(i, sfield.get()); LoadField(dex_file, it, klass, sfield); } for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) { - SirtRef<Field> ifield(self, AllocField(self)); + SirtRef<mirror::Field> ifield(self, AllocField(self)); klass->SetInstanceField(i, ifield.get()); LoadField(dex_file, it, klass, ifield); } @@ -1687,7 +1709,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file, } size_t class_def_method_index = 0; for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) { - SirtRef<AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); + SirtRef<mirror::AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); klass->SetDirectMethod(i, method.get()); if (oat_class.get() != NULL) { LinkCode(method, oat_class.get(), class_def_method_index); @@ -1696,7 +1718,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file, class_def_method_index++; } for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) { - SirtRef<AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); + SirtRef<mirror::AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); klass->SetVirtualMethod(i, method.get()); DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); if (oat_class.get() != NULL) { @@ -1708,21 +1730,21 @@ void ClassLinker::LoadClass(const DexFile& dex_file, } void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it, - SirtRef<Class>& klass, SirtRef<Field>& dst) { + SirtRef<mirror::Class>& klass, SirtRef<mirror::Field>& dst) { uint32_t field_idx = it.GetMemberIndex(); dst->SetDexFieldIndex(field_idx); dst->SetDeclaringClass(klass.get()); dst->SetAccessFlags(it.GetMemberAccessFlags()); } -AbstractMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, - const ClassDataItemIterator& it, - SirtRef<Class>& klass) { +mirror::AbstractMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, + const ClassDataItemIterator& it, + SirtRef<mirror::Class>& klass) { uint32_t dex_method_idx = it.GetMemberIndex(); const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); StringPiece method_name(dex_file.GetMethodName(method_id)); - AbstractMethod* dst = NULL; + mirror::AbstractMethod* dst = NULL; if (method_name == "<init>") { dst = AllocConstructor(self); } else { @@ -1780,11 +1802,11 @@ AbstractMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) { Thread* self = Thread::Current(); - SirtRef<DexCache> dex_cache(self, AllocDexCache(self, dex_file)); + SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file)); AppendToBootClassPath(dex_file, dex_cache); } -void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) { +void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) { CHECK(dex_cache.get() != NULL) << dex_file.GetLocation(); boot_class_path_.push_back(&dex_file); RegisterDexFile(dex_file, dex_cache); @@ -1805,7 +1827,7 @@ bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const { return IsDexFileRegisteredLocked(dex_file); } -void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) { +void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) { dex_lock_.AssertHeld(Thread::Current()); CHECK(dex_cache.get() != NULL) << dex_file.GetLocation(); CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation())); @@ -1825,7 +1847,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) { // Don't alloc while holding the lock, since allocation may need to // suspend all threads and another thread may need the dex_lock_ to // get to a suspend point. - SirtRef<DexCache> dex_cache(self, AllocDexCache(self, dex_file)); + SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file)); { MutexLock mu(self, dex_lock_); if (IsDexFileRegisteredLocked(dex_file)) { @@ -1835,16 +1857,16 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) { } } -void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) { +void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) { MutexLock mu(Thread::Current(), dex_lock_); RegisterDexFileLocked(dex_file, dex_cache); } -DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { +mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { MutexLock mu(Thread::Current(), dex_lock_); // Search assuming unique-ness of dex file. for (size_t i = 0; i != dex_caches_.size(); ++i) { - DexCache* dex_cache = dex_caches_[i]; + mirror::DexCache* dex_cache = dex_caches_[i]; if (dex_cache->GetDexFile() == &dex_file) { return dex_cache; } @@ -1852,35 +1874,39 @@ DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { // Search matching by location name. std::string location(dex_file.GetLocation()); for (size_t i = 0; i != dex_caches_.size(); ++i) { - DexCache* dex_cache = dex_caches_[i]; + mirror::DexCache* dex_cache = dex_caches_[i]; if (dex_cache->GetDexFile()->GetLocation() == location) { return dex_cache; } } // Failure, dump diagnostic and abort. for (size_t i = 0; i != dex_caches_.size(); ++i) { - DexCache* dex_cache = dex_caches_[i]; + mirror::DexCache* dex_cache = dex_caches_[i]; LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation(); } LOG(FATAL) << "Failed to find DexCache for DexFile " << location; return NULL; } -void ClassLinker::FixupDexCaches(AbstractMethod* resolution_method) const { +void ClassLinker::FixupDexCaches(mirror::AbstractMethod* resolution_method) const { MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i != dex_caches_.size(); ++i) { dex_caches_[i]->Fixup(resolution_method); } } -Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class, Primitive::Type type) { +mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) { + return InitializePrimitiveClass(AllocClass(self, sizeof(mirror::Class)), type); +} + +mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) { CHECK(primitive_class != NULL); // Must hold lock on object when initializing. ObjectLock lock(Thread::Current(), primitive_class); primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract); primitive_class->SetPrimitiveType(type); - primitive_class->SetStatus(Class::kStatusInitialized); - Class* existing = InsertClass(Primitive::Descriptor(type), primitive_class, false); + primitive_class->SetStatus(mirror::Class::kStatusInitialized); + mirror::Class* existing = InsertClass(Primitive::Descriptor(type), primitive_class, false); CHECK(existing == NULL) << "InitPrimitiveClass(" << type << ") failed"; return primitive_class; } @@ -1898,11 +1924,12 @@ Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class, Primitive:: // array class; that always comes from the base element class. // // Returns NULL with an exception raised on failure. -Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* class_loader) { +mirror::Class* ClassLinker::CreateArrayClass(const std::string& descriptor, + mirror::ClassLoader* class_loader) { CHECK_EQ('[', descriptor[0]); // Identify the underlying component type - Class* component_type = FindClass(descriptor.substr(1).c_str(), class_loader); + mirror::Class* component_type = FindClass(descriptor.substr(1).c_str(), class_loader); if (component_type == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return NULL; @@ -1926,7 +1953,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* // class to the hash table --- necessary because of possible races with // other threads.) if (class_loader != component_type->GetClassLoader()) { - Class* new_class = LookupClass(descriptor.c_str(), component_type->GetClassLoader()); + mirror::Class* new_class = LookupClass(descriptor.c_str(), component_type->GetClassLoader()); if (new_class != NULL) { return new_class; } @@ -1941,7 +1968,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* // Array classes are simple enough that we don't need to do a full // link step. Thread* self = Thread::Current(); - SirtRef<Class> new_class(self, NULL); + SirtRef<mirror::Class> new_class(self, NULL); if (!init_done_) { // Classes that were hand created, ie not by FindSystemClass if (descriptor == "[Ljava/lang/Class;") { @@ -1963,7 +1990,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* } } if (new_class.get() == NULL) { - new_class.reset(AllocClass(self, sizeof(Class))); + new_class.reset(AllocClass(self, sizeof(mirror::Class))); if (new_class.get() == NULL) { return NULL; } @@ -1971,12 +1998,12 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* } ObjectLock lock(self, new_class.get()); // Must hold lock on object when initializing. DCHECK(new_class->GetComponentType() != NULL); - Class* java_lang_Object = GetClassRoot(kJavaLangObject); + mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject); new_class->SetSuperClass(java_lang_Object); new_class->SetVTable(java_lang_Object->GetVTable()); new_class->SetPrimitiveType(Primitive::kPrimNot); new_class->SetClassLoader(component_type->GetClassLoader()); - new_class->SetStatus(Class::kStatusInitialized); + new_class->SetStatus(mirror::Class::kStatusInitialized); // don't need to set new_class->SetObjectSize(..) // because Object::SizeOf delegates to Array::SizeOf @@ -2006,7 +2033,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() & ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask); - Class* existing = InsertClass(descriptor, new_class.get(), false); + mirror::Class* existing = InsertClass(descriptor, new_class.get(), false); if (existing == NULL) { return new_class.get(); } @@ -2019,7 +2046,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* return existing; } -Class* ClassLinker::FindPrimitiveClass(char type) { +mirror::Class* ClassLinker::FindPrimitiveClass(char type) { switch (Primitive::GetType(type)) { case Primitive::kPrimByte: return GetClassRoot(kPrimitiveByte); @@ -2047,9 +2074,9 @@ Class* ClassLinker::FindPrimitiveClass(char type) { return NULL; } -Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, bool image_class) { +mirror::Class* ClassLinker::InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool image_class) { if (VLOG_IS_ON(class_linker)) { - DexCache* dex_cache = klass->GetDexCache(); + mirror::DexCache* dex_cache = klass->GetDexCache(); std::string source; if (dex_cache != NULL) { source += " from "; @@ -2060,7 +2087,7 @@ Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, boo size_t hash = StringPieceHash()(descriptor); MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); Table& classes = image_class ? image_classes_ : classes_; - Class* existing = LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, classes); + mirror::Class* existing = LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, classes); #ifndef NDEBUG // Check we don't have the class in the other table in error Table& other_classes = image_class ? classes_ : image_classes_; @@ -2074,22 +2101,24 @@ Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, boo return NULL; } -bool ClassLinker::RemoveClass(const char* descriptor, const ClassLoader* class_loader) { +bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader* class_loader) { size_t hash = Hash(descriptor); MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::iterator It; // TODO: C++0x auto // TODO: determine if its better to search classes_ or image_classes_ first ClassHelper kh; - for (It it = classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) { - Class* klass = it->second; + for (It it = classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; + ++it) { + mirror::Class* klass = it->second; kh.ChangeClass(klass); if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) { classes_.erase(it); return true; } } - for (It it = image_classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) { - Class* klass = it->second; + for (It it = image_classes_.lower_bound(hash), end = classes_.end(); + it != end && it->first == hash; ++it) { + mirror::Class* klass = it->second; kh.ChangeClass(klass); if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) { image_classes_.erase(it); @@ -2099,28 +2128,30 @@ bool ClassLinker::RemoveClass(const char* descriptor, const ClassLoader* class_l return false; } -Class* ClassLinker::LookupClass(const char* descriptor, const ClassLoader* class_loader) { +mirror::Class* ClassLinker::LookupClass(const char* descriptor, + const mirror::ClassLoader* class_loader) { size_t hash = Hash(descriptor); MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); // TODO: determine if its better to search classes_ or image_classes_ first - Class* klass = LookupClassLocked(descriptor, class_loader, hash, classes_); + mirror::Class* klass = LookupClassLocked(descriptor, class_loader, hash, classes_); if (klass != NULL) { return klass; } return LookupClassLocked(descriptor, class_loader, hash, image_classes_); } -Class* ClassLinker::LookupClassLocked(const char* descriptor, const ClassLoader* class_loader, - size_t hash, const Table& classes) { +mirror::Class* ClassLinker::LookupClassLocked(const char* descriptor, + const mirror::ClassLoader* class_loader, + size_t hash, const Table& classes) { ClassHelper kh(NULL, this); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = classes.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) { - Class* klass = it->second; + mirror::Class* klass = it->second; kh.ChangeClass(klass); if (strcmp(descriptor, kh.GetDescriptor()) == 0 && klass->GetClassLoader() == class_loader) { #ifndef NDEBUG for (++it; it != end && it->first == hash; ++it) { - Class* klass2 = it->second; + mirror::Class* klass2 = it->second; kh.ChangeClass(klass2); CHECK(!(strcmp(descriptor, kh.GetDescriptor()) == 0 && klass2->GetClassLoader() == class_loader)) << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " " @@ -2133,7 +2164,7 @@ Class* ClassLinker::LookupClassLocked(const char* descriptor, const ClassLoader* return NULL; } -void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& classes) { +void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& classes) { classes.clear(); size_t hash = Hash(descriptor); MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); @@ -2141,14 +2172,14 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& cla // TODO: determine if its better to search classes_ or image_classes_ first ClassHelper kh(NULL, this); for (It it = classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) { - Class* klass = it->second; + mirror::Class* klass = it->second; kh.ChangeClass(klass); if (strcmp(descriptor, kh.GetDescriptor()) == 0) { classes.push_back(klass); } } for (It it = image_classes_.lower_bound(hash), end = classes_.end(); it != end && it->first == hash; ++it) { - Class* klass = it->second; + mirror::Class* klass = it->second; kh.ChangeClass(klass); if (strcmp(descriptor, kh.GetDescriptor()) == 0) { classes.push_back(klass); @@ -2156,7 +2187,7 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& cla } } -void ClassLinker::VerifyClass(Class* klass) { +void ClassLinker::VerifyClass(mirror::Class* klass) { // TODO: assert that the monitor on the Class is held Thread* self = Thread::Current(); ObjectLock lock(self, klass); @@ -2174,16 +2205,17 @@ void ClassLinker::VerifyClass(Class* klass) { return; } - if (klass->GetStatus() == Class::kStatusResolved) { - klass->SetStatus(Class::kStatusVerifying); + if (klass->GetStatus() == mirror::Class::kStatusResolved) { + klass->SetStatus(mirror::Class::kStatusVerifying); } else { - CHECK_EQ(klass->GetStatus(), Class::kStatusRetryVerificationAtRuntime) << PrettyClass(klass); + CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime) + << PrettyClass(klass); CHECK(!Runtime::Current()->IsCompiler()); - klass->SetStatus(Class::kStatusVerifyingAtRuntime); + klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime); } // Verify super class. - Class* super = klass->GetSuperClass(); + mirror::Class* super = klass->GetSuperClass(); std::string error_msg; if (super != NULL) { // Acquire lock to prevent races on verifying the super class. @@ -2198,7 +2230,7 @@ void ClassLinker::VerifyClass(Class* klass) { error_msg += " that attempts to sub-class erroneous class "; error_msg += PrettyDescriptor(super); LOG(ERROR) << error_msg << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8(); - SirtRef<Throwable> cause(self, self->GetException()); + SirtRef<mirror::Throwable> cause(self, self->GetException()); if (cause.get() != NULL) { self->ClearException(); } @@ -2206,24 +2238,24 @@ void ClassLinker::VerifyClass(Class* klass) { if (cause.get() != NULL) { self->GetException()->SetCause(cause.get()); } - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return; } } // Try to use verification information from the oat file, otherwise do runtime verification. const DexFile& dex_file = *klass->GetDexCache()->GetDexFile(); - Class::Status oat_file_class_status(Class::kStatusNotReady); + mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady); bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status); verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure; - if (oat_file_class_status == Class::kStatusError) { + if (oat_file_class_status == mirror::Class::kStatusError) { LOG(WARNING) << "Skipping runtime verification of erroneous class " << PrettyDescriptor(klass) << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8(); error_msg = "Rejecting class "; error_msg += PrettyDescriptor(klass); error_msg += " because it failed compile-time verification"; Thread::Current()->ThrowNewException("Ljava/lang/VerifyError;", error_msg.c_str()); - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return; } if (!preverified) { @@ -2239,16 +2271,16 @@ void ClassLinker::VerifyClass(Class* klass) { // Make sure all classes referenced by catch blocks are resolved. ResolveClassExceptionHandlerTypes(dex_file, klass); if (verifier_failure == verifier::MethodVerifier::kNoFailure) { - klass->SetStatus(Class::kStatusVerified); + klass->SetStatus(mirror::Class::kStatusVerified); } else { CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure); // Soft failures at compile time should be retried at runtime. Soft // failures at runtime will be handled by slow paths in the generated // code. Set status accordingly. if (Runtime::Current()->IsCompiler()) { - klass->SetStatus(Class::kStatusRetryVerificationAtRuntime); + klass->SetStatus(mirror::Class::kStatusRetryVerificationAtRuntime); } else { - klass->SetStatus(Class::kStatusVerified); + klass->SetStatus(mirror::Class::kStatusVerified); } } } else { @@ -2257,12 +2289,12 @@ void ClassLinker::VerifyClass(Class* klass) { << " because: " << error_msg; self->AssertNoPendingException(); self->ThrowNewException("Ljava/lang/VerifyError;", error_msg.c_str()); - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); } } -bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass, - Class::Status& oat_file_class_status) { +bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass, + mirror::Class::Status& oat_file_class_status) { if (!Runtime::Current()->IsStarted()) { return false; } @@ -2281,11 +2313,11 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass, CHECK(oat_class.get() != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor; oat_file_class_status = oat_class->GetStatus(); - if (oat_file_class_status == Class::kStatusVerified || - oat_file_class_status == Class::kStatusInitialized) { + if (oat_file_class_status == mirror::Class::kStatusVerified || + oat_file_class_status == mirror::Class::kStatusInitialized) { return true; } - if (oat_file_class_status == Class::kStatusRetryVerificationAtRuntime) { + if (oat_file_class_status == mirror::Class::kStatusRetryVerificationAtRuntime) { // Compile time verification failed with a soft error. Compile time verification can fail // because we have incomplete type information. Consider the following: // class ... { @@ -2305,12 +2337,12 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass, // at compile time). return false; } - if (oat_file_class_status == Class::kStatusError) { + if (oat_file_class_status == mirror::Class::kStatusError) { // Compile time verification failed with a hard error. This is caused by invalid instructions // in the class. These errors are unrecoverable. return false; } - if (oat_file_class_status == Class::kStatusNotReady) { + if (oat_file_class_status == mirror::Class::kStatusNotReady) { // Status is uninitialized if we couldn't determine the status at compile time, for example, // not loading the class. // TODO: when the verifier doesn't rely on Class-es failing to resolve/load the type hierarchy @@ -2323,7 +2355,7 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass, return false; } -void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, Class* klass) { +void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass) { for (size_t i = 0; i < klass->NumDirectMethods(); i++) { ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i)); } @@ -2332,7 +2364,8 @@ void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, Cla } } -void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, AbstractMethod* method) { +void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, + mirror::AbstractMethod* method) { // similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod. const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset()); if (code_item == NULL) { @@ -2350,7 +2383,7 @@ void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, Ab // Ensure exception types are resolved so that they don't need resolution to be delivered, // unresolved exception types will be ignored by exception delivery if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) { - Class* exception_type = linker->ResolveType(iterator.GetHandlerTypeIndex(), method); + mirror::Class* exception_type = linker->ResolveType(iterator.GetHandlerTypeIndex(), method); if (exception_type == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); Thread::Current()->ClearException(); @@ -2361,26 +2394,29 @@ void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, Ab } } -static void CheckProxyConstructor(AbstractMethod* constructor); -static void CheckProxyMethod(AbstractMethod* method, SirtRef<AbstractMethod>& prototype); +static void CheckProxyConstructor(mirror::AbstractMethod* constructor); +static void CheckProxyMethod(mirror::AbstractMethod* method, + SirtRef<mirror::AbstractMethod>& prototype); -Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces, - ClassLoader* loader, ObjectArray<AbstractMethod>* methods, - ObjectArray<ObjectArray<Class> >* throws) { +mirror::Class* ClassLinker::CreateProxyClass(mirror::String* name, + mirror::ObjectArray<mirror::Class>* interfaces, + mirror::ClassLoader* loader, + mirror::ObjectArray<mirror::AbstractMethod>* methods, + mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >* throws) { Thread* self = Thread::Current(); - SirtRef<Class> klass(self, AllocClass(self, GetClassRoot(kJavaLangClass), - sizeof(SynthesizedProxyClass))); + SirtRef<mirror::Class> klass(self, AllocClass(self, GetClassRoot(kJavaLangClass), + sizeof(mirror::SynthesizedProxyClass))); CHECK(klass.get() != NULL); DCHECK(klass->GetClass() != NULL); - klass->SetObjectSize(sizeof(Proxy)); + klass->SetObjectSize(sizeof(mirror::Proxy)); klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal); klass->SetClassLoader(loader); DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot); klass->SetName(name); - Class* proxy_class = GetClassRoot(kJavaLangReflectProxy); + mirror::Class* proxy_class = GetClassRoot(kJavaLangReflectProxy); klass->SetDexCache(proxy_class->GetDexCache()); - klass->SetStatus(Class::kStatusIdx); + klass->SetStatus(mirror::Class::kStatusIdx); klass->SetDexTypeIndex(DexFile::kDexNoIndex16); @@ -2388,13 +2424,13 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface klass->SetSFields(AllocFieldArray(self, 2)); // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by // our proxy, so Class.getInterfaces doesn't return the flattened set. - SirtRef<Field> interfaces_sfield(self, AllocField(self)); + SirtRef<mirror::Field> interfaces_sfield(self, AllocField(self)); klass->SetStaticField(0, interfaces_sfield.get()); interfaces_sfield->SetDexFieldIndex(0); interfaces_sfield->SetDeclaringClass(klass.get()); interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); // 2. Create a static field 'throws' that holds exceptions thrown by our methods. - SirtRef<Field> throws_sfield(self, AllocField(self)); + SirtRef<mirror::Field> throws_sfield(self, AllocField(self)); klass->SetStaticField(1, throws_sfield.get()); throws_sfield->SetDexFieldIndex(1); throws_sfield->SetDeclaringClass(klass.get()); @@ -2408,24 +2444,24 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface size_t num_virtual_methods = methods->GetLength(); klass->SetVirtualMethods(AllocMethodArray(self, num_virtual_methods)); for (size_t i = 0; i < num_virtual_methods; ++i) { - SirtRef<AbstractMethod> prototype(self, methods->Get(i)); + SirtRef<mirror::AbstractMethod> prototype(self, methods->Get(i)); klass->SetVirtualMethod(i, CreateProxyMethod(self, klass, prototype)); } klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy - klass->SetStatus(Class::kStatusLoaded); // Class is now effectively in the loaded state + klass->SetStatus(mirror::Class::kStatusLoaded); // Class is now effectively in the loaded state DCHECK(!Thread::Current()->IsExceptionPending()); // Link the fields and virtual methods, creating vtable and iftables if (!LinkClass(klass, interfaces)) { - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return NULL; } { ObjectLock lock(self, klass.get()); // Must hold lock on object when initializing. interfaces_sfield->SetObject(klass.get(), interfaces); throws_sfield->SetObject(klass.get(), throws); - klass->SetStatus(Class::kStatusInitialized); + klass->SetStatus(mirror::Class::kStatusInitialized); } // sanity checks @@ -2433,7 +2469,7 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface CHECK(klass->GetIFields() == NULL); CheckProxyConstructor(klass->GetDirectMethod(0)); for (size_t i = 0; i < num_virtual_methods; ++i) { - SirtRef<AbstractMethod> prototype(self, methods->Get(i)); + SirtRef<mirror::AbstractMethod> prototype(self, methods->Get(i)); CheckProxyMethod(klass->GetVirtualMethod(i), prototype); } @@ -2445,27 +2481,29 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface name->ToModifiedUtf8().c_str())); CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name); - SynthesizedProxyClass* synth_proxy_class = down_cast<SynthesizedProxyClass*>(klass.get()); + mirror::SynthesizedProxyClass* synth_proxy_class = + down_cast<mirror::SynthesizedProxyClass*>(klass.get()); CHECK_EQ(synth_proxy_class->GetInterfaces(), interfaces); CHECK_EQ(synth_proxy_class->GetThrows(), throws); } return klass.get(); } -std::string ClassLinker::GetDescriptorForProxy(const Class* proxy_class) { +std::string ClassLinker::GetDescriptorForProxy(const mirror::Class* proxy_class) { DCHECK(proxy_class->IsProxyClass()); - String* name = proxy_class->GetName(); + mirror::String* name = proxy_class->GetName(); DCHECK(name != NULL); return DotToDescriptor(name->ToModifiedUtf8().c_str()); } -AbstractMethod* ClassLinker::FindMethodForProxy(const Class* proxy_class, const AbstractMethod* proxy_method) { +mirror::AbstractMethod* ClassLinker::FindMethodForProxy(const mirror::Class* proxy_class, + const mirror::AbstractMethod* proxy_method) { DCHECK(proxy_class->IsProxyClass()); DCHECK(proxy_method->IsProxyMethod()); // Locate the dex cache of the original interface/Object - DexCache* dex_cache = NULL; + mirror::DexCache* dex_cache = NULL; { - ObjectArray<Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes(); + mirror::ObjectArray<mirror::Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes(); MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i != dex_caches_.size(); ++i) { if (dex_caches_[i]->GetResolvedTypes() == resolved_types) { @@ -2476,27 +2514,31 @@ AbstractMethod* ClassLinker::FindMethodForProxy(const Class* proxy_class, const } CHECK(dex_cache != NULL); uint32_t method_idx = proxy_method->GetDexMethodIndex(); - AbstractMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx); + mirror::AbstractMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx); CHECK(resolved_method != NULL); return resolved_method; } -AbstractMethod* ClassLinker::CreateProxyConstructor(Thread* self, SirtRef<Class>& klass, Class* proxy_class) { +mirror::AbstractMethod* ClassLinker::CreateProxyConstructor(Thread* self, + SirtRef<mirror::Class>& klass, + mirror::Class* proxy_class) { // Create constructor for Proxy that must initialize h - ObjectArray<AbstractMethod>* proxy_direct_methods = proxy_class->GetDirectMethods(); + mirror::ObjectArray<mirror::AbstractMethod>* proxy_direct_methods = + proxy_class->GetDirectMethods(); CHECK_EQ(proxy_direct_methods->GetLength(), 15); - AbstractMethod* proxy_constructor = proxy_direct_methods->Get(2); + mirror::AbstractMethod* proxy_constructor = proxy_direct_methods->Get(2); // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its // code_ too) - AbstractMethod* constructor = down_cast<AbstractMethod*>(proxy_constructor->Clone(self)); + mirror::AbstractMethod* constructor = + down_cast<mirror::AbstractMethod*>(proxy_constructor->Clone(self)); // Make this constructor public and fix the class to be our Proxy version constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic); constructor->SetDeclaringClass(klass.get()); return constructor; } -static void CheckProxyConstructor(AbstractMethod* constructor) +static void CheckProxyConstructor(mirror::AbstractMethod* constructor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(constructor->IsConstructor()); MethodHelper mh(constructor); @@ -2505,15 +2547,15 @@ static void CheckProxyConstructor(AbstractMethod* constructor) DCHECK(constructor->IsPublic()); } -AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<Class>& klass, - SirtRef<AbstractMethod>& prototype) { +mirror::AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass, + SirtRef<mirror::AbstractMethod>& prototype) { // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden // prototype method prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(), prototype.get()); // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize // as necessary - AbstractMethod* method = down_cast<AbstractMethod*>(prototype->Clone(self)); + mirror::AbstractMethod* method = down_cast<mirror::AbstractMethod*>(prototype->Clone(self)); // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to // the intersection of throw exceptions as defined in Proxy @@ -2522,7 +2564,8 @@ AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<Class>& kla // At runtime the method looks like a reference and argument saving method, clone the code // related parameters from this method. - AbstractMethod* refs_and_args = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs); + mirror::AbstractMethod* refs_and_args = + Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs); method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask()); method->SetFpSpillMask(refs_and_args->GetFpSpillMask()); method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes()); @@ -2536,7 +2579,8 @@ AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<Class>& kla return method; } -static void CheckProxyMethod(AbstractMethod* method, SirtRef<AbstractMethod>& prototype) +static void CheckProxyMethod(mirror::AbstractMethod* method, + SirtRef<mirror::AbstractMethod>& prototype) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Basic sanity CHECK(!prototype->IsFinal()); @@ -2560,18 +2604,18 @@ static void CheckProxyMethod(AbstractMethod* method, SirtRef<AbstractMethod>& pr CHECK_EQ(mh.GetReturnType(), mh2.GetReturnType()); } -bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_init_statics) { +bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_run_clinit, bool can_init_statics) { CHECK(klass->IsResolved() || klass->IsErroneous()) << PrettyClass(klass) << ": state=" << klass->GetStatus(); Thread* self = Thread::Current(); - AbstractMethod* clinit = NULL; + mirror::AbstractMethod* clinit = NULL; { // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol ObjectLock lock(self, klass); - if (klass->GetStatus() == Class::kStatusInitialized) { + if (klass->GetStatus() == mirror::Class::kStatusInitialized) { return true; } @@ -2580,11 +2624,11 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in return false; } - if (klass->GetStatus() == Class::kStatusResolved || - klass->GetStatus() == Class::kStatusRetryVerificationAtRuntime) { + if (klass->GetStatus() == mirror::Class::kStatusResolved || + klass->GetStatus() == mirror::Class::kStatusRetryVerificationAtRuntime) { VerifyClass(klass); - if (klass->GetStatus() != Class::kStatusVerified) { - if (klass->GetStatus() == Class::kStatusError) { + if (klass->GetStatus() != mirror::Class::kStatusVerified) { + if (klass->GetStatus() == mirror::Class::kStatusError) { CHECK(self->IsExceptionPending()); } return false; @@ -2606,7 +2650,7 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in // to initializing and we need to wait. Either way, this // invocation of InitializeClass will not be responsible for // running <clinit> and will return. - if (klass->GetStatus() == Class::kStatusInitializing) { + if (klass->GetStatus() == mirror::Class::kStatusInitializing) { // We caught somebody else in the act; was it us? if (klass->GetClinitThreadId() == self->GetTid()) { // Yes. That's fine. Return so we can continue initializing. @@ -2617,15 +2661,15 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in } if (!ValidateSuperClassDescriptors(klass)) { - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); lock.NotifyAll(); return false; } - DCHECK_EQ(klass->GetStatus(), Class::kStatusVerified) << PrettyClass(klass); + DCHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass); klass->SetClinitThreadId(self->GetTid()); - klass->SetStatus(Class::kStatusInitializing); + klass->SetStatus(mirror::Class::kStatusInitializing); } uint64_t t0 = NanoTime(); @@ -2665,7 +2709,7 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in if (self->IsExceptionPending()) { WrapExceptionInInitializer(); - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); success = false; } else { RuntimeStats* global_stats = Runtime::Current()->GetStats(); @@ -2677,10 +2721,10 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in // Set the class as initialized except if we can't initialize static fields and static field // initialization is necessary. if (!can_init_statics && has_static_field_initializers) { - klass->SetStatus(Class::kStatusVerified); // Don't leave class in initializing state. + klass->SetStatus(mirror::Class::kStatusVerified); // Don't leave class in initializing state. success = false; } else { - klass->SetStatus(Class::kStatusInitialized); + klass->SetStatus(mirror::Class::kStatusInitialized); } if (VLOG_IS_ON(class_linker)) { ClassHelper kh(klass); @@ -2692,7 +2736,7 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_in return success; } -bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& lock) +bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { while (true) { self->AssertNoPendingException(); @@ -2703,14 +2747,14 @@ bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& // "interruptShouldThrow" was set), bail out. if (self->IsExceptionPending()) { WrapExceptionInInitializer(); - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); return false; } // Spurious wakeup? Go back to waiting. - if (klass->GetStatus() == Class::kStatusInitializing) { + if (klass->GetStatus() == mirror::Class::kStatusInitializing) { continue; } - if (klass->GetStatus() == Class::kStatusVerified && Runtime::Current()->IsCompiler()) { + if (klass->GetStatus() == mirror::Class::kStatusVerified && Runtime::Current()->IsCompiler()) { // Compile time initialization failed. return false; } @@ -2729,16 +2773,16 @@ bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& LOG(FATAL) << "Not Reached" << PrettyClass(klass); } -bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { +bool ClassLinker::ValidateSuperClassDescriptors(const mirror::Class* klass) { if (klass->IsInterface()) { return true; } // begin with the methods local to the superclass if (klass->HasSuperClass() && klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) { - const Class* super = klass->GetSuperClass(); + const mirror::Class* super = klass->GetSuperClass(); for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) { - const AbstractMethod* method = klass->GetVTable()->Get(i); + const mirror::AbstractMethod* method = klass->GetVTable()->Get(i); if (method != super->GetVTable()->Get(i) && !IsSameMethodSignatureInDifferentClassContexts(method, super, klass)) { ThrowLinkageError("Class %s method %s resolves differently in superclass %s", @@ -2748,12 +2792,12 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { } } } - IfTable* iftable = klass->GetIfTable(); + mirror::IfTable* iftable = klass->GetIfTable(); for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { - Class* interface = iftable->GetInterface(i); + mirror::Class* interface = iftable->GetInterface(i); if (klass->GetClassLoader() != interface->GetClassLoader()) { for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { - const AbstractMethod* method = iftable->GetMethodArray(i)->Get(j); + const mirror::AbstractMethod* method = iftable->GetMethodArray(i)->Get(j); if (!IsSameMethodSignatureInDifferentClassContexts(method, interface, method->GetDeclaringClass())) { ThrowLinkageError("Class %s method %s resolves differently in interface %s", @@ -2770,9 +2814,9 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { // Returns true if classes referenced by the signature of the method are the // same classes in klass1 as they are in klass2. -bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const AbstractMethod* method, - const Class* klass1, - const Class* klass2) { +bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::AbstractMethod* method, + const mirror::Class* klass1, + const mirror::Class* klass2) { if (klass1 == klass2) { return true; } @@ -2803,29 +2847,29 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const AbstractMe // Returns true if the descriptor resolves to the same class in the context of klass1 and klass2. bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor, - const Class* klass1, - const Class* klass2) { + const mirror::Class* klass1, + const mirror::Class* klass2) { CHECK(descriptor != NULL); CHECK(klass1 != NULL); CHECK(klass2 != NULL); if (klass1 == klass2) { return true; } - Class* found1 = FindClass(descriptor, klass1->GetClassLoader()); + mirror::Class* found1 = FindClass(descriptor, klass1->GetClassLoader()); if (found1 == NULL) { Thread::Current()->ClearException(); } - Class* found2 = FindClass(descriptor, klass2->GetClassLoader()); + mirror::Class* found2 = FindClass(descriptor, klass2->GetClassLoader()); if (found2 == NULL) { Thread::Current()->ClearException(); } return found1 == found2; } -bool ClassLinker::InitializeSuperClass(Class* klass, bool can_run_clinit, bool can_init_fields) { +bool ClassLinker::InitializeSuperClass(mirror::Class* klass, bool can_run_clinit, bool can_init_fields) { CHECK(klass != NULL); if (!klass->IsInterface() && klass->HasSuperClass()) { - Class* super_class = klass->GetSuperClass(); + mirror::Class* super_class = klass->GetSuperClass(); if (!super_class->IsInitialized()) { CHECK(!super_class->IsInterface()); // Must hold lock on object when initializing and setting status. @@ -2835,11 +2879,11 @@ bool ClassLinker::InitializeSuperClass(Class* klass, bool can_run_clinit, bool c if (!super_initialized) { if (!can_run_clinit) { // Don't set status to error when we can't run <clinit>. - CHECK_EQ(klass->GetStatus(), Class::kStatusInitializing) << PrettyClass(klass); - klass->SetStatus(Class::kStatusVerified); + CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusInitializing) << PrettyClass(klass); + klass->SetStatus(mirror::Class::kStatusVerified); return false; } - klass->SetStatus(Class::kStatusError); + klass->SetStatus(mirror::Class::kStatusError); klass->NotifyAll(); return false; } @@ -2848,7 +2892,7 @@ bool ClassLinker::InitializeSuperClass(Class* klass, bool can_run_clinit, bool c return true; } -bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit, bool can_init_fields) { +bool ClassLinker::EnsureInitialized(mirror::Class* c, bool can_run_clinit, bool can_init_fields) { DCHECK(c != NULL); if (c->IsInitialized()) { return true; @@ -2864,8 +2908,8 @@ bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit, bool can_init } void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - Class* c, SafeMap<uint32_t, Field*>& field_map) { - ClassLoader* cl = c->GetClassLoader(); + mirror::Class* c, SafeMap<uint32_t, mirror::Field*>& field_map) { + mirror::ClassLoader* cl = c->GetClassLoader(); const byte* class_data = dex_file.GetClassData(dex_class_def); ClassDataItemIterator it(dex_file, class_data); for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) { @@ -2873,12 +2917,12 @@ void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::Clas } } -bool ClassLinker::InitializeStaticFields(Class* klass) { +bool ClassLinker::InitializeStaticFields(mirror::Class* klass) { size_t num_static_fields = klass->NumStaticFields(); if (num_static_fields == 0) { return false; } - DexCache* dex_cache = klass->GetDexCache(); + mirror::DexCache* dex_cache = klass->GetDexCache(); // TODO: this seems like the wrong check. do we really want !IsPrimitive && !IsArray? if (dex_cache == NULL) { return false; @@ -2892,7 +2936,7 @@ bool ClassLinker::InitializeStaticFields(Class* klass) { if (it.HasNext()) { // We reordered the fields, so we need to be able to map the field indexes to the right fields. - SafeMap<uint32_t, Field*> field_map; + SafeMap<uint32_t, mirror::Field*> field_map; ConstructFieldMap(dex_file, *dex_class_def, klass, field_map); for (size_t i = 0; it.HasNext(); i++, it.Next()) { it.ReadValueToField(field_map.Get(i)); @@ -2902,8 +2946,9 @@ bool ClassLinker::InitializeStaticFields(Class* klass) { return false; } -bool ClassLinker::LinkClass(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) { - CHECK_EQ(Class::kStatusLoaded, klass->GetStatus()); +bool ClassLinker::LinkClass(SirtRef<mirror::Class>& klass, + mirror::ObjectArray<mirror::Class>* interfaces) { + CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus()); if (!LinkSuperClass(klass)) { return false; } @@ -2918,19 +2963,19 @@ bool ClassLinker::LinkClass(SirtRef<Class>& klass, ObjectArray<Class>* interface } CreateReferenceInstanceOffsets(klass); CreateReferenceStaticOffsets(klass); - CHECK_EQ(Class::kStatusLoaded, klass->GetStatus()); - klass->SetStatus(Class::kStatusResolved); + CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus()); + klass->SetStatus(mirror::Class::kStatusResolved); return true; } -bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) { - CHECK_EQ(Class::kStatusIdx, klass->GetStatus()); +bool ClassLinker::LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file) { + CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus()); StringPiece descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex())); const DexFile::ClassDef* class_def = dex_file.FindClassDef(descriptor); CHECK(class_def != NULL); uint16_t super_class_idx = class_def->superclass_idx_; if (super_class_idx != DexFile::kDexNoIndex16) { - Class* super_class = ResolveType(dex_file, super_class_idx, klass.get()); + mirror::Class* super_class = ResolveType(dex_file, super_class_idx, klass.get()); if (super_class == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return false; @@ -2949,7 +2994,7 @@ bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& d if (interfaces != NULL) { for (size_t i = 0; i < interfaces->Size(); i++) { uint16_t idx = interfaces->GetTypeItem(i).type_idx_; - Class* interface = ResolveType(dex_file, idx, klass.get()); + mirror::Class* interface = ResolveType(dex_file, idx, klass.get()); if (interface == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return false; @@ -2966,13 +3011,13 @@ bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& d } } // Mark the class as loaded. - klass->SetStatus(Class::kStatusLoaded); + klass->SetStatus(mirror::Class::kStatusLoaded); return true; } -bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) { +bool ClassLinker::LinkSuperClass(SirtRef<mirror::Class>& klass) { CHECK(!klass->IsPrimitive()); - Class* super = klass->GetSuperClass(); + mirror::Class* super = klass->GetSuperClass(); if (klass.get() == GetClassRoot(kJavaLangObject)) { if (super != NULL) { Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassFormatError;", @@ -3031,7 +3076,8 @@ bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) { } // Populate the class vtable and itable. Compute return type indices. -bool ClassLinker::LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) { +bool ClassLinker::LinkMethods(SirtRef<mirror::Class>& klass, + mirror::ObjectArray<mirror::Class>* interfaces) { if (klass->IsInterface()) { // No vtable. size_t count = klass->NumVirtualMethods(); @@ -3051,24 +3097,24 @@ bool ClassLinker::LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfa return true; } -bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { +bool ClassLinker::LinkVirtualMethods(SirtRef<mirror::Class>& klass) { Thread* self = Thread::Current(); if (klass->HasSuperClass()) { uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength(); size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength(); CHECK_LE(actual_count, max_count); // TODO: do not assign to the vtable field until it is fully constructed. - SirtRef<ObjectArray<AbstractMethod> > + SirtRef<mirror::ObjectArray<mirror::AbstractMethod> > vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(self, max_count)); // See if any of our virtual methods override the superclass. MethodHelper local_mh(NULL, this); MethodHelper super_mh(NULL, this); for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) { - AbstractMethod* local_method = klass->GetVirtualMethodDuringLinking(i); + mirror::AbstractMethod* local_method = klass->GetVirtualMethodDuringLinking(i); local_mh.ChangeMethod(local_method); size_t j = 0; for (; j < actual_count; ++j) { - AbstractMethod* super_method = vtable->Get(j); + mirror::AbstractMethod* super_method = vtable->Get(j); super_mh.ChangeMethod(super_method); if (local_mh.HasSameNameAndSignature(&super_mh)) { if (klass->CanAccessMember(super_method->GetDeclaringClass(), super_method->GetAccessFlags())) { @@ -3112,10 +3158,10 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { ThrowClassFormatError("Too many methods: %d", num_virtual_methods); return false; } - SirtRef<ObjectArray<AbstractMethod> > + SirtRef<mirror::ObjectArray<mirror::AbstractMethod> > vtable(self, AllocMethodArray(self, num_virtual_methods)); for (size_t i = 0; i < num_virtual_methods; ++i) { - AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i); + mirror::AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i); vtable->Set(i, virtual_method); virtual_method->SetMethodIndex(i & 0xFFFF); } @@ -3124,7 +3170,8 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { return true; } -bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) { +bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass, + mirror::ObjectArray<mirror::Class>* interfaces) { size_t super_ifcount; if (klass->HasSuperClass()) { super_ifcount = klass->GetSuperClass()->GetIfTableCount(); @@ -3136,7 +3183,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> uint32_t num_interfaces = interfaces == NULL ? kh.NumDirectInterfaces() : interfaces->GetLength(); ifcount += num_interfaces; for (size_t i = 0; i < num_interfaces; i++) { - Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i); + mirror::Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i); ifcount += interface->GetIfTableCount(); } if (ifcount == 0) { @@ -3148,7 +3195,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> if (ifcount == super_ifcount) { // Class implements same interfaces as parent, are any of these not marker interfaces? bool has_non_marker_interface = false; - IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); + mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); for (size_t i = 0; i < ifcount; ++i) { if (super_iftable->GetMethodArrayCount(i) > 0) { has_non_marker_interface = true; @@ -3162,18 +3209,18 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } } Thread* self = Thread::Current(); - SirtRef<IfTable> iftable(self, AllocIfTable(self, ifcount)); + SirtRef<mirror::IfTable> iftable(self, AllocIfTable(self, ifcount)); if (super_ifcount != 0) { - IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); + mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); for (size_t i = 0; i < super_ifcount; i++) { - Class* super_interface = super_iftable->GetInterface(i); + mirror::Class* super_interface = super_iftable->GetInterface(i); iftable->SetInterface(i, super_interface); } } // Flatten the interface inheritance hierarchy. size_t idx = super_ifcount; for (size_t i = 0; i < num_interfaces; i++) { - Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i); + mirror::Class* interface = interfaces == NULL ? kh.GetDirectInterface(i) : interfaces->Get(i); DCHECK(interface != NULL); if (!interface->IsInterface()) { ClassHelper ih(interface); @@ -3186,7 +3233,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> // Check if interface is already in iftable bool duplicate = false; for (size_t j = 0; j < idx; j++) { - Class* existing_interface = iftable->GetInterface(j); + mirror::Class* existing_interface = iftable->GetInterface(j); if (existing_interface == interface) { duplicate = true; break; @@ -3197,10 +3244,10 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> iftable->SetInterface(idx++, interface); // Add this interface's non-duplicate super-interfaces. for (int32_t j = 0; j < interface->GetIfTableCount(); j++) { - Class* super_interface = interface->GetIfTable()->GetInterface(j); + mirror::Class* super_interface = interface->GetIfTable()->GetInterface(j); bool super_duplicate = false; for (size_t k = 0; k < idx; k++) { - Class* existing_interface = iftable->GetInterface(k); + mirror::Class* existing_interface = iftable->GetInterface(k); if (existing_interface == super_interface) { super_duplicate = true; break; @@ -3214,7 +3261,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } // Shrink iftable in case duplicates were found if (idx < ifcount) { - iftable.reset(down_cast<IfTable*>(iftable->CopyOf(self, idx * IfTable::kMax))); + iftable.reset(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax))); ifcount = idx; } else { CHECK_EQ(idx, ifcount); @@ -3225,18 +3272,19 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> if (klass->IsInterface()) { return true; } - std::vector<AbstractMethod*> miranda_list; + std::vector<mirror::AbstractMethod*> miranda_list; MethodHelper vtable_mh(NULL, this); MethodHelper interface_mh(NULL, this); for (size_t i = 0; i < ifcount; ++i) { - Class* interface = iftable->GetInterface(i); + mirror::Class* interface = iftable->GetInterface(i); size_t num_methods = interface->NumVirtualMethods(); if (num_methods > 0) { - ObjectArray<AbstractMethod>* method_array = AllocMethodArray(self, num_methods); + mirror::ObjectArray<mirror::AbstractMethod>* method_array = + AllocMethodArray(self, num_methods); iftable->SetMethodArray(i, method_array); - ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking(); + mirror::ObjectArray<mirror::AbstractMethod>* vtable = klass->GetVTableDuringLinking(); for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { - AbstractMethod* interface_method = interface->GetVirtualMethod(j); + mirror::AbstractMethod* interface_method = interface->GetVirtualMethod(j); interface_mh.ChangeMethod(interface_method); int32_t k; // For each method listed in the interface's method list, find the @@ -3248,7 +3296,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> // those don't end up in the virtual method table, so it shouldn't // matter which direction we go. We walk it backward anyway.) for (k = vtable->GetLength() - 1; k >= 0; --k) { - AbstractMethod* vtable_method = vtable->Get(k); + mirror::AbstractMethod* vtable_method = vtable->Get(k); vtable_mh.ChangeMethod(vtable_method); if (interface_mh.HasSameNameAndSignature(&vtable_mh)) { if (!vtable_method->IsPublic()) { @@ -3262,9 +3310,9 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } } if (k < 0) { - SirtRef<AbstractMethod> miranda_method(self, NULL); + SirtRef<mirror::AbstractMethod> miranda_method(self, NULL); for (size_t mir = 0; mir < miranda_list.size(); mir++) { - AbstractMethod* mir_method = miranda_list[mir]; + mirror::AbstractMethod* mir_method = miranda_list[mir]; vtable_mh.ChangeMethod(mir_method); if (interface_mh.HasSameNameAndSignature(&vtable_mh)) { miranda_method.reset(miranda_list[mir]); @@ -3273,7 +3321,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } if (miranda_method.get() == NULL) { // point the interface table at a phantom slot - miranda_method.reset(down_cast<AbstractMethod*>(interface_method->Clone(self))); + miranda_method.reset(down_cast<mirror::AbstractMethod*>(interface_method->Clone(self))); miranda_list.push_back(miranda_method.get()); } method_array->Set(j, miranda_method.get()); @@ -3288,13 +3336,14 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> ? AllocMethodArray(self, new_method_count) : klass->GetVirtualMethods()->CopyOf(self, new_method_count)); - SirtRef<ObjectArray<AbstractMethod> > vtable(self, klass->GetVTableDuringLinking()); + SirtRef<mirror::ObjectArray<mirror::AbstractMethod> > + vtable(self, klass->GetVTableDuringLinking()); CHECK(vtable.get() != NULL); int old_vtable_count = vtable->GetLength(); int new_vtable_count = old_vtable_count + miranda_list.size(); vtable.reset(vtable->CopyOf(self, new_vtable_count)); for (size_t i = 0; i < miranda_list.size(); ++i) { - AbstractMethod* method = miranda_list[i]; + mirror::AbstractMethod* method = miranda_list[i]; // Leave the declaring class alone as type indices are relative to it method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda); method->SetMethodIndex(0xFFFF & (old_vtable_count + i)); @@ -3305,7 +3354,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> klass->SetVTable(vtable.get()); } - ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking(); + mirror::ObjectArray<mirror::AbstractMethod>* vtable = klass->GetVTableDuringLinking(); for (int i = 0; i < vtable->GetLength(); ++i) { CHECK(vtable->Get(i) != NULL); } @@ -3315,12 +3364,12 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> return true; } -bool ClassLinker::LinkInstanceFields(SirtRef<Class>& klass) { +bool ClassLinker::LinkInstanceFields(SirtRef<mirror::Class>& klass) { CHECK(klass.get() != NULL); return LinkFields(klass, false); } -bool ClassLinker::LinkStaticFields(SirtRef<Class>& klass) { +bool ClassLinker::LinkStaticFields(SirtRef<mirror::Class>& klass) { CHECK(klass.get() != NULL); size_t allocated_class_size = klass->GetClassSize(); bool success = LinkFields(klass, true); @@ -3333,7 +3382,8 @@ struct LinkFieldsComparator { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : fh_(fh) {} // No thread safety analysis as will be called from STL. Checked lock held in constructor. - bool operator()(const Field* field1, const Field* field2) NO_THREAD_SAFETY_ANALYSIS { + bool operator()(const mirror::Field* field1, const mirror::Field* field2) + NO_THREAD_SAFETY_ANALYSIS { // First come reference fields, then 64-bit, and finally 32-bit fh_->ChangeField(field1); Primitive::Type type1 = fh_->GetTypeAsPrimitiveType(); @@ -3360,11 +3410,11 @@ struct LinkFieldsComparator { FieldHelper* fh_; }; -bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { +bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) { size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields(); - ObjectArray<Field>* fields = + mirror::ObjectArray<mirror::Field>* fields = is_static ? klass->GetSFields() : klass->GetIFields(); // Initialize size and field_offset @@ -3372,9 +3422,9 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { MemberOffset field_offset(0); if (is_static) { size = klass->GetClassSize(); - field_offset = Class::FieldsOffset(); + field_offset = mirror::Class::FieldsOffset(); } else { - Class* super_class = klass->GetSuperClass(); + mirror::Class* super_class = klass->GetSuperClass(); if (super_class != NULL) { CHECK(super_class->IsResolved()); field_offset = MemberOffset(super_class->GetObjectSize()); @@ -3386,7 +3436,7 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { // we want a relatively stable order so that adding new fields // minimizes disruption of C++ version such as Class and Method. - std::deque<Field*> grouped_and_sorted_fields; + std::deque<mirror::Field*> grouped_and_sorted_fields; for (size_t i = 0; i < num_fields; i++) { grouped_and_sorted_fields.push_back(fields->Get(i)); } @@ -3399,7 +3449,7 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { size_t current_field = 0; size_t num_reference_fields = 0; for (; current_field < num_fields; current_field++) { - Field* field = grouped_and_sorted_fields.front(); + mirror::Field* field = grouped_and_sorted_fields.front(); fh.ChangeField(field); Primitive::Type type = fh.GetTypeAsPrimitiveType(); bool isPrimitive = type != Primitive::kPrimNot; @@ -3418,7 +3468,7 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { // into place. If we can't find one, we'll have to pad it. if (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) { for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) { - Field* field = grouped_and_sorted_fields[i]; + mirror::Field* field = grouped_and_sorted_fields[i]; fh.ChangeField(field); Primitive::Type type = fh.GetTypeAsPrimitiveType(); CHECK(type != Primitive::kPrimNot); // should only be working on primitive types @@ -3439,7 +3489,7 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { // finish assigning field offsets to all fields. DCHECK(current_field == num_fields || IsAligned<8>(field_offset.Uint32Value())); while (!grouped_and_sorted_fields.empty()) { - Field* field = grouped_and_sorted_fields.front(); + mirror::Field* field = grouped_and_sorted_fields.front(); grouped_and_sorted_fields.pop_front(); fh.ChangeField(field); Primitive::Type type = fh.GetTypeAsPrimitiveType(); @@ -3469,12 +3519,13 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { // non-reference fields, and all double-wide fields are aligned. bool seen_non_ref = false; for (size_t i = 0; i < num_fields; i++) { - Field* field = fields->Get(i); + mirror::Field* field = fields->Get(i); if (false) { // enable to debug field layout LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance") << " class=" << PrettyClass(klass.get()) << " field=" << PrettyField(field) - << " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false); + << " offset=" << field->GetField32(MemberOffset(mirror::Field::OffsetOffset()), + false); } fh.ChangeField(field); Primitive::Type type = fh.GetTypeAsPrimitiveType(); @@ -3512,9 +3563,9 @@ bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) { // Set the bitmap of reference offsets, refOffsets, from the ifields // list. -void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<Class>& klass) { +void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass) { uint32_t reference_offsets = 0; - Class* super_class = klass->GetSuperClass(); + mirror::Class* super_class = klass->GetSuperClass(); if (super_class != NULL) { reference_offsets = super_class->GetReferenceInstanceOffsets(); // If our superclass overflowed, we don't stand a chance. @@ -3526,23 +3577,23 @@ void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<Class>& klass) { CreateReferenceOffsets(klass, false, reference_offsets); } -void ClassLinker::CreateReferenceStaticOffsets(SirtRef<Class>& klass) { +void ClassLinker::CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass) { CreateReferenceOffsets(klass, true, 0); } -void ClassLinker::CreateReferenceOffsets(SirtRef<Class>& klass, bool is_static, +void ClassLinker::CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static, uint32_t reference_offsets) { size_t num_reference_fields = is_static ? klass->NumReferenceStaticFieldsDuringLinking() : klass->NumReferenceInstanceFieldsDuringLinking(); - const ObjectArray<Field>* fields = + const mirror::ObjectArray<mirror::Field>* fields = is_static ? klass->GetSFields() : klass->GetIFields(); // All of the fields that contain object references are guaranteed // to be at the beginning of the fields list. for (size_t i = 0; i < num_reference_fields; ++i) { // Note that byte_offset is the offset from the beginning of // object, not the offset into instance data - const Field* field = fields->Get(i); + const mirror::Field* field = fields->Get(i); MemberOffset byte_offset = field->GetOffsetDuringLinking(); CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U); if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) { @@ -3562,27 +3613,27 @@ void ClassLinker::CreateReferenceOffsets(SirtRef<Class>& klass, bool is_static, } } -String* ClassLinker::ResolveString(const DexFile& dex_file, - uint32_t string_idx, DexCache* dex_cache) { +mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, + uint32_t string_idx, mirror::DexCache* dex_cache) { DCHECK(dex_cache != NULL); - String* resolved = dex_cache->GetResolvedString(string_idx); + mirror::String* resolved = dex_cache->GetResolvedString(string_idx); if (resolved != NULL) { return resolved; } const DexFile::StringId& string_id = dex_file.GetStringId(string_idx); int32_t utf16_length = dex_file.GetStringLength(string_id); const char* utf8_data = dex_file.GetStringData(string_id); - String* string = intern_table_->InternStrong(utf16_length, utf8_data); + mirror::String* string = intern_table_->InternStrong(utf16_length, utf8_data); dex_cache->SetResolvedString(string_idx, string); return string; } -Class* ClassLinker::ResolveType(const DexFile& dex_file, - uint16_t type_idx, - DexCache* dex_cache, - ClassLoader* class_loader) { +mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, + uint16_t type_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader) { DCHECK(dex_cache != NULL); - Class* resolved = dex_cache->GetResolvedType(type_idx); + mirror::Class* resolved = dex_cache->GetResolvedType(type_idx); if (resolved == NULL) { const char* descriptor = dex_file.StringByTypeIdx(type_idx); resolved = FindClass(descriptor, class_loader); @@ -3604,21 +3655,21 @@ Class* ClassLinker::ResolveType(const DexFile& dex_file, return resolved; } -AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, - uint32_t method_idx, - DexCache* dex_cache, - ClassLoader* class_loader, - const AbstractMethod* referrer, - InvokeType type) { +mirror::AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, + uint32_t method_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + const mirror::AbstractMethod* referrer, + InvokeType type) { DCHECK(dex_cache != NULL); // Check for hit in the dex cache. - AbstractMethod* resolved = dex_cache->GetResolvedMethod(method_idx); + mirror::AbstractMethod* resolved = dex_cache->GetResolvedMethod(method_idx); if (resolved != NULL) { return resolved; } // Fail, get the declaring class. const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); - Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); + mirror::Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); if (klass == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return NULL; @@ -3689,8 +3740,8 @@ AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, // If we found something, check that it can be accessed by the referrer. if (resolved != NULL && referrer != NULL) { - Class* methods_class = resolved->GetDeclaringClass(); - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* methods_class = resolved->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (!referring_class->CanAccess(methods_class)) { ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, referrer, resolved, type); @@ -3751,18 +3802,18 @@ AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, } } -Field* ClassLinker::ResolveField(const DexFile& dex_file, - uint32_t field_idx, - DexCache* dex_cache, - ClassLoader* class_loader, - bool is_static) { +mirror::Field* ClassLinker::ResolveField(const DexFile& dex_file, + uint32_t field_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + bool is_static) { DCHECK(dex_cache != NULL); - Field* resolved = dex_cache->GetResolvedField(field_idx); + mirror::Field* resolved = dex_cache->GetResolvedField(field_idx); if (resolved != NULL) { return resolved; } const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); + mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); if (klass == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return NULL; @@ -3791,17 +3842,17 @@ Field* ClassLinker::ResolveField(const DexFile& dex_file, return resolved; } -Field* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, - uint32_t field_idx, - DexCache* dex_cache, - ClassLoader* class_loader) { +mirror::Field* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, + uint32_t field_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader) { DCHECK(dex_cache != NULL); - Field* resolved = dex_cache->GetResolvedField(field_idx); + mirror::Field* resolved = dex_cache->GetResolvedField(field_idx); if (resolved != NULL) { return resolved; } const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); + mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); if (klass == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return NULL; @@ -3818,9 +3869,10 @@ Field* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, return resolved; } -const char* ClassLinker::MethodShorty(uint32_t method_idx, AbstractMethod* referrer, uint32_t* length) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); +const char* ClassLinker::MethodShorty(uint32_t method_idx, mirror::AbstractMethod* referrer, + uint32_t* length) { + mirror::Class* declaring_class = referrer->GetDeclaringClass(); + mirror::DexCache* dex_cache = declaring_class->GetDexCache(); const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); return dex_file.GetMethodShorty(method_id, length); @@ -3829,7 +3881,7 @@ const char* ClassLinker::MethodShorty(uint32_t method_idx, AbstractMethod* refer void ClassLinker::DumpAllClasses(int flags) const { // TODO: at the time this was written, it wasn't safe to call PrettyField with the ClassLinker // lock held, because it might need to resolve a field's type, which would try to take the lock. - std::vector<Class*> all_classes; + std::vector<mirror::Class*> all_classes; { MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto @@ -3865,7 +3917,7 @@ pid_t ClassLinker::GetDexLockOwner() { return dex_lock_.GetExclusiveOwnerTid(); } -void ClassLinker::SetClassRoot(ClassRoot class_root, Class* klass) { +void ClassLinker::SetClassRoot(ClassRoot class_root, mirror::Class* klass) { DCHECK(!init_done_); DCHECK(klass != NULL); diff --git a/src/class_linker.h b/src/class_linker.h index 09a43c533c..3039d55f7a 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -23,23 +23,26 @@ #include "base/macros.h" #include "base/mutex.h" -#include "dex_cache.h" #include "dex_file.h" #include "gtest/gtest.h" -#include "heap.h" +#include "root_visitor.h" #include "oat_file.h" -#include "object.h" -#include "safe_map.h" namespace art { - +namespace mirror { class ClassLoader; +class DexCache; +class DexCacheTest_Open_Test; +class IfTable; +template<class T> class ObjectArray; +class StackTraceElement; +} class ImageSpace; class InternTable; class ObjectLock; template<class T> class SirtRef; -typedef bool (ClassVisitor)(Class* c, void* arg); +typedef bool (ClassVisitor)(mirror::Class* c, void* arg); class ClassLinker { public: @@ -56,33 +59,33 @@ class ClassLinker { // Finds a class by its descriptor, loading it if necessary. // If class_loader is null, searches boot_class_path_. - Class* FindClass(const char* descriptor, ClassLoader* class_loader) + mirror::Class* FindClass(const char* descriptor, mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* FindSystemClass(const char* descriptor) + mirror::Class* FindSystemClass(const char* descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Define a new a class based on a ClassDef from a DexFile - Class* DefineClass(const StringPiece& descriptor, ClassLoader* class_loader, - const DexFile& dex_file, const DexFile::ClassDef& dex_class_def) + mirror::Class* DefineClass(const StringPiece& descriptor, mirror::ClassLoader* class_loader, + const DexFile& dex_file, const DexFile::ClassDef& dex_class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Finds a class by its descriptor, returning NULL if it isn't wasn't loaded // by the given 'class_loader'. - Class* LookupClass(const char* descriptor, const ClassLoader* class_loader) + mirror::Class* LookupClass(const char* descriptor, const mirror::ClassLoader* class_loader) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Finds all the classes with the given descriptor, regardless of ClassLoader. - void LookupClasses(const char* descriptor, std::vector<Class*>& classes) + void LookupClasses(const char* descriptor, std::vector<mirror::Class*>& classes) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* FindPrimitiveClass(char type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Class* FindPrimitiveClass(char type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // General class unloading is not supported, this is used to prune // unwanted classes during image writing. - bool RemoveClass(const char* descriptor, const ClassLoader* class_loader) + bool RemoveClass(const char* descriptor, const mirror::ClassLoader* class_loader) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -98,27 +101,20 @@ class ClassLinker { // Resolve a String with the given index from the DexFile, storing the // result in the DexCache. The referrer is used to identify the // target DexCache and ClassLoader to use for resolution. - String* ResolveString(uint32_t string_idx, const AbstractMethod* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx); - if (UNLIKELY(resolved_string == NULL)) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_string = ResolveString(dex_file, string_idx, dex_cache); - } - return resolved_string; - } + mirror::String* ResolveString(uint32_t string_idx, const mirror::AbstractMethod* referrer) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a String with the given index from the DexFile, storing the // result in the DexCache. - String* ResolveString(const DexFile& dex_file, uint32_t string_idx, DexCache* dex_cache) + mirror::String* ResolveString(const DexFile& dex_file, uint32_t string_idx, + mirror::DexCache* dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a Type with the given index from the DexFile, storing the // result in the DexCache. The referrer is used to identity the // target DexCache and ClassLoader to use for resolution. - Class* ResolveType(const DexFile& dex_file, uint16_t type_idx, const Class* referrer) + mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx, + const mirror::Class* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return ResolveType(dex_file, type_idx, @@ -129,40 +125,20 @@ class ClassLinker { // Resolve a Type with the given index from the DexFile, storing the // result in the DexCache. The referrer is used to identify the // target DexCache and ClassLoader to use for resolution. - Class* ResolveType(uint16_t type_idx, const AbstractMethod* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx); - if (UNLIKELY(resolved_type == NULL)) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); - ClassLoader* class_loader = declaring_class->GetClassLoader(); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); - } - return resolved_type; - } + mirror::Class* ResolveType(uint16_t type_idx, const mirror::AbstractMethod* referrer) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* ResolveType(uint16_t type_idx, const Field* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); - Class* resolved_type = dex_cache->GetResolvedType(type_idx); - if (UNLIKELY(resolved_type == NULL)) { - ClassLoader* class_loader = declaring_class->GetClassLoader(); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); - } - return resolved_type; - } + mirror::Class* ResolveType(uint16_t type_idx, const mirror::Field* referrer) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a type with the given ID from the DexFile, storing the // result in DexCache. The ClassLoader is used to search for the // type, since it may be referenced from but not contained within // the given DexFile. - Class* ResolveType(const DexFile& dex_file, - uint16_t type_idx, - DexCache* dex_cache, - ClassLoader* class_loader) + mirror::Class* ResolveType(const DexFile& dex_file, + uint16_t type_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a method with a given ID from the DexFile, storing the @@ -170,50 +146,31 @@ class ClassLinker { // in ResolveType. What is unique is the method type argument which // is used to determine if this method is a direct, static, or // virtual method. - AbstractMethod* ResolveMethod(const DexFile& dex_file, - uint32_t method_idx, - DexCache* dex_cache, - ClassLoader* class_loader, - const AbstractMethod* referrer, - InvokeType type) + mirror::AbstractMethod* ResolveMethod(const DexFile& dex_file, + uint32_t method_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + const mirror::AbstractMethod* referrer, + InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* ResolveMethod(uint32_t method_idx, const AbstractMethod* referrer, InvokeType type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* resolved_method = referrer->GetDexCacheResolvedMethods()->Get(method_idx); - if (UNLIKELY(resolved_method == NULL || resolved_method->IsRuntimeMethod())) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); - ClassLoader* class_loader = declaring_class->GetClassLoader(); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_method = ResolveMethod(dex_file, method_idx, dex_cache, class_loader, referrer, type); - } - return resolved_method; - } + mirror::AbstractMethod* ResolveMethod(uint32_t method_idx, const mirror::AbstractMethod* referrer, + InvokeType type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Field* ResolveField(uint32_t field_idx, const AbstractMethod* referrer, bool is_static) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* resolved_field = - referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); - if (UNLIKELY(resolved_field == NULL)) { - Class* declaring_class = referrer->GetDeclaringClass(); - DexCache* dex_cache = declaring_class->GetDexCache(); - ClassLoader* class_loader = declaring_class->GetClassLoader(); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static); - } - return resolved_field; - } + mirror::Field* ResolveField(uint32_t field_idx, const mirror::AbstractMethod* referrer, + bool is_static) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a field with a given ID from the DexFile, storing the // result in DexCache. The ClassLinker and ClassLoader are used as // in ResolveType. What is unique is the is_static argument which is // used to determine if we are resolving a static or non-static // field. - Field* ResolveField(const DexFile& dex_file, + mirror::Field* ResolveField(const DexFile& dex_file, uint32_t field_idx, - DexCache* dex_cache, - ClassLoader* class_loader, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -221,20 +178,20 @@ class ClassLinker { // result in DexCache. The ClassLinker and ClassLoader are used as // in ResolveType. No is_static argument is provided so that Java // field resolution semantics are followed. - Field* ResolveFieldJLS(const DexFile& dex_file, - uint32_t field_idx, - DexCache* dex_cache, - ClassLoader* class_loader) + mirror::Field* ResolveFieldJLS(const DexFile& dex_file, + uint32_t field_idx, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Get shorty from method index without resolution. Used to do handlerization. - const char* MethodShorty(uint32_t method_idx, AbstractMethod* referrer, uint32_t* length) + const char* MethodShorty(uint32_t method_idx, mirror::AbstractMethod* referrer, uint32_t* length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns true on success, false if there's an exception pending. // can_run_clinit=false allows the compiler to attempt to init a class, // given the restriction that no <clinit> execution is possible. - bool EnsureInitialized(Class* c, bool can_run_clinit, bool can_init_fields) + bool EnsureInitialized(mirror::Class* c, bool can_run_clinit, bool can_init_fields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Initializes classes that have instances in the image but that have @@ -244,7 +201,7 @@ class ClassLinker { void RegisterDexFile(const DexFile& dex_file) LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void RegisterDexFile(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) + void RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -262,15 +219,15 @@ class ClassLinker { void VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) const LOCKS_EXCLUDED(Locks::classlinker_classes_lock_); - void VisitRoots(Heap::RootVisitor* visitor, void* arg) + void VisitRoots(RootVisitor* visitor, void* arg) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_, dex_lock_); - DexCache* FindDexCache(const DexFile& dex_file) const + mirror::DexCache* FindDexCache(const DexFile& dex_file) const LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsDexFileRegistered(const DexFile& dex_file) const LOCKS_EXCLUDED(dex_lock_); - void FixupDexCaches(AbstractMethod* resolution_method) const + void FixupDexCaches(mirror::AbstractMethod* resolution_method) const LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -310,66 +267,54 @@ class ClassLinker { // TODO: replace this with multiple methods that allocate the correct managed type. template <class T> - ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length); - } + mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<Class>* AllocClassArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<Class>::Alloc(self, GetClassRoot(kClassArrayClass), length); - } + mirror::ObjectArray<mirror::Class>* AllocClassArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<String>* AllocStringArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<String>::Alloc(self, GetClassRoot(kJavaLangStringArrayClass), length); - } + mirror::ObjectArray<mirror::String>* AllocStringArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<AbstractMethod>* AllocAbstractMethodArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<AbstractMethod>::Alloc(self, - GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length); - } + mirror::ObjectArray<mirror::AbstractMethod>* AllocAbstractMethodArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<AbstractMethod>* AllocMethodArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<AbstractMethod>::Alloc(self, - GetClassRoot(kJavaLangReflectMethodArrayClass), length); - } + mirror::ObjectArray<mirror::AbstractMethod>* AllocMethodArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - IfTable* AllocIfTable(Thread* self, size_t ifcount) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return down_cast<IfTable*>( - IfTable::Alloc(self, GetClassRoot(kObjectArrayClass), ifcount * IfTable::kMax)); - } + mirror::IfTable* AllocIfTable(Thread* self, size_t ifcount) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<Field>* AllocFieldArray(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<Field>::Alloc(self, GetClassRoot(kJavaLangReflectFieldArrayClass), length); - } + mirror::ObjectArray<mirror::Field>* AllocFieldArray(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<StackTraceElement>* AllocStackTraceElementArray(Thread* self, size_t length) + mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self, + size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void VerifyClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass, - Class::Status& oat_file_class_status) + void VerifyClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass, + mirror::Class::Status& oat_file_class_status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, Class* klass) + void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, AbstractMethod* klass) + void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, mirror::AbstractMethod* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* CreateProxyClass(String* name, ObjectArray<Class>* interfaces, ClassLoader* loader, - ObjectArray<AbstractMethod>* methods, ObjectArray<ObjectArray<Class> >* throws) + mirror::Class* CreateProxyClass(mirror::String* name, mirror::ObjectArray<mirror::Class>* interfaces, + mirror::ClassLoader* loader, + mirror::ObjectArray<mirror::AbstractMethod>* methods, + mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >* throws) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - std::string GetDescriptorForProxy(const Class* proxy_class) + std::string GetDescriptorForProxy(const mirror::Class* proxy_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* FindMethodForProxy(const Class* proxy_class, const AbstractMethod* proxy_method) + mirror::AbstractMethod* FindMethodForProxy(const mirror::Class* proxy_class, + const mirror::AbstractMethod* proxy_method) LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Get the oat code for a method when its class isn't yet initialized - const void* GetOatCodeFor(const AbstractMethod* method) + const void* GetOatCodeFor(const mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Get the oat code for a method from a method index. @@ -389,7 +334,7 @@ class ClassLinker { private: explicit ClassLinker(InternTable*); - const OatFile::OatMethod GetOatMethodFor(const AbstractMethod* method) + const OatFile::OatMethod GetOatMethodFor(const mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Initialize class linker by bootstraping from dex files @@ -401,43 +346,41 @@ class ClassLinker { OatFile* OpenOat(const ImageSpace* space) LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void InitFromImageCallback(Object* obj, void* arg) + static void InitFromImageCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FinishInit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // For early bootstrapping by Init - Class* AllocClass(Thread* self, Class* java_lang_Class, size_t class_size) + mirror::Class* AllocClass(Thread* self, mirror::Class* java_lang_Class, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Alloc* convenience functions to avoid needing to pass in Class* + // Alloc* convenience functions to avoid needing to pass in mirror::Class* // values that are known to the ClassLinker such as // kObjectArrayClass and kJavaLangString etc. - Class* AllocClass(Thread* self, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - DexCache* AllocDexCache(Thread* self, const DexFile& dex_file) + mirror::Class* AllocClass(Thread* self, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Field* AllocField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Method* AllocMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Constructor* AllocConstructor(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Field* AllocField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Method* AllocMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Constructor* AllocConstructor(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* CreatePrimitiveClass(Thread* self, Primitive::Type type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return InitializePrimitiveClass(AllocClass(self, sizeof(Class)), type); - } - Class* InitializePrimitiveClass(Class* primitive_class, Primitive::Type type) + mirror::Class* CreatePrimitiveClass(Thread* self, Primitive::Type type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Class* InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* CreateArrayClass(const std::string& descriptor, ClassLoader* class_loader) + mirror::Class* CreateArrayClass(const std::string& descriptor, mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void AppendToBootClassPath(const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) + void AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - Class* c, SafeMap<uint32_t, Field*>& field_map) + mirror::Class* c, SafeMap<uint32_t, mirror::Field*>& field_map) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); size_t SizeOfClass(const DexFile& dex_file, @@ -445,18 +388,20 @@ class ClassLinker { void LoadClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - SirtRef<Class>& klass, - ClassLoader* class_loader) + SirtRef<mirror::Class>& klass, + mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass, - SirtRef<Field>& dst) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, + SirtRef<mirror::Class>& klass, SirtRef<mirror::Field>& dst) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* LoadMethod(Thread* self, const DexFile& dex_file, - const ClassDataItemIterator& dex_method, - SirtRef<Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::AbstractMethod* LoadMethod(Thread* self, const DexFile& dex_file, + const ClassDataItemIterator& dex_method, + SirtRef<mirror::Class>& klass) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupStaticTrampolines(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FixupStaticTrampolines(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Finds the associated oat class for a dex_file and descriptor const OatFile::OatClass* GetOatClass(const DexFile& dex_file, const char* descriptor); @@ -464,74 +409,75 @@ class ClassLinker { // Attempts to insert a class into a class table. Returns NULL if // the class was inserted, otherwise returns an existing class with // the same descriptor and ClassLoader. - Class* InsertClass(const StringPiece& descriptor, Class* klass, bool image_class) + mirror::Class* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool image_class) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) + void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) EXCLUSIVE_LOCKS_REQUIRED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsDexFileRegisteredLocked(const DexFile& dex_file) const EXCLUSIVE_LOCKS_REQUIRED(dex_lock_); void RegisterOatFileLocked(const OatFile& oat_file) EXCLUSIVE_LOCKS_REQUIRED(dex_lock_) EXCLUSIVE_LOCKS_REQUIRED(dex_lock_); - bool InitializeClass(Class* klass, bool can_run_clinit, bool can_init_statics) + bool InitializeClass(mirror::Class* klass, bool can_run_clinit, bool can_init_statics) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& lock); - bool ValidateSuperClassDescriptors(const Class* klass) + bool WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock); + bool ValidateSuperClassDescriptors(const mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool InitializeSuperClass(Class* klass, bool can_run_clinit, bool can_init_fields) + bool InitializeSuperClass(mirror::Class* klass, bool can_run_clinit, bool can_init_fields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Initialize static fields, returns true if fields were initialized. - bool InitializeStaticFields(Class* klass) + bool InitializeStaticFields(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsSameDescriptorInDifferentClassContexts(const char* descriptor, - const Class* klass1, - const Class* klass2) + const mirror::Class* klass1, + const mirror::Class* klass2) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsSameMethodSignatureInDifferentClassContexts(const AbstractMethod* descriptor, - const Class* klass1, - const Class* klass2) + bool IsSameMethodSignatureInDifferentClassContexts(const mirror::AbstractMethod* method, + const mirror::Class* klass1, + const mirror::Class* klass2) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkClass(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) + bool LinkClass(SirtRef<mirror::Class>& klass, mirror::ObjectArray<mirror::Class>* interfaces) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkSuperClass(SirtRef<Class>& klass) + bool LinkSuperClass(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) + bool LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) + bool LinkMethods(SirtRef<mirror::Class>& klass, mirror::ObjectArray<mirror::Class>* interfaces) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkVirtualMethods(SirtRef<Class>& klass) + bool LinkVirtualMethods(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) + bool LinkInterfaceMethods(SirtRef<mirror::Class>& klass, + mirror::ObjectArray<mirror::Class>* interfaces) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkStaticFields(SirtRef<Class>& klass) + bool LinkStaticFields(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkInstanceFields(SirtRef<Class>& klass) + bool LinkInstanceFields(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkFields(SirtRef<Class>& klass, bool is_static) + bool LinkFields(SirtRef<mirror::Class>& klass, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void CreateReferenceInstanceOffsets(SirtRef<Class>& klass) + void CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void CreateReferenceStaticOffsets(SirtRef<Class>& klass) + void CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void CreateReferenceOffsets(SirtRef<Class>& klass, bool is_static, + void CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static, uint32_t reference_offsets) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // For use by ImageWriter to find DexCaches for its roots - const std::vector<DexCache*>& GetDexCaches() { + const std::vector<mirror::DexCache*>& GetDexCaches() { return dex_caches_; } @@ -547,28 +493,29 @@ class ClassLinker { EXCLUSIVE_LOCKS_REQUIRED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateProxyConstructor(Thread* self, SirtRef<Class>& klass, Class* proxy_class) + mirror::AbstractMethod* CreateProxyConstructor(Thread* self, SirtRef<mirror::Class>& klass, + mirror::Class* proxy_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateProxyMethod(Thread* self, SirtRef<Class>& klass, - SirtRef<AbstractMethod>& prototype) + mirror::AbstractMethod* CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass, + SirtRef<mirror::AbstractMethod>& prototype) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::vector<const DexFile*> boot_class_path_; mutable Mutex dex_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - std::vector<DexCache*> dex_caches_ GUARDED_BY(dex_lock_); + std::vector<mirror::DexCache*> dex_caches_ GUARDED_BY(dex_lock_); std::vector<const OatFile*> oat_files_ GUARDED_BY(dex_lock_); // multimap from a string hash code of a class descriptor to - // Class* instances. Results should be compared for a matching + // mirror::Class* instances. Results should be compared for a matching // Class::descriptor_ and Class::class_loader_. - typedef std::multimap<size_t, Class*> Table; - Table image_classes_ GUARDED_BY(Locks::classlinker_classes_lock_); + typedef std::multimap<size_t, mirror::Class*> Table; + Table image_classes_ GUARDED_BY(Locks::classlinker_classes_lock_); Table classes_ GUARDED_BY(Locks::classlinker_classes_lock_); - Class* LookupClassLocked(const char* descriptor, const ClassLoader* class_loader, - size_t hash, const Table& classes) + mirror::Class* LookupClassLocked(const char* descriptor, const mirror::ClassLoader* class_loader, + size_t hash, const Table& classes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::classlinker_classes_lock_); @@ -615,20 +562,14 @@ class ClassLinker { kJavaLangStackTraceElementArrayClass, kClassRootsMax, }; - ObjectArray<Class>* class_roots_; + mirror::ObjectArray<mirror::Class>* class_roots_; - Class* GetClassRoot(ClassRoot class_root) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(class_roots_ != NULL); - Class* klass = class_roots_->Get(class_root); - DCHECK(klass != NULL); - return klass; - } + mirror::Class* GetClassRoot(ClassRoot class_root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetClassRoot(ClassRoot class_root, Class* klass) + void SetClassRoot(ClassRoot class_root, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<Class>* GetClassRoots() { + mirror::ObjectArray<mirror::Class>* GetClassRoots() { DCHECK(class_roots_ != NULL); return class_roots_; } @@ -641,7 +582,7 @@ class ClassLinker { return descriptor; } - IfTable* array_iftable_; + mirror::IfTable* array_iftable_; bool init_done_; bool is_dirty_; @@ -652,7 +593,7 @@ class ClassLinker { friend class ImageWriter; // for GetClassRoots friend class ObjectTest; FRIEND_TEST(ClassLinkerTest, ClassRootDescriptors); - FRIEND_TEST(DexCacheTest, Open); + FRIEND_TEST(mirror::DexCacheTest, Open); FRIEND_TEST(ExceptionTest, FindExceptionHandler); FRIEND_TEST(ObjectTest, AllocObjectArray); DISALLOW_COPY_AND_ASSIGN(ClassLinker); diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index d32e91e98a..893e7a4a6b 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -19,13 +19,24 @@ #include <string> #include "UniquePtr.h" +#include "class_linker-inl.h" #include "common_test.h" -#include "dex_cache.h" #include "dex_file.h" #include "heap.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/proxy.h" +#include "mirror/stack_trace_element.h" #include "runtime_support.h" #include "sirt_ref.h" +using namespace art::mirror; + namespace art { class ClassLinkerTest : public CommonTest { @@ -600,10 +611,10 @@ struct FieldClassOffsets : public CheckOffsets<FieldClass> { }; }; -struct MethodClassOffsets : public CheckOffsets<MethodClass> { - MethodClassOffsets() : CheckOffsets<MethodClass>(true, "Ljava/lang/reflect/Method;") { +struct MethodClassOffsets : public CheckOffsets<AbstractMethodClass> { + MethodClassOffsets() : CheckOffsets<AbstractMethodClass>(true, "Ljava/lang/reflect/Method;") { // alphabetical references - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(MethodClass, ORDER_BY_SIGNATURE_), "ORDER_BY_SIGNATURE")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethodClass, ORDER_BY_SIGNATURE_), "ORDER_BY_SIGNATURE")); }; }; diff --git a/src/common_test.h b/src/common_test.h index 5a5479a05d..46a8309c2a 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -26,12 +26,12 @@ #include "base/stringprintf.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" -#include "class_loader.h" #include "compiler.h" #include "dex_file.h" #include "gtest/gtest.h" #include "heap.h" #include "instruction_set.h" +#include "mirror/class_loader.h" #include "oat_file.h" #include "object_utils.h" #include "os.h" @@ -171,7 +171,7 @@ class ScratchFile { class CommonTest : public testing::Test { public: - static void MakeExecutable(const ByteArray* code_array) { + static void MakeExecutable(const mirror::ByteArray* code_array) { CHECK(code_array != NULL); MakeExecutable(code_array->GetData(), code_array->GetLength()); } @@ -189,7 +189,7 @@ class CommonTest : public testing::Test { const uint32_t* mapping_table, const uint16_t* vmap_table, const uint8_t* gc_map, - const AbstractMethod::InvokeStub* invoke_stub) { + const mirror::AbstractMethod::InvokeStub* invoke_stub) { return OatFile::OatMethod(NULL, reinterpret_cast<uint32_t>(code), frame_size_in_bytes, @@ -205,7 +205,7 @@ class CommonTest : public testing::Test { ); } - void MakeExecutable(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void MakeExecutable(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(method != NULL); MethodHelper mh(method); @@ -215,8 +215,8 @@ class CommonTest : public testing::Test { const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); MakeExecutable(invoke_stub); - const AbstractMethod::InvokeStub* method_invoke_stub = - reinterpret_cast<const AbstractMethod::InvokeStub*>( + const mirror::AbstractMethod::InvokeStub* method_invoke_stub = + reinterpret_cast<const mirror::AbstractMethod::InvokeStub*>( CompiledCode::CodePointer(&invoke_stub[0], compiled_invoke_stub->GetInstructionSet())); @@ -224,7 +224,7 @@ class CommonTest : public testing::Test { << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub); if (!method->IsAbstract()) { - const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); + const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); const DexFile& dex_file = *dex_cache->GetDexFile(); const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, @@ -473,14 +473,14 @@ class CommonTest : public testing::Test { ScopedLocalRef<jobject> class_loader_local(soa.Env(), soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader)); jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get()); - soa.Self()->SetClassLoaderOverride(soa.Decode<ClassLoader*>(class_loader_local.get())); + soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get())); Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path); return class_loader; } - void CompileClass(ClassLoader* class_loader, const char* class_name) { + void CompileClass(mirror::ClassLoader* class_loader, const char* class_name) { std::string class_descriptor(DotToDescriptor(class_name)); - Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); + mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); CHECK(klass != NULL) << "Class not found " << class_name; for (size_t i = 0; i < klass->NumDirectMethods(); i++) { CompileMethod(klass->GetDirectMethod(i)); @@ -490,7 +490,7 @@ class CommonTest : public testing::Test { } } - void CompileMethod(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void CompileMethod(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(method != NULL); compiler_->CompileOne(method); MakeExecutable(method); @@ -498,29 +498,29 @@ class CommonTest : public testing::Test { MakeExecutable(runtime_->GetJniDlsymLookupStub()); } - void CompileDirectMethod(ClassLoader* class_loader, + void CompileDirectMethod(mirror::ClassLoader* class_loader, const char* class_name, const char* method_name, const char* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); + mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); CHECK(klass != NULL) << "Class not found " << class_name; - AbstractMethod* method = klass->FindDirectMethod(method_name, signature); + mirror::AbstractMethod* method = klass->FindDirectMethod(method_name, signature); CHECK(method != NULL) << "Direct method not found: " << class_name << "." << method_name << signature; CompileMethod(method); } - void CompileVirtualMethod(ClassLoader* class_loader, + void CompileVirtualMethod(mirror::ClassLoader* class_loader, const char* class_name, const char* method_name, const char* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); + mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); CHECK(klass != NULL) << "Class not found " << class_name; - AbstractMethod* method = klass->FindVirtualMethod(method_name, signature); + mirror::AbstractMethod* method = klass->FindVirtualMethod(method_name, signature); CHECK(method != NULL) << "Virtual method not found: " << class_name << "." << method_name << signature; CompileMethod(method); diff --git a/src/common_throws.cc b/src/common_throws.cc index cefc4abdf9..734d544bd2 100644 --- a/src/common_throws.cc +++ b/src/common_throws.cc @@ -17,8 +17,12 @@ #include "common_throws.h" #include "base/logging.h" +#include "class_linker-inl.h" #include "dex_instruction.h" #include "invoke_type.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "thread.h" @@ -26,7 +30,7 @@ namespace art { -static void AddReferrerLocation(std::ostream& os, const AbstractMethod* referrer) +static void AddReferrerLocation(std::ostream& os, const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (referrer != NULL) { ClassHelper kh(referrer->GetDeclaringClass()); @@ -37,7 +41,7 @@ static void AddReferrerLocation(std::ostream& os, const AbstractMethod* referrer } } -static void AddReferrerLocationFromClass(std::ostream& os, Class* referrer) +static void AddReferrerLocationFromClass(std::ostream& os, mirror::Class* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (referrer != NULL) { ClassHelper kh(referrer); @@ -51,16 +55,16 @@ static void AddReferrerLocationFromClass(std::ostream& os, Class* referrer) // NullPointerException -void ThrowNullPointerExceptionForFieldAccess(Field* field, bool is_read) { +void ThrowNullPointerExceptionForFieldAccess(mirror::Field* field, bool is_read) { std::ostringstream msg; msg << "Attempt to " << (is_read ? "read from" : "write to") << " field '" << PrettyField(field, true) << "' on a null object reference"; Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str()); } -void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t method_idx, +void ThrowNullPointerExceptionForMethodAccess(mirror::AbstractMethod* caller, uint32_t method_idx, InvokeType type) { - DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); + mirror::DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); const DexFile& dex_file = *dex_cache->GetDexFile(); std::ostringstream msg; msg << "Attempt to invoke " << type << " method '" @@ -68,7 +72,7 @@ void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t m Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str()); } -void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t dex_pc) { +void ThrowNullPointerExceptionFromDexPC(mirror::AbstractMethod* throw_method, uint32_t dex_pc) { const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem(); CHECK_LT(dex_pc, code->insns_size_in_code_units_); const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); @@ -93,7 +97,7 @@ void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t d case Instruction::IGET_BYTE: case Instruction::IGET_CHAR: case Instruction::IGET_SHORT: { - Field* field = + mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false); ThrowNullPointerExceptionForFieldAccess(field, true /* read */); break; @@ -105,7 +109,7 @@ void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t d case Instruction::IPUT_BYTE: case Instruction::IPUT_CHAR: case Instruction::IPUT_SHORT: { - Field* field = + mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false); ThrowNullPointerExceptionForFieldAccess(field, false /* write */); break; @@ -149,7 +153,7 @@ void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t d // IllegalAccessError -void ThrowIllegalAccessErrorClass(Class* referrer, Class* accessed) { +void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) { std::ostringstream msg; msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '" << PrettyDescriptor(accessed) << "'"; @@ -157,9 +161,9 @@ void ThrowIllegalAccessErrorClass(Class* referrer, Class* accessed) { Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str()); } -void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed, - const AbstractMethod* caller, - const AbstractMethod* called, +void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed, + const mirror::AbstractMethod* caller, + const mirror::AbstractMethod* called, InvokeType type) { std::ostringstream msg; msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '" @@ -169,7 +173,7 @@ void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* acces Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str()); } -void ThrowIllegalAccessErrorMethod(Class* referrer, AbstractMethod* accessed) { +void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::AbstractMethod* accessed) { std::ostringstream msg; msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '" << PrettyDescriptor(referrer) << "'"; @@ -177,7 +181,7 @@ void ThrowIllegalAccessErrorMethod(Class* referrer, AbstractMethod* accessed) { Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str()); } -void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed) { +void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::Field* accessed) { std::ostringstream msg; msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '" << PrettyDescriptor(referrer) << "'"; @@ -185,7 +189,8 @@ void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed) { Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str()); } -void ThrowIllegalAccessErrorFinalField(const AbstractMethod* referrer, Field* accessed) { +void ThrowIllegalAccessErrorFinalField(const mirror::AbstractMethod* referrer, + mirror::Field* accessed) { std::ostringstream msg; msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '" << PrettyMethod(referrer) << "'"; @@ -196,7 +201,8 @@ void ThrowIllegalAccessErrorFinalField(const AbstractMethod* referrer, Field* ac // IncompatibleClassChangeError void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type, - AbstractMethod* method, const AbstractMethod* referrer) { + mirror::AbstractMethod* method, + const mirror::AbstractMethod* referrer) { std::ostringstream msg; msg << "The method '" << PrettyMethod(method) << "' was expected to be of type " << expected_type << " but instead was found to be of type " << found_type; @@ -205,9 +211,9 @@ void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType foun msg.str().c_str()); } -void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const AbstractMethod* interface_method, - Object* this_object, - const AbstractMethod* referrer) { +void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::AbstractMethod* interface_method, + mirror::Object* this_object, + const mirror::AbstractMethod* referrer) { // Referrer is calling interface_method on this_object, however, the interface_method isn't // implemented by this_object. CHECK(this_object != NULL); @@ -221,8 +227,8 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const AbstractMe msg.str().c_str()); } -void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static, - const AbstractMethod* referrer) { +void ThrowIncompatibleClassChangeErrorField(const mirror::Field* resolved_field, bool is_static, + const mirror::AbstractMethod* referrer) { std::ostringstream msg; msg << "Expected '" << PrettyField(resolved_field) << "' to be a " << (is_static ? "static" : "instance") << " field" << " rather than a " @@ -234,8 +240,8 @@ void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is // NoSuchMethodError -void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name, - const StringPiece& signature, const AbstractMethod* referrer) { +void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, + const StringPiece& signature, const mirror::AbstractMethod* referrer) { std::ostringstream msg; ClassHelper kh(c); msg << "No " << type << " method " << name << signature @@ -244,8 +250,8 @@ void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name, Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str()); } -void ThrowNoSuchMethodError(uint32_t method_idx, const AbstractMethod* referrer) { - DexCache* dex_cache = referrer->GetDeclaringClass()->GetDexCache(); +void ThrowNoSuchMethodError(uint32_t method_idx, const mirror::AbstractMethod* referrer) { + mirror::DexCache* dex_cache = referrer->GetDeclaringClass()->GetDexCache(); const DexFile& dex_file = *dex_cache->GetDexFile(); std::ostringstream msg; msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'"; diff --git a/src/common_throws.h b/src/common_throws.h index 33769c49b8..9e28bd72e3 100644 --- a/src/common_throws.h +++ b/src/common_throws.h @@ -18,62 +18,73 @@ #define ART_SRC_COMMON_THROWS_H_ #include "base/mutex.h" -#include "object.h" +#include "invoke_type.h" namespace art { +namespace mirror { +class AbstractMethod; +class Class; +class Field; +class Object; +} // namespace mirror +class StringPiece; // NullPointerException -void ThrowNullPointerExceptionForFieldAccess(Field* field, bool is_read) +void ThrowNullPointerExceptionForFieldAccess(mirror::Field* field, bool is_read) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t method_idx, InvokeType type) +void ThrowNullPointerExceptionForMethodAccess(mirror::AbstractMethod* caller, uint32_t method_idx, + InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t dex_pc) +void ThrowNullPointerExceptionFromDexPC(mirror::AbstractMethod* throw_method, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // IllegalAccessError -void ThrowIllegalAccessErrorClass(Class* referrer, Class* accessed) +void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed, - const AbstractMethod* caller, const AbstractMethod* called, +void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed, + const mirror::AbstractMethod* caller, + const mirror::AbstractMethod* called, InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIllegalAccessErrorMethod(Class* referrer, AbstractMethod* accessed) +void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::AbstractMethod* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed) +void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::Field* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIllegalAccessErrorFinalField(const AbstractMethod* referrer, Field* accessed) +void ThrowIllegalAccessErrorFinalField(const mirror::AbstractMethod* referrer, + mirror::Field* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // IncompatibleClassChangeError void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type, - AbstractMethod* method, const AbstractMethod* referrer) + mirror::AbstractMethod* method, + const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const AbstractMethod* interface_method, - Object* this_object, - const AbstractMethod* referrer) +void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::AbstractMethod* interface_method, + mirror::Object* this_object, + const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static, - const AbstractMethod* referrer) +void ThrowIncompatibleClassChangeErrorField(const mirror::Field* resolved_field, bool is_static, + const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // NoSuchMethodError -void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name, - const StringPiece& signature, const AbstractMethod* referrer) +void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, + const StringPiece& signature, const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void ThrowNoSuchMethodError(uint32_t method_idx, const AbstractMethod* referrer) +void ThrowNoSuchMethodError(uint32_t method_idx, const mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } // namespace art diff --git a/src/compiled_class.h b/src/compiled_class.h index 97dd8ee8d1..f050ee6a7e 100644 --- a/src/compiled_class.h +++ b/src/compiled_class.h @@ -17,19 +17,19 @@ #ifndef ART_SRC_COMPILED_CLASS_H_ #define ART_SRC_COMPILED_CLASS_H_ -#include "object.h" +#include "mirror/class.h" namespace art { class CompiledClass { public: - explicit CompiledClass(Class::Status status) : status_(status) {} + explicit CompiledClass(mirror::Class::Status status) : status_(status) {} ~CompiledClass() {} - Class::Status GetStatus() const { + mirror::Class::Status GetStatus() const { return status_; } private: - const Class::Status status_; + const mirror::Class::Status status_; }; } // namespace art diff --git a/src/compiler.cc b/src/compiler.cc index 18460ceda2..903b70a4ad 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -23,15 +23,22 @@ #include "base/stl_util.h" #include "class_linker.h" -#include "class_loader.h" -#include "dex_cache.h" #include "jni_internal.h" #include "oat_compilation_unit.h" #include "oat_file.h" #include "oat/runtime/stub.h" #include "object_utils.h" #include "runtime.h" +#include "gc/card_table-inl.h" #include "gc/space.h" +#include "mirror/class_loader.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/throwable.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" #include "thread.h" @@ -431,7 +438,7 @@ CompilerTls* Compiler::GetTls() { return res; } -ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set, +mirror::ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set, Runtime::TrampolineType type) { switch (instruction_set) { case kArm: @@ -447,7 +454,7 @@ ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set, } } -ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) { +mirror::ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) { switch (instruction_set) { case kArm: case kThumb2: @@ -462,7 +469,7 @@ ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) { } } -ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) { +mirror::ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) { switch (instruction_set) { case kArm: case kThumb2: @@ -497,7 +504,7 @@ void Compiler::CompileAll(jobject class_loader, } } -void Compiler::CompileOne(const AbstractMethod* method) { +void Compiler::CompileOne(const mirror::AbstractMethod* method) { DCHECK(!Runtime::Current()->IsStarted()); Thread* self = Thread::Current(); jobject class_loader; @@ -566,12 +573,12 @@ void Compiler::RecordClassStatus(ClassReference ref, CompiledClass* compiled_cla bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) { ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); if (!IsImage()) { stats_->TypeNotInDexCache(); return false; } - Class* resolved_class = dex_cache->GetResolvedType(type_idx); + mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == NULL) { stats_->TypeNotInDexCache(); return false; @@ -593,7 +600,7 @@ bool Compiler::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, if (IsImage()) { // We resolve all const-string strings when building for the image. ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); Runtime::Current()->GetClassLinker()->ResolveString(dex_file, string_idx, dex_cache); result = true; } @@ -608,15 +615,15 @@ bool Compiler::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, bool Compiler::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexFile& dex_file, uint32_t type_idx) { ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); // Get type from dex cache assuming it was populated by the verifier - Class* resolved_class = dex_cache->GetResolvedType(type_idx); + mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == NULL) { stats_->TypeNeedsAccessCheck(); return false; // Unknown class needs access checks. } const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx); - Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); + mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); if (referrer_class == NULL) { stats_->TypeNeedsAccessCheck(); return false; // Incomplete referrer knowledge needs access check. @@ -636,15 +643,15 @@ bool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx, const DexFile& dex_file, uint32_t type_idx) { ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); // Get type from dex cache assuming it was populated by the verifier. - Class* resolved_class = dex_cache->GetResolvedType(type_idx); + mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == NULL) { stats_->TypeNeedsAccessCheck(); return false; // Unknown class needs access checks. } const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx); - Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); + mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); if (referrer_class == NULL) { stats_->TypeNeedsAccessCheck(); return false; // Incomplete referrer knowledge needs access check. @@ -660,33 +667,33 @@ bool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx, return result; } -static Class* ComputeCompilingMethodsClass(ScopedObjectAccess& soa, - OatCompilationUnit* mUnit) +static mirror::Class* ComputeCompilingMethodsClass(ScopedObjectAccess& soa, + OatCompilationUnit* mUnit) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(mUnit->class_loader_); + mirror::DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->class_loader_); const DexFile::MethodId& referrer_method_id = mUnit->dex_file_->GetMethodId(mUnit->method_idx_); return mUnit->class_linker_->ResolveType(*mUnit->dex_file_, referrer_method_id.class_idx_, dex_cache, class_loader); } -static Field* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAccess& soa, - OatCompilationUnit* mUnit, - uint32_t field_idx) +static mirror::Field* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAccess& soa, + OatCompilationUnit* mUnit, + uint32_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(mUnit->class_loader_); + mirror::DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->class_loader_); return mUnit->class_linker_->ResolveField(*mUnit->dex_file_, field_idx, dex_cache, class_loader, false); } -static AbstractMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa, - OatCompilationUnit* mUnit, - uint32_t method_idx, - InvokeType type) +static mirror::AbstractMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa, + OatCompilationUnit* mUnit, + uint32_t method_idx, + InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(mUnit->class_loader_); + mirror::DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->class_loader_); return mUnit->class_linker_->ResolveMethod(*mUnit->dex_file_, method_idx, dex_cache, class_loader, NULL, type); } @@ -698,11 +705,11 @@ bool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* field_offset = -1; is_volatile = true; // Try to resolve field and ignore if an Incompatible Class Change Error (ie is static). - Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); + mirror::Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); if (resolved_field != NULL && !resolved_field->IsStatic()) { - Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); + mirror::Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); if (referrer_class != NULL) { - Class* fields_class = resolved_field->GetDeclaringClass(); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); bool access_ok = referrer_class->CanAccess(fields_class) && referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()); @@ -711,7 +718,7 @@ bool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* // protected field being made public by a sub-class. Resort to the dex file to determine // the correct class for the access check. const DexFile& dex_file = *referrer_class->GetDexCache()->GetDexFile(); - Class* dex_fields_class = mUnit->class_linker_->ResolveType(dex_file, + mirror::Class* dex_fields_class = mUnit->class_linker_->ResolveType(dex_file, dex_file.GetFieldId(field_idx).class_idx_, referrer_class); access_ok = referrer_class->CanAccess(dex_fields_class) && @@ -746,11 +753,11 @@ bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mU is_referrers_class = false; is_volatile = true; // Try to resolve field and ignore if an Incompatible Class Change Error (ie isn't static). - Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); + mirror::Field* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); if (resolved_field != NULL && resolved_field->IsStatic()) { - Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); + mirror::Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); if (referrer_class != NULL) { - Class* fields_class = resolved_field->GetDeclaringClass(); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); if (fields_class == referrer_class) { is_referrers_class = true; // implies no worrying about class initialization field_offset = resolved_field->GetOffset().Int32Value(); @@ -767,7 +774,7 @@ bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mU // the correct class for the access check. Don't change the field's class as that is // used to identify the SSB. const DexFile& dex_file = *referrer_class->GetDexCache()->GetDexFile(); - Class* dex_fields_class = + mirror::Class* dex_fields_class = mUnit->class_linker_->ResolveType(dex_file, dex_file.GetFieldId(field_idx).class_idx_, referrer_class); @@ -781,7 +788,7 @@ bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mU // in its static storage base (which may fail if it doesn't have a slot for it) // TODO: for images we can elide the static storage base null check // if we know there's a non-null entry in the image - DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); + mirror::DexCache* dex_cache = mUnit->class_linker_->FindDexCache(*mUnit->dex_file_); if (fields_class->GetDexCache() == dex_cache) { // common case where the dex cache of both the referrer and the field are the same, // no need to search the dex file @@ -820,7 +827,8 @@ bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mU return false; // Incomplete knowledge needs slow path. } -void Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, AbstractMethod* method, +void Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, + mirror::AbstractMethod* method, uintptr_t& direct_code, uintptr_t& direct_method) { // For direct and static methods compute possible direct_code and direct_method values, ie // an address for the Method* being invoked and an address of the code for that Method*. @@ -876,15 +884,15 @@ bool Compiler::ComputeInvokeInfo(uint32_t method_idx, OatCompilationUnit* mUnit, vtable_idx = -1; direct_code = 0; direct_method = 0; - AbstractMethod* resolved_method = + mirror::AbstractMethod* resolved_method = ComputeMethodReferencedFromCompilingMethod(soa, mUnit, method_idx, type); if (resolved_method != NULL) { // Don't try to fast-path if we don't understand the caller's class or this appears to be an // Incompatible Class Change Error. - Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); + mirror::Class* referrer_class = ComputeCompilingMethodsClass(soa, mUnit); bool icce = resolved_method->CheckIncompatibleClassChange(type); if (referrer_class != NULL && !icce) { - Class* methods_class = resolved_method->GetDeclaringClass(); + mirror::Class* methods_class = resolved_method->GetDeclaringClass(); if (!referrer_class->CanAccess(methods_class) || !referrer_class->CanAccessMember(methods_class, resolved_method->GetAccessFlags())) { @@ -1068,7 +1076,7 @@ class CompilationContext { // classes found in the boot classpath. Since at runtime we will // select the class from the boot classpath, do not attempt to resolve // or compile it now. -static bool SkipClass(ClassLoader* class_loader, +static bool SkipClass(mirror::ClassLoader* class_loader, const DexFile& dex_file, const DexFile::ClassDef& class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -1077,7 +1085,7 @@ static bool SkipClass(ClassLoader* class_loader, } const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* klass = class_linker->FindClass(descriptor, NULL); + mirror::Class* klass = class_linker->FindClass(descriptor, NULL); if (klass == NULL) { Thread* self = Thread::Current(); CHECK(self->IsExceptionPending()); @@ -1090,7 +1098,7 @@ static bool SkipClass(ClassLoader* class_loader, static void ResolveClassFieldsAndMethods(const CompilationContext* context, size_t class_def_index) LOCKS_EXCLUDED(Locks::mutator_lock_) { ScopedObjectAccess soa(Thread::Current()); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(context->GetClassLoader()); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(context->GetClassLoader()); const DexFile& dex_file = *context->GetDexFile(); // Method and Field are the worst. We can't resolve without either @@ -1115,11 +1123,11 @@ static void ResolveClassFieldsAndMethods(const CompilationContext* context, size } Thread* self = Thread::Current(); ClassLinker* class_linker = context->GetClassLinker(); - DexCache* dex_cache = class_linker->FindDexCache(dex_file); + mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file); ClassDataItemIterator it(dex_file, class_data); while (it.HasNextStaticField()) { - Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, - class_loader, true); + mirror::Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, + class_loader, true); if (field == NULL) { CHECK(self->IsExceptionPending()); self->ClearException(); @@ -1134,8 +1142,8 @@ static void ResolveClassFieldsAndMethods(const CompilationContext* context, size requires_constructor_barrier = true; } - Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, - class_loader, false); + mirror::Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, + class_loader, false); if (field == NULL) { CHECK(self->IsExceptionPending()); self->ClearException(); @@ -1147,9 +1155,9 @@ static void ResolveClassFieldsAndMethods(const CompilationContext* context, size class_def_index); } while (it.HasNextDirectMethod()) { - AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache, - class_loader, NULL, - it.GetMethodInvokeType(class_def)); + mirror::AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), + dex_cache, class_loader, NULL, + it.GetMethodInvokeType(class_def)); if (method == NULL) { CHECK(self->IsExceptionPending()); self->ClearException(); @@ -1157,9 +1165,9 @@ static void ResolveClassFieldsAndMethods(const CompilationContext* context, size it.Next(); } while (it.HasNextVirtualMethod()) { - AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache, - class_loader, NULL, - it.GetMethodInvokeType(class_def)); + mirror::AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), + dex_cache, class_loader, NULL, + it.GetMethodInvokeType(class_def)); if (method == NULL) { CHECK(self->IsExceptionPending()); self->ClearException(); @@ -1175,9 +1183,9 @@ static void ResolveType(const CompilationContext* context, size_t type_idx) ScopedObjectAccess soa(Thread::Current()); ClassLinker* class_linker = context->GetClassLinker(); const DexFile& dex_file = *context->GetDexFile(); - DexCache* dex_cache = class_linker->FindDexCache(dex_file); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(context->GetClassLoader()); - Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader); + mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(context->GetClassLoader()); + mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader); if (klass == NULL) { CHECK(soa.Self()->IsExceptionPending()); @@ -1214,9 +1222,9 @@ static void VerifyClass(const CompilationContext* context, size_t class_def_inde ScopedObjectAccess soa(Thread::Current()); const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index); const char* descriptor = context->GetDexFile()->GetClassDescriptor(class_def); - Class* klass = + mirror::Class* klass = context->GetClassLinker()->FindClass(descriptor, - soa.Decode<ClassLoader*>(context->GetClassLoader())); + soa.Decode<mirror::ClassLoader*>(context->GetClassLoader())); if (klass == NULL) { Thread* self = Thread::Current(); CHECK(self->IsExceptionPending()); @@ -1227,11 +1235,11 @@ static void VerifyClass(const CompilationContext* context, size_t class_def_inde * This is to ensure the class is structurally sound for compilation. An unsound class * will be rejected by the verifier and later skipped during compilation in the compiler. */ - DexCache* dex_cache = context->GetClassLinker()->FindDexCache(*context->GetDexFile()); + mirror::DexCache* dex_cache = context->GetClassLinker()->FindDexCache(*context->GetDexFile()); std::string error_msg; if (verifier::MethodVerifier::VerifyClass(context->GetDexFile(), dex_cache, - soa.Decode<ClassLoader*>(context->GetClassLoader()), + soa.Decode<mirror::ClassLoader*>(context->GetClassLoader()), class_def_index, error_msg) == verifier::MethodVerifier::kHardFailure) { const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index); @@ -1446,9 +1454,9 @@ static void InitializeClass(const CompilationContext* context, size_t class_def_ LOCKS_EXCLUDED(Locks::mutator_lock_) { const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index); ScopedObjectAccess soa(Thread::Current()); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(context->GetClassLoader()); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(context->GetClassLoader()); const char* descriptor = context->GetDexFile()->GetClassDescriptor(class_def); - Class* klass = context->GetClassLinker()->FindClass(descriptor, class_loader); + mirror::Class* klass = context->GetClassLinker()->FindClass(descriptor, class_loader); Thread* self = Thread::Current(); bool compiling_boot = Runtime::Current()->GetHeap()->GetSpaces().size() == 1; bool can_init_static_fields = compiling_boot && @@ -1480,10 +1488,10 @@ static void InitializeClass(const CompilationContext* context, size_t class_def_ LOG(INFO) << "Initializing: " << descriptor; if (StringPiece(descriptor) == "Ljava/lang/Void;"){ // Hand initialize j.l.Void to avoid Dex file operations in un-started runtime. - ObjectArray<Field>* fields = klass->GetSFields(); + mirror::ObjectArray<mirror::Field>* fields = klass->GetSFields(); CHECK_EQ(fields->GetLength(), 1); fields->Get(0)->SetObj(klass, context->GetClassLinker()->FindPrimitiveClass('V')); - klass->SetStatus(Class::kStatusInitialized); + klass->SetStatus(mirror::Class::kStatusInitialized); } else { context->GetClassLinker()->EnsureInitialized(klass, true, can_init_static_fields); } @@ -1497,7 +1505,7 @@ static void InitializeClass(const CompilationContext* context, size_t class_def_ } } // Record the final class status if necessary. - Class::Status status = klass->GetStatus(); + mirror::Class::Status status = klass->GetStatus(); Compiler::ClassReference ref(context->GetDexFile(), class_def_index); CompiledClass* compiled_class = context->GetCompiler()->GetCompiledClass(ref); if (compiled_class == NULL) { @@ -1550,7 +1558,7 @@ void Compiler::CompileClass(const CompilationContext* context, size_t class_def_ const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); { ScopedObjectAccess soa(Thread::Current()); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(context->GetClassLoader()); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(context->GetClassLoader()); if (SkipClass(class_loader, dex_file, class_def)) { return; } diff --git a/src/compiler.h b/src/compiler.h index 13130d7bd6..0f99f4d2e0 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -24,12 +24,10 @@ #include "base/mutex.h" #include "compiled_class.h" #include "compiled_method.h" -#include "dex_cache.h" #include "dex_file.h" #include "instruction_set.h" #include "invoke_type.h" #include "oat_file.h" -#include "object.h" #include "runtime.h" #include "safe_map.h" #include "thread_pool.h" @@ -79,7 +77,7 @@ class Compiler { LOCKS_EXCLUDED(Locks::mutator_lock_); // Compile a single Method - void CompileOne(const AbstractMethod* method) + void CompileOne(const mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsDebuggingSupported() { @@ -101,16 +99,16 @@ class Compiler { CompilerTls* GetTls(); // Stub to throw AbstractMethodError - static ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set) + static mirror::ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Generate the trampoline that's invoked by unresolved direct methods - static ByteArray* CreateResolutionStub(InstructionSet instruction_set, - Runtime::TrampolineType type) + static mirror::ByteArray* CreateResolutionStub(InstructionSet instruction_set, + Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static ByteArray* CreateJniDlsymLookupStub(InstructionSet instruction_set) + static mirror::ByteArray* CreateJniDlsymLookupStub(InstructionSet instruction_set) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // A class is uniquely located by its DexFile and the class_defs_ table index into that DexFile @@ -273,7 +271,8 @@ class Compiler { private: // Compute constant code and method pointers when possible - void GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, AbstractMethod* method, + void GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, + mirror::AbstractMethod* method, uintptr_t& direct_code, uintptr_t& direct_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -397,11 +396,11 @@ class Compiler { CompilerEnableAutoElfLoadingFn compiler_enable_auto_elf_loading_; typedef const void* (*CompilerGetMethodCodeAddrFn) - (const Compiler& compiler, const CompiledMethod* cm, const AbstractMethod* method); + (const Compiler& compiler, const CompiledMethod* cm, const mirror::AbstractMethod* method); CompilerGetMethodCodeAddrFn compiler_get_method_code_addr_; - typedef const AbstractMethod::InvokeStub* (*CompilerGetMethodInvokeStubAddrFn) - (const Compiler& compiler, const CompiledInvokeStub* cm, const AbstractMethod* method); + typedef const mirror::AbstractMethod::InvokeStub* (*CompilerGetMethodInvokeStubAddrFn) + (const Compiler& compiler, const CompiledInvokeStub* cm, const mirror::AbstractMethod* method); CompilerGetMethodInvokeStubAddrFn compiler_get_method_invoke_stub_addr_; diff --git a/src/compiler/codegen/arm/call_arm.cc b/src/compiler/codegen/arm/call_arm.cc index cb3af5eb22..47306f402c 100644 --- a/src/compiler/codegen/arm/call_arm.cc +++ b/src/compiler/codegen/arm/call_arm.cc @@ -489,7 +489,7 @@ void ArmCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation GenNullCheck(cu, rl_src.s_reg_low, r0, opt_flags); LoadWordDisp(cu, rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); NewLIR3(cu, kThumb2Ldrex, r1, r0, - Object::MonitorOffset().Int32Value() >> 2); // Get object->lock + mirror::Object::MonitorOffset().Int32Value() >> 2); // Get object->lock // Align owner OpRegImm(cu, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); // Is lock unheld on lock or held by us (==thread_id) on unlock? @@ -498,7 +498,7 @@ void ArmCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation OpRegImm(cu, kOpCmp, r1, 0); OpIT(cu, kCondEq, ""); NewLIR4(cu, kThumb2Strex, r1, r2, r0, - Object::MonitorOffset().Int32Value() >> 2); + mirror::Object::MonitorOffset().Int32Value() >> 2); OpRegImm(cu, kOpCmp, r1, 0); OpIT(cu, kCondNe, "T"); // Go expensive route - artLockObjectFromCode(self, obj); @@ -522,7 +522,7 @@ void ArmCodegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation LoadValueDirectFixed(cu, rl_src, r0); // Get obj LockCallTemps(cu); // Prepare for explicit register usage GenNullCheck(cu, rl_src.s_reg_low, r0, opt_flags); - LoadWordDisp(cu, r0, Object::MonitorOffset().Int32Value(), r1); // Get lock + LoadWordDisp(cu, r0, mirror::Object::MonitorOffset().Int32Value(), r1); // Get lock LoadWordDisp(cu, rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); // Is lock unheld on lock or held by us (==thread_id) on unlock? OpRegRegImm(cu, kOpAnd, r3, r1, @@ -532,7 +532,7 @@ void ArmCodegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation NewLIR3(cu, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); OpRegReg(cu, kOpSub, r1, r2); OpIT(cu, kCondEq, "EE"); - StoreWordDisp(cu, r0, Object::MonitorOffset().Int32Value(), r3); + StoreWordDisp(cu, r0, mirror::Object::MonitorOffset().Int32Value(), r3); // Go expensive route - UnlockObjectFromCode(obj); LoadWordDisp(cu, rARM_SELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR); ClobberCalleeSave(cu); diff --git a/src/compiler/codegen/arm/int_arm.cc b/src/compiler/codegen/arm/int_arm.cc index e86f379694..6a1178e340 100644 --- a/src/compiler/codegen/arm/int_arm.cc +++ b/src/compiler/codegen/arm/int_arm.cc @@ -565,16 +565,16 @@ void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; RegLocation rl_result; rl_array = LoadValue(cu, rl_array, kCoreReg); rl_index = LoadValue(cu, rl_index, kCoreReg); if (rl_dest.wide) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } /* null object? */ @@ -637,13 +637,13 @@ void ArmCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; if (size == kLong || size == kDouble) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } rl_array = LoadValue(cu, rl_array, kCoreReg); @@ -706,8 +706,8 @@ void ArmCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re void ArmCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { - int len_offset = Array::LengthOffset().Int32Value(); - int data_offset = Array::DataOffset(sizeof(Object*)).Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); + int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); FlushAllRegs(cu); // Use explicit registers LockCallTemps(cu); @@ -727,7 +727,7 @@ void ArmCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, Object::ClassOffset().Int32Value(), r_array_class); + LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. diff --git a/src/compiler/codegen/gen_common.cc b/src/compiler/codegen/gen_common.cc index e1054db201..acaad5b26b 100644 --- a/src/compiler/codegen/gen_common.cc +++ b/src/compiler/codegen/gen_common.cc @@ -330,7 +330,7 @@ void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) SRegOffset(cu, rl_first.s_reg_low)); // Set up the target pointer OpRegRegImm(cu, kOpAdd, r_dst, TargetReg(kRet0), - Array::DataOffset(component_size).Int32Value()); + mirror::Array::DataOffset(component_size).Int32Value()); // Set up the loop counter (known to be > 0) LoadConstant(cu, r_idx, elems - 1); // Generate the copy loop. Going backwards for convenience @@ -342,14 +342,15 @@ void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) OpDecAndBranch(cu, kCondGe, r_idx, target); if (cu->instruction_set == kX86) { // Restore the target pointer - OpRegRegImm(cu, kOpAdd, TargetReg(kRet0), r_dst, -Array::DataOffset(component_size).Int32Value()); + OpRegRegImm(cu, kOpAdd, TargetReg(kRet0), r_dst, + -mirror::Array::DataOffset(component_size).Int32Value()); } } else if (!info->is_range) { // TUNING: interleave for (int i = 0; i < elems; i++) { RegLocation rl_arg = LoadValue(cu, info->args[i], kCoreReg); StoreBaseDisp(cu, TargetReg(kRet0), - Array::DataOffset(component_size).Int32Value() + + mirror::Array::DataOffset(component_size).Int32Value() + i * 4, rl_arg.low_reg, kWord); // If the LoadValue caused a temp to be allocated, free it if (IsTemp(cu, rl_arg.low_reg)) { @@ -386,7 +387,7 @@ void Codegen::GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_sr RegLocation rl_method = LoadCurrMethod(cu); rBase = AllocTemp(cu); LoadWordDisp(cu, rl_method.low_reg, - AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); + mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); if (IsTemp(cu, rl_method.low_reg)) { FreeTemp(cu, rl_method.low_reg); } @@ -404,10 +405,10 @@ void Codegen::GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_sr rBase = TargetReg(kArg0); LockTemp(cu, rBase); LoadWordDisp(cu, r_method, - AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), + mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), rBase); LoadWordDisp(cu, rBase, - Array::DataOffset(sizeof(Object*)).Int32Value() + + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + sizeof(int32_t*) * ssb_index, rBase); // rBase now points at appropriate static storage base (Class*) // or NULL if not initialized. Check for NULL and call helper if NULL. @@ -480,7 +481,7 @@ void Codegen::GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_de RegLocation rl_method = LoadCurrMethod(cu); rBase = AllocTemp(cu); LoadWordDisp(cu, rl_method.low_reg, - AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); + mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); } else { // Medium path, static storage base in a different class which // requires checks that the other class is initialized @@ -495,10 +496,10 @@ void Codegen::GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_de rBase = TargetReg(kArg0); LockTemp(cu, rBase); LoadWordDisp(cu, r_method, - AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), + mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), rBase); LoadWordDisp(cu, rBase, - Array::DataOffset(sizeof(Object*)).Int32Value() + + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + sizeof(int32_t*) * ssb_index, rBase); // rBase now points at appropriate static storage base (Class*) // or NULL if not initialized. Check for NULL and call helper if NULL. @@ -619,7 +620,7 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) OpRegCopy(cu, TargetReg(kArg0), v1); if (target_x86) { // x86 leaves the array pointer in v2, so load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, Array::LengthOffset().Int32Value()); + OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { OpRegCopy(cu, TargetReg(kArg1), v2); } @@ -629,7 +630,7 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) OpRegCopy(cu, TargetReg(kArg2), v1); if (target_x86) { // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, Array::LengthOffset().Int32Value()); + OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { OpRegCopy(cu, TargetReg(kArg1), v2); } @@ -637,7 +638,7 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) } else { if (target_x86) { // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, Array::LengthOffset().Int32Value()); + OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { OpRegCopy(cu, TargetReg(kArg1), v2); } @@ -799,10 +800,10 @@ void Codegen::GenConstClass(CompilationUnit* cu, uint32_t type_idx, RegLocation } else { // We're don't need access checks, load type from dex cache int32_t dex_cache_offset = - AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(); + mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(); LoadWordDisp(cu, rl_method.low_reg, dex_cache_offset, res_reg); int32_t offset_of_type = - Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*) + mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*) * type_idx); LoadWordDisp(cu, res_reg, offset_of_type, rl_result.low_reg); if (!cu->compiler->CanAssumeTypeIsPresentInDexCache(*cu->dex_file, @@ -844,8 +845,8 @@ void Codegen::GenConstClass(CompilationUnit* cu, uint32_t type_idx, RegLocation void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocation rl_dest) { /* NOTE: Most strings should be available at compile time */ - int32_t offset_of_string = Array::DataOffset(sizeof(String*)).Int32Value() + - (sizeof(String*) * string_idx); + int32_t offset_of_string = mirror::Array::DataOffset(sizeof(mirror::String*)).Int32Value() + + (sizeof(mirror::String*) * string_idx); if (!cu->compiler->CanAssumeStringIsPresentInDexCache( *cu->dex_file, string_idx) || SLOW_STRING_PATH) { // slow path, resolve string if not in dex cache @@ -853,7 +854,7 @@ void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocati LockCallTemps(cu); // Using explicit registers LoadCurrMethodDirect(cu, TargetReg(kArg2)); LoadWordDisp(cu, TargetReg(kArg2), - AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0)); + mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0)); // Might call out to helper, which will return resolved string in kRet0 int r_tgt = CallHelperSetup(cu, ENTRYPOINT_OFFSET(pResolveStringFromCode)); LoadWordDisp(cu, TargetReg(kArg0), offset_of_string, TargetReg(kRet0)); @@ -888,7 +889,7 @@ void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocati int res_reg = AllocTemp(cu); RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); LoadWordDisp(cu, rl_method.low_reg, - AbstractMethod::DexCacheStringsOffset().Int32Value(), res_reg); + mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), res_reg); LoadWordDisp(cu, res_reg, offset_of_string, rl_result.low_reg); StoreValue(cu, rl_dest, rl_result); } @@ -942,9 +943,9 @@ void Codegen::GenInstanceof(CompilationUnit* cu, uint32_t type_idx, RegLocation // Load dex cache entry into class_reg (kArg2) LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); // kArg0 <= ref LoadWordDisp(cu, TargetReg(kArg1), - AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); + mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); int32_t offset_of_type = - Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*) + mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*) * type_idx); LoadWordDisp(cu, class_reg, offset_of_type, class_reg); if (!cu->compiler->CanAssumeTypeIsPresentInDexCache( @@ -968,8 +969,8 @@ void Codegen::GenInstanceof(CompilationUnit* cu, uint32_t type_idx, RegLocation } LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL); /* load object->klass_ */ - DCHECK_EQ(Object::ClassOffset().Int32Value(), 0); - LoadWordDisp(cu, TargetReg(kArg0), Object::ClassOffset().Int32Value(), TargetReg(kArg1)); + DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0); + LoadWordDisp(cu, TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */ LIR* call_inst; LIR* branchover = NULL; @@ -1026,10 +1027,10 @@ void Codegen::GenCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation r } else { // Load dex cache entry into class_reg (kArg2) LoadWordDisp(cu, TargetReg(kArg1), - AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); + mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); int32_t offset_of_type = - Array::DataOffset(sizeof(Class*)).Int32Value() + - (sizeof(Class*) * type_idx); + mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + + (sizeof(mirror::Class*) * type_idx); LoadWordDisp(cu, class_reg, offset_of_type, class_reg); if (!cu->compiler->CanAssumeTypeIsPresentInDexCache( *cu->dex_file, type_idx)) { @@ -1051,8 +1052,8 @@ void Codegen::GenCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation r /* Null is OK - continue */ LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL); /* load object->klass_ */ - DCHECK_EQ(Object::ClassOffset().Int32Value(), 0); - LoadWordDisp(cu, TargetReg(kArg0), Object::ClassOffset().Int32Value(), TargetReg(kArg1)); + DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0); + LoadWordDisp(cu, TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); /* kArg1 now contains object->klass_ */ LIR* branch2; if (cu->instruction_set == kThumb2) { diff --git a/src/compiler/codegen/gen_invoke.cc b/src/compiler/codegen/gen_invoke.cc index fe60affdca..78425c40bd 100644 --- a/src/compiler/codegen/gen_invoke.cc +++ b/src/compiler/codegen/gen_invoke.cc @@ -365,7 +365,7 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, break; case 1: // Get method->dex_cache_resolved_methods_ cg->LoadWordDisp(cu, cg->TargetReg(kArg0), - AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0)); + mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0)); // Set up direct code if known. if (direct_code != 0) { if (direct_code != static_cast<unsigned int>(-1)) { @@ -384,13 +384,14 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, break; case 2: // Grab target method* cg->LoadWordDisp(cu, cg->TargetReg(kArg0), - Array::DataOffset(sizeof(Object*)).Int32Value() + dex_idx * 4, + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4, cg-> TargetReg(kArg0)); break; case 3: // Grab the code from the method* if (cu->instruction_set != kX86) { if (direct_code == 0) { - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), AbstractMethod::GetCodeOffset().Int32Value(), + cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + mirror::AbstractMethod::GetCodeOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); } break; @@ -428,20 +429,22 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info, case 1: // Is "this" null? [use kArg1] cg->GenNullCheck(cu, info->args[0].s_reg_low, cg->TargetReg(kArg1), info->opt_flags); // get this->klass_ [use kArg1, set kInvokeTgt] - cg->LoadWordDisp(cu, cg->TargetReg(kArg1), Object::ClassOffset().Int32Value(), + cg->LoadWordDisp(cu, cg->TargetReg(kArg1), mirror::Object::ClassOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; case 2: // Get this->klass_->vtable [usr kInvokeTgt, set kInvokeTgt] - cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), Class::VTableOffset().Int32Value(), + cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), mirror::Class::VTableOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; case 3: // Get target method [use kInvokeTgt, set kArg0] cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), (method_idx * 4) + - Array::DataOffset(sizeof(Object*)).Int32Value(), cg->TargetReg(kArg0)); + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(), + cg->TargetReg(kArg0)); break; case 4: // Get the compiled code address [uses kArg0, sets kInvokeTgt] if (cu->instruction_set != kX86) { - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), AbstractMethod::GetCodeOffset().Int32Value(), + cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + mirror::AbstractMethod::GetCodeOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; } @@ -503,12 +506,12 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state, break; case 1: // Get method->dex_cache_resolved_methods_ [set/use kArg0] cg->LoadWordDisp(cu, cg->TargetReg(kArg0), - AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), + mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0)); break; case 2: // Grab target method* [set/use kArg0] cg->LoadWordDisp(cu, cg->TargetReg(kArg0), - Array::DataOffset(sizeof(Object*)).Int32Value() + dex_idx * 4, + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4, cg->TargetReg(kArg0)); break; default: @@ -837,13 +840,13 @@ bool Codegen::GenInlinedCharAt(CompilationUnit* cu, CallInfo* info) return false; } // Location of reference to data array - int value_offset = String::ValueOffset().Int32Value(); + int value_offset = mirror::String::ValueOffset().Int32Value(); // Location of count - int count_offset = String::CountOffset().Int32Value(); + int count_offset = mirror::String::CountOffset().Int32Value(); // Starting offset within data array - int offset_offset = String::OffsetOffset().Int32Value(); + int offset_offset = mirror::String::OffsetOffset().Int32Value(); // Start of char data with array_ - int data_offset = Array::DataOffset(sizeof(uint16_t)).Int32Value(); + int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); RegLocation rl_obj = info->args[0]; RegLocation rl_idx = info->args[1]; @@ -921,7 +924,7 @@ bool Codegen::GenInlinedStringIsEmptyOrLength(CompilationUnit* cu, CallInfo* inf RegLocation rl_dest = InlineTarget(cu, info); RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags); - LoadWordDisp(cu, rl_obj.low_reg, String::CountOffset().Int32Value(), + LoadWordDisp(cu, rl_obj.low_reg, mirror::String::CountOffset().Int32Value(), rl_result.low_reg); if (is_empty) { // dst = (dst == 0); @@ -1284,7 +1287,7 @@ void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info) } else { if (fast_path && info->type != kInterface) { call_inst = OpMem(cu, kOpBlx, TargetReg(kArg0), - AbstractMethod::GetCodeOffset().Int32Value()); + mirror::AbstractMethod::GetCodeOffset().Int32Value()); } else { int trampoline = 0; switch (info->type) { diff --git a/src/compiler/codegen/mips/int_mips.cc b/src/compiler/codegen/mips/int_mips.cc index e2a5a02ccb..86f0527bf1 100644 --- a/src/compiler/codegen/mips/int_mips.cc +++ b/src/compiler/codegen/mips/int_mips.cc @@ -439,16 +439,16 @@ void MipsCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, R RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; RegLocation rl_result; rl_array = LoadValue(cu, rl_array, kCoreReg); rl_index = LoadValue(cu, rl_index, kCoreReg); if (size == kLong || size == kDouble) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } /* null object? */ @@ -511,13 +511,13 @@ void MipsCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, R RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; if (size == kLong || size == kDouble) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } rl_array = LoadValue(cu, rl_array, kCoreReg); @@ -583,8 +583,8 @@ void MipsCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, R void MipsCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { - int len_offset = Array::LengthOffset().Int32Value(); - int data_offset = Array::DataOffset(sizeof(Object*)).Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); + int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); FlushAllRegs(cu); // Use explicit registers LockCallTemps(cu); @@ -604,7 +604,7 @@ void MipsCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, Object::ClassOffset().Int32Value(), r_array_class); + LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc index e38977ad10..2657b791ac 100644 --- a/src/compiler/codegen/mir_to_gbc.cc +++ b/src/compiler/codegen/mir_to_gbc.cc @@ -2684,7 +2684,7 @@ static void CvtArrayLength(CompilationUnit* cu, llvm::CallInst* call_inst) cg->GenNullCheck(cu, rl_src.s_reg_low, rl_src.low_reg, opt_flags->getZExtValue()); RegLocation rl_dest = GetLoc(cu, call_inst); RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); cg->LoadWordDisp(cu, rl_src.low_reg, len_offset, rl_result.low_reg); cg->StoreValue(cu, rl_dest, rl_result); } diff --git a/src/compiler/codegen/mir_to_lir.cc b/src/compiler/codegen/mir_to_lir.cc index 2bc0f8642b..77d581fd6e 100644 --- a/src/compiler/codegen/mir_to_lir.cc +++ b/src/compiler/codegen/mir_to_lir.cc @@ -210,7 +210,7 @@ static bool CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::ARRAY_LENGTH: int len_offset; - len_offset = Array::LengthOffset().Int32Value(); + len_offset = mirror::Array::LengthOffset().Int32Value(); rl_src[0] = cg->LoadValue(cu, rl_src[0], kCoreReg); cg->GenNullCheck(cu, rl_src[0].s_reg_low, rl_src[0].low_reg, opt_flags); rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); diff --git a/src/compiler/codegen/x86/call_x86.cc b/src/compiler/codegen/x86/call_x86.cc index 727c5e861a..f9b25c844c 100644 --- a/src/compiler/codegen/x86/call_x86.cc +++ b/src/compiler/codegen/x86/call_x86.cc @@ -163,7 +163,7 @@ void X86Codegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation NewLIR2(cu, kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); NewLIR2(cu, kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); NewLIR2(cu, kX86Xor32RR, rAX, rAX); - NewLIR3(cu, kX86LockCmpxchgMR, rCX, Object::MonitorOffset().Int32Value(), rDX); + NewLIR3(cu, kX86LockCmpxchgMR, rCX, mirror::Object::MonitorOffset().Int32Value(), rDX); LIR* branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondEq); // If lock is held, go the expensive route - artLockObjectFromCode(self, obj); CallRuntimeHelperReg(cu, ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX, true); @@ -180,10 +180,10 @@ void X86Codegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation // TODO: clear hash state? NewLIR2(cu, kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); NewLIR2(cu, kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); - NewLIR3(cu, kX86Mov32RM, rCX, rAX, Object::MonitorOffset().Int32Value()); + NewLIR3(cu, kX86Mov32RM, rCX, rAX, mirror::Object::MonitorOffset().Int32Value()); OpRegReg(cu, kOpSub, rCX, rDX); LIR* branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondNe); - NewLIR3(cu, kX86Mov32MR, rAX, Object::MonitorOffset().Int32Value(), rCX); + NewLIR3(cu, kX86Mov32MR, rAX, mirror::Object::MonitorOffset().Int32Value(), rCX); LIR* branch2 = NewLIR1(cu, kX86Jmp8, 0); branch->target = NewLIR0(cu, kPseudoTargetLabel); // Otherwise, go the expensive route - UnlockObjectFromCode(obj); diff --git a/src/compiler/codegen/x86/int_x86.cc b/src/compiler/codegen/x86/int_x86.cc index 0f1fc53925..f2d023cbad 100644 --- a/src/compiler/codegen/x86/int_x86.cc +++ b/src/compiler/codegen/x86/int_x86.cc @@ -446,16 +446,16 @@ void X86Codegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; RegLocation rl_result; rl_array = LoadValue(cu, rl_array, kCoreReg); rl_index = LoadValue(cu, rl_index, kCoreReg); if (size == kLong || size == kDouble) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } /* null object? */ @@ -494,13 +494,13 @@ void X86Codegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); - int len_offset = Array::LengthOffset().Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; if (size == kLong || size == kDouble) { - data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); } else { - data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value(); + data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } rl_array = LoadValue(cu, rl_array, kCoreReg); @@ -537,8 +537,8 @@ void X86Codegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re void X86Codegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { - int len_offset = Array::LengthOffset().Int32Value(); - int data_offset = Array::DataOffset(sizeof(Object*)).Int32Value(); + int len_offset = mirror::Array::LengthOffset().Int32Value(); + int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); FlushAllRegs(cu); // Use explicit registers LockCallTemps(cu); @@ -558,7 +558,7 @@ void X86Codegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, Object::ClassOffset().Int32Value(), r_array_class); + LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. diff --git a/src/compiler/compiler_internals.h b/src/compiler/compiler_internals.h index 1379a3b0a7..746999d43c 100644 --- a/src/compiler/compiler_internals.h +++ b/src/compiler/compiler_internals.h @@ -28,11 +28,10 @@ #include "compiler.h" #include "compiler_ir.h" #include "compiler_utility.h" -#include "dex_cache.h" #include "frontend.h" #include "gc/card_table.h" +#include "mirror/dex_cache.h" #include "monitor.h" -#include "object.h" #include "ralloc.h" #include "thread.h" #include "utils.h" diff --git a/src/compiler/frontend.cc b/src/compiler/frontend.cc index 31423ef095..6ccbc07180 100644 --- a/src/compiler/frontend.cc +++ b/src/compiler/frontend.cc @@ -19,7 +19,7 @@ #include "dataflow.h" #include "ssa_transformation.h" #include "leb128.h" -#include "object.h" +#include "mirror/object.h" #include "runtime.h" #include "codegen/codegen_util.h" #include "codegen/mir_to_gbc.h" diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h index 9aa9791ee8..bb14c49163 100644 --- a/src/compiler_llvm/compiler_llvm.h +++ b/src/compiler_llvm/compiler_llvm.h @@ -21,7 +21,7 @@ #include "compiler.h" #include "dex_file.h" #include "instruction_set.h" -#include "object.h" +#include "mirror/object.h" #include "procedure_linkage_table.h" #include <UniquePtr.h> @@ -31,13 +31,15 @@ #include <vector> namespace art { - class ClassLoader; class CompiledInvokeStub; class CompiledMethod; class Compiler; class OatCompilationUnit; - class AbstractMethod; -} + namespace mirror { + class AbstractMethod; + class ClassLoader; + } // namespace mirror +} // namespace art namespace llvm { @@ -47,7 +49,7 @@ namespace llvm { class PointerType; class StructType; class Type; -} +} // namespace llvm namespace art { diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc index a7970d5403..03488747e8 100644 --- a/src/compiler_llvm/gbc_expander.cc +++ b/src/compiler_llvm/gbc_expander.cc @@ -19,8 +19,8 @@ #include "compiler.h" #include "greenland/intrinsic_helper.h" +#include "mirror/object.h" #include "oat_compilation_unit.h" -#include "object.h" #include "thread.h" #include "verifier/method_verifier.h" diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc index da55d94cce..e81afed8bc 100644 --- a/src/compiler_llvm/jni_compiler.cc +++ b/src/compiler_llvm/jni_compiler.cc @@ -23,8 +23,8 @@ #include "compiler.h" #include "compiler_llvm.h" #include "ir_builder.h" +#include "mirror/object.h" #include "oat_compilation_unit.h" -#include "object.h" #include "runtime.h" #include "runtime_support_func.h" #include "utils_llvm.h" diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h index c4287751d1..0731e92a52 100644 --- a/src/compiler_llvm/jni_compiler.h +++ b/src/compiler_llvm/jni_compiler.h @@ -21,14 +21,16 @@ namespace art { class ClassLinker; - class ClassLoader; class CompiledMethod; class Compiler; - class DexCache; class DexFile; - class AbstractMethod; class OatCompilationUnit; -} + namespace mirror { + class AbstractMethod; + class ClassLoader; + class DexCache; + } // namespace mirror +} // namespace art namespace llvm { class AllocaInst; @@ -39,7 +41,7 @@ namespace llvm { class Module; class Type; class Value; -} +} // namespace llvm namespace art { namespace compiler_llvm { diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index ccec7e96ec..bc3fb92075 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -25,8 +25,8 @@ #include "dalvik_reg.h" #include "greenland/inferred_reg_category_map.h" #include "ir_builder.h" +#include "mirror/object.h" #include "oat_compilation_unit.h" -#include "object.h" #include "object_utils.h" #include "runtime_support_func.h" #include "runtime_support_llvm.h" diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h index f67866affd..dd9d1829c3 100644 --- a/src/compiler_llvm/method_compiler.h +++ b/src/compiler_llvm/method_compiler.h @@ -34,17 +34,20 @@ namespace art { class ClassLinker; - class ClassLoader; class CompiledMethod; class Compiler; - class DexCache; - class Field; class OatCompilationUnit; + namespace mirror { + class ClassLoader; + class DexCache; + class Field; + } // namespace mirror + namespace greenland { class InferredRegCategoryMap; - } -} + } // namespace greenland +} // namespace art namespace llvm { @@ -55,7 +58,7 @@ namespace llvm { class LLVMContext; class Module; class Type; -} +} // namespace llvm namespace art { diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc index 169f8e8b42..36b5fa1974 100644 --- a/src/compiler_llvm/runtime_support_builder.cc +++ b/src/compiler_llvm/runtime_support_builder.cc @@ -19,7 +19,7 @@ #include "gc/card_table.h" #include "ir_builder.h" #include "monitor.h" -#include "object.h" +#include "mirror/object.h" #include "thread.h" #include <llvm/DerivedTypes.h> @@ -179,7 +179,7 @@ void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) { kTBAARuntimeInfo); Value* monitor = irb_.LoadFromObjectOffset(object, - Object::MonitorOffset().Int32Value(), + mirror::Object::MonitorOffset().Int32Value(), irb_.getJIntTy(), kTBAARuntimeInfo); @@ -199,7 +199,7 @@ void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) { irb_.SetInsertPoint(bb_fast); // Set all bits to zero (except hash state) irb_.StoreToObjectOffset(object, - Object::MonitorOffset().Int32Value(), + mirror::Object::MonitorOffset().Int32Value(), hash_state, kTBAARuntimeInfo); irb_.CreateBr(bb_cont); diff --git a/src/compiler_llvm/runtime_support_builder_thumb2.cc b/src/compiler_llvm/runtime_support_builder_thumb2.cc index 3299afe1bd..c18ae834b5 100644 --- a/src/compiler_llvm/runtime_support_builder_thumb2.cc +++ b/src/compiler_llvm/runtime_support_builder_thumb2.cc @@ -17,8 +17,8 @@ #include "runtime_support_builder_thumb2.h" #include "ir_builder.h" +#include "mirror/object.h" #include "monitor.h" -#include "object.h" #include "thread.h" #include "utils_llvm.h" diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc index d3552e94c4..8de90fff56 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -22,8 +22,8 @@ #include "compiler_runtime_func_list.h" #include "dex_file.h" #include "dex_instruction.h" +#include "mirror/object.h" #include "nth_caller_visitor.h" -#include "object.h" #include "object_utils.h" #include "reflection.h" #include "runtime_support.h" @@ -60,7 +60,7 @@ void* art_set_current_thread_from_code(void* thread_object_addr) { return NULL; } -void art_lock_object_from_code(Object* obj, Thread* thread) +void art_lock_object_from_code(mirror::Object* obj, Thread* thread) EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) { DCHECK(obj != NULL); // Assumed to have been checked before entry obj->MonitorEnter(thread); // May block @@ -69,7 +69,7 @@ void art_lock_object_from_code(Object* obj, Thread* thread) DCHECK(!thread->IsExceptionPending()); } -void art_unlock_object_from_code(Object* obj, Thread* thread) +void art_unlock_object_from_code(mirror::Object* obj, Thread* thread) UNLOCK_FUNCTION(monitor_lock_) { DCHECK(obj != NULL); // Assumed to have been checked before entry // MonitorExit may throw exception @@ -82,7 +82,7 @@ void art_test_suspend_from_code(Thread* thread) } ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame, - AbstractMethod* method, uint32_t num_vregs) { + mirror::AbstractMethod* method, uint32_t num_vregs) { ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame); new_shadow_frame->SetMethod(method); new_shadow_frame->SetNumberOfVRegs(num_vregs); @@ -120,13 +120,13 @@ void art_throw_array_bounds_from_code(int32_t index, int32_t length) void art_throw_no_such_method_from_code(int32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // We need the calling method as context for the method_idx. - AbstractMethod* method = Thread::Current()->GetCurrentMethod(); + mirror::AbstractMethod* method = Thread::Current()->GetCurrentMethod(); ThrowNoSuchMethodError(method_idx, method); } void art_throw_null_pointer_exception_from_code(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* throw_method = + mirror::AbstractMethod* throw_method = Thread::Current()->GetManagedStack()->GetTopShadowFrame()->GetMethod(); ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc); } @@ -135,21 +135,21 @@ void art_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_l ThrowStackOverflowError(Thread::Current()); } -void art_throw_exception_from_code(Object* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread::Current()->DeliverException(static_cast<Throwable*>(exception)); +void art_throw_exception_from_code(mirror::Object* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + Thread::Current()->DeliverException(static_cast<mirror::Throwable*>(exception)); } void* art_get_and_clear_exception(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(self->IsExceptionPending()); - Throwable* exception = self->GetException(); + mirror::Throwable* exception = self->GetException(); self->ClearException(); return exception; } -int32_t art_find_catch_block_from_code(AbstractMethod* current_method, uint32_t ti_offset) +int32_t art_find_catch_block_from_code(mirror::AbstractMethod* current_method, uint32_t ti_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* exception_type = Thread::Current()->GetException()->GetClass(); + mirror::Class* exception_type = Thread::Current()->GetException()->GetClass(); MethodHelper mh(current_method); const DexFile::CodeItem* code_item = mh.GetCodeItem(); DCHECK_LT(ti_offset, code_item->tries_size_); @@ -164,7 +164,7 @@ int32_t art_find_catch_block_from_code(AbstractMethod* current_method, uint32_t return iter_index; } // Does this catch exception type apply? - Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); + mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); if (iter_exception_type == NULL) { // The verifier should take care of resolving all exception classes early LOG(WARNING) << "Unresolved exception class when finding catch block: " @@ -183,57 +183,57 @@ int32_t art_find_catch_block_from_code(AbstractMethod* current_method, uint32_t // Object Space //---------------------------------------------------------------------------- -Object* art_alloc_object_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_alloc_object_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return AllocObjectFromCode(type_idx, referrer, thread, false); } -Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return AllocObjectFromCode(type_idx, referrer, thread, true); } -Object* art_alloc_array_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_alloc_array_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, uint32_t length, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return AllocArrayFromCode(type_idx, referrer, length, self, false); } -Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx, + mirror::AbstractMethod* referrer, uint32_t length, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return AllocArrayFromCode(type_idx, referrer, length, self, true); } -Object* art_check_and_alloc_array_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_check_and_alloc_array_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, uint32_t length, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false); } -Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx, + mirror::AbstractMethod* referrer, uint32_t length, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true); } -static AbstractMethod* FindMethodHelper(uint32_t method_idx, Object* this_object, - AbstractMethod* caller_method, bool access_check, +static mirror::AbstractMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_object, + mirror::AbstractMethod* caller_method, bool access_check, InvokeType type, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type); + mirror::AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type); if (UNLIKELY(method == NULL)) { method = FindMethodFromCode(method_idx, this_object, caller_method, thread, access_check, type); @@ -254,71 +254,71 @@ static AbstractMethod* FindMethodHelper(uint32_t method_idx, Object* this_object return method; } -Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, +mirror::Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread); } -Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, +mirror::Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread); } -Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, +mirror::Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread); } -Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, +mirror::Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread); } -Object* +mirror::Object* art_find_interface_method_from_code_with_access_check(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread); } -Object* art_find_interface_method_from_code(uint32_t method_idx, - Object* this_object, - AbstractMethod* referrer, +mirror::Object* art_find_interface_method_from_code(uint32_t method_idx, + mirror::Object* this_object, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread); } -Object* art_initialize_static_storage_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_initialize_static_storage_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false); } -Object* art_initialize_type_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_initialize_type_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false); } -Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, - AbstractMethod* referrer, +mirror::Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, + mirror::AbstractMethod* referrer, Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when caller isn't guaranteed to have access to a type and the dex cache may be @@ -326,14 +326,14 @@ Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true); } -Object* art_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx) +mirror::Object* art_resolve_string_from_code(mirror::AbstractMethod* referrer, uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return ResolveStringFromCode(referrer, string_idx); } -int32_t art_set32_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int32_t new_value) +int32_t art_set32_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, int32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint32_t)); if (LIKELY(field != NULL)) { field->Set32(field->GetDeclaringClass(), new_value); return 0; @@ -347,9 +347,9 @@ int32_t art_set32_static_from_code(uint32_t field_idx, AbstractMethod* referrer, return -1; } -int32_t art_set64_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int64_t new_value) +int32_t art_set64_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, int64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t)); if (LIKELY(field != NULL)) { field->Set64(field->GetDeclaringClass(), new_value); return 0; @@ -363,15 +363,15 @@ int32_t art_set64_static_from_code(uint32_t field_idx, AbstractMethod* referrer, return -1; } -int32_t art_set_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* new_value) +int32_t art_set_obj_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { field->SetObj(field->GetDeclaringClass(), new_value); return 0; } field = FindFieldFromCode(field_idx, referrer, Thread::Current(), - StaticObjectWrite, sizeof(Object*)); + StaticObjectWrite, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { field->SetObj(field->GetDeclaringClass(), new_value); return 0; @@ -379,9 +379,9 @@ int32_t art_set_obj_static_from_code(uint32_t field_idx, AbstractMethod* referre return -1; } -int32_t art_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer) +int32_t art_get32_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t)); if (LIKELY(field != NULL)) { return field->Get32(field->GetDeclaringClass()); } @@ -393,9 +393,9 @@ int32_t art_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer) return 0; } -int64_t art_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer) +int64_t art_get64_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t)); if (LIKELY(field != NULL)) { return field->Get64(field->GetDeclaringClass()); } @@ -407,24 +407,24 @@ int64_t art_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer) return 0; } -Object* art_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer) +mirror::Object* art_get_obj_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(field->GetDeclaringClass()); } field = FindFieldFromCode(field_idx, referrer, Thread::Current(), - StaticObjectRead, sizeof(Object*)); + StaticObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(field->GetDeclaringClass()); } return 0; } -int32_t art_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, - Object* obj, uint32_t new_value) +int32_t art_set32_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, + mirror::Object* obj, uint32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t)); if (LIKELY(field != NULL)) { field->Set32(obj, new_value); return 0; @@ -438,10 +438,10 @@ int32_t art_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referre return -1; } -int32_t art_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, - Object* obj, int64_t new_value) +int32_t art_set64_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, + mirror::Object* obj, int64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t)); if (LIKELY(field != NULL)) { field->Set64(obj, new_value); return 0; @@ -455,16 +455,16 @@ int32_t art_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referre return -1; } -int32_t art_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, - Object* obj, Object* new_value) +int32_t art_set_obj_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, + mirror::Object* obj, mirror::Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { field->SetObj(obj, new_value); return 0; } field = FindFieldFromCode(field_idx, referrer, Thread::Current(), - InstanceObjectWrite, sizeof(Object*)); + InstanceObjectWrite, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { field->SetObj(obj, new_value); return 0; @@ -472,9 +472,9 @@ int32_t art_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* refer return -1; } -int32_t art_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj) +int32_t art_get32_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t)); if (LIKELY(field != NULL)) { return field->Get32(obj); } @@ -486,9 +486,9 @@ int32_t art_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referre return 0; } -int64_t art_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj) +int64_t art_get64_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t)); if (LIKELY(field != NULL)) { return field->Get64(obj); } @@ -500,22 +500,22 @@ int64_t art_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referre return 0; } -Object* art_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj) +mirror::Object* art_get_obj_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(obj); } field = FindFieldFromCode(field_idx, referrer, Thread::Current(), - InstanceObjectRead, sizeof(Object*)); + InstanceObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(obj); } return 0; } -void art_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc, - Array* array, uint32_t payload_offset) +void art_fill_array_data_from_code(mirror::AbstractMethod* method, uint32_t dex_pc, + mirror::Array* array, uint32_t payload_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Test: Is array equal to null? (Guard NullPointerException) if (UNLIKELY(array == NULL)) { @@ -555,14 +555,14 @@ void art_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc, // Type checking, in the nature of casting //---------------------------------------------------------------------------- -int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type) +int32_t art_is_assignable_from_code(const mirror::Class* dest_type, const mirror::Class* src_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(dest_type != NULL); DCHECK(src_type != NULL); return dest_type->IsAssignableFrom(src_type) ? 1 : 0; } -void art_check_cast_from_code(const Class* dest_type, const Class* src_type) +void art_check_cast_from_code(const mirror::Class* dest_type, const mirror::Class* src_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(dest_type->IsClass()) << PrettyClass(dest_type); DCHECK(src_type->IsClass()) << PrettyClass(src_type); @@ -574,16 +574,16 @@ void art_check_cast_from_code(const Class* dest_type, const Class* src_type) } } -void art_check_put_array_element_from_code(const Object* element, const Object* array) +void art_check_put_array_element_from_code(const mirror::Object* element, const mirror::Object* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (element == NULL) { return; } DCHECK(array != NULL); - Class* array_class = array->GetClass(); + mirror::Class* array_class = array->GetClass(); DCHECK(array_class != NULL); - Class* component_type = array_class->GetComponentType(); - Class* element_class = element->GetClass(); + mirror::Class* component_type = array_class->GetComponentType(); + mirror::Class* element_class = element->GetClass(); if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) { Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", "%s cannot be stored in an array of type %s", @@ -634,11 +634,11 @@ void art_jni_method_end_synchronized(uint32_t saved_local_ref_cookie, jobject lo PopLocalReferences(saved_local_ref_cookie, self); } -Object* art_jni_method_end_with_reference(jobject result, uint32_t saved_local_ref_cookie, +mirror::Object* art_jni_method_end_with_reference(jobject result, uint32_t saved_local_ref_cookie, Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { self->TransitionFromSuspendedToRunnable(); - Object* o = self->DecodeJObject(result); // Must decode before pop. + mirror::Object* o = self->DecodeJObject(result); // Must decode before pop. PopLocalReferences(saved_local_ref_cookie, self); // Process result. if (UNLIKELY(self->GetJniEnv()->check_jni)) { @@ -650,13 +650,13 @@ Object* art_jni_method_end_with_reference(jobject result, uint32_t saved_local_r return o; } -Object* art_jni_method_end_with_reference_synchronized(jobject result, +mirror::Object* art_jni_method_end_with_reference_synchronized(jobject result, uint32_t saved_local_ref_cookie, jobject locked, Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { self->TransitionFromSuspendedToRunnable(); UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. - Object* o = self->DecodeJObject(result); + mirror::Object* o = self->DecodeJObject(result); PopLocalReferences(saved_local_ref_cookie, self); // Process result. if (UNLIKELY(self->GetJniEnv()->check_jni)) { @@ -711,12 +711,12 @@ static void* art_find_compiler_runtime_func(const char* name) { // Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation // handler which is a field within the proxy object receiver. The var args encode the arguments // with the last argument being a pointer to a JValue to store the result in. -void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) +void art_proxy_invoke_handler_from_code(mirror::AbstractMethod* proxy_method, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { va_list ap; va_start(ap, proxy_method); - Object* receiver = va_arg(ap, Object*); + mirror::Object* receiver = va_arg(ap, mirror::Object*); Thread* self = va_arg(ap, Thread*); MethodHelper proxy_mh(proxy_method); @@ -734,19 +734,19 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver); // Convert proxy method into expected interface method. - AbstractMethod* interface_method = proxy_method->FindOverriddenMethod(); + mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod(); DCHECK(interface_method != NULL); DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method); - // Record arguments and turn Object* arguments into jobject to survive GC. + // Record arguments and turn mirror::Object* arguments into jobject to survive GC. std::vector<jvalue> args; const size_t num_params = proxy_mh.NumArgs(); for (size_t i = 1; i < num_params; ++i) { jvalue val; switch (proxy_mh.GetParamPrimitiveType(i)) { case Primitive::kPrimNot: - val.l = soa.AddLocalReference<jobject>(va_arg(ap, Object*)); + val.l = soa.AddLocalReference<jobject>(va_arg(ap, mirror::Object*)); break; case Primitive::kPrimBoolean: // Fall-through. case Primitive::kPrimByte: // Fall-through. diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h index 6c133c9902..6a0b339062 100644 --- a/src/compiler_llvm/runtime_support_llvm.h +++ b/src/compiler_llvm/runtime_support_llvm.h @@ -17,7 +17,7 @@ #ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_ #define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_ -#include "object.h" +#include "mirror/object.h" namespace art { diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc index d03400f296..3a28b8733c 100644 --- a/src/compiler_llvm/stub_compiler.cc +++ b/src/compiler_llvm/stub_compiler.cc @@ -22,7 +22,7 @@ #include "compiler.h" #include "compiler_llvm.h" #include "ir_builder.h" -#include "object.h" +#include "mirror/object.h" #include "runtime_support_func.h" #include "utils_llvm.h" diff --git a/src/compiler_test.cc b/src/compiler_test.cc index f5135115b0..bd25eb3a3c 100644 --- a/src/compiler_test.cc +++ b/src/compiler_test.cc @@ -22,10 +22,13 @@ #include "UniquePtr.h" #include "class_linker.h" #include "common_test.h" -#include "dex_cache.h" #include "dex_file.h" #include "heap.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" namespace art { @@ -69,7 +72,7 @@ class CompilerTest : public CommonTest { const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); const char* descriptor = dex_file.GetClassDescriptor(class_def); ScopedObjectAccess soa(Thread::Current()); - Class* c = class_linker->FindClass(descriptor, soa.Decode<ClassLoader*>(class_loader)); + mirror::Class* c = class_linker->FindClass(descriptor, soa.Decode<mirror::ClassLoader*>(class_loader)); CHECK(c != NULL); for (size_t i = 0; i < c->NumDirectMethods(); i++) { MakeExecutable(c->GetDirectMethod(i)); @@ -92,21 +95,21 @@ TEST_F(CompilerTest, DISABLED_LARGE_CompileDexLibCore) { // All libcore references should resolve ScopedObjectAccess soa(Thread::Current()); const DexFile* dex = java_lang_dex_file_; - DexCache* dex_cache = class_linker_->FindDexCache(*dex); + mirror::DexCache* dex_cache = class_linker_->FindDexCache(*dex); EXPECT_EQ(dex->NumStringIds(), dex_cache->NumStrings()); for (size_t i = 0; i < dex_cache->NumStrings(); i++) { - const String* string = dex_cache->GetResolvedString(i); + const mirror::String* string = dex_cache->GetResolvedString(i); EXPECT_TRUE(string != NULL) << "string_idx=" << i; } EXPECT_EQ(dex->NumTypeIds(), dex_cache->NumResolvedTypes()); for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { - Class* type = dex_cache->GetResolvedType(i); + mirror::Class* type = dex_cache->GetResolvedType(i); EXPECT_TRUE(type != NULL) << "type_idx=" << i << " " << dex->GetTypeDescriptor(dex->GetTypeId(i)); } EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumResolvedMethods()); for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { - AbstractMethod* method = dex_cache->GetResolvedMethod(i); + mirror::AbstractMethod* method = dex_cache->GetResolvedMethod(i); EXPECT_TRUE(method != NULL) << "method_idx=" << i << " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i)) << " " << dex->GetMethodName(dex->GetMethodId(i)); @@ -117,7 +120,7 @@ TEST_F(CompilerTest, DISABLED_LARGE_CompileDexLibCore) { } EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields()); for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { - Field* field = dex_cache->GetResolvedField(i); + mirror::Field* field = dex_cache->GetResolvedField(i); EXPECT_TRUE(field != NULL) << "field_idx=" << i << " " << dex->GetFieldDeclaringClassDescriptor(dex->GetFieldId(i)) << " " << dex->GetFieldName(dex->GetFieldId(i)); diff --git a/src/debugger.cc b/src/debugger.cc index 3e93511ce2..312172569c 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -21,10 +21,19 @@ #include <set> #include "class_linker.h" -#include "class_loader.h" +#include "class_linker-inl.h" #include "dex_instruction.h" +#include "gc/card_table-inl.h" #include "gc/large_object_space.h" #include "gc/space.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/throwable.h" #include "oat/runtime/context.h" #include "object_utils.h" #include "safe_map.h" @@ -34,6 +43,7 @@ #include "sirt_ref.h" #include "stack_indirect_reference_table.h" #include "thread_list.h" +#include "utf.h" #include "well_known_classes.h" namespace art { @@ -42,14 +52,14 @@ static const size_t kMaxAllocRecordStackDepth = 16; // Max 255. static const size_t kNumAllocRecords = 512; // Must be power of 2. static const uintptr_t kInvalidId = 1; -static const Object* kInvalidObject = reinterpret_cast<Object*>(kInvalidId); +static const mirror::Object* kInvalidObject = reinterpret_cast<mirror::Object*>(kInvalidId); class ObjectRegistry { public: ObjectRegistry() : lock_("ObjectRegistry lock") { } - JDWP::ObjectId Add(Object* o) { + JDWP::ObjectId Add(mirror::Object* o) { if (o == NULL) { return 0; } @@ -76,14 +86,14 @@ class ObjectRegistry { } MutexLock mu(Thread::Current(), lock_); - typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto + typedef SafeMap<JDWP::ObjectId, mirror::Object*>::iterator It; // C++0x auto It it = map_.find(id); return (it != map_.end()) ? reinterpret_cast<T>(it->second) : reinterpret_cast<T>(kInvalidId); } - void VisitRoots(Heap::RootVisitor* visitor, void* arg) { + void VisitRoots(RootVisitor* visitor, void* arg) { MutexLock mu(Thread::Current(), lock_); - typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto + typedef SafeMap<JDWP::ObjectId, mirror::Object*>::iterator It; // C++0x auto for (It it = map_.begin(); it != map_.end(); ++it) { visitor(it->second, arg); } @@ -91,11 +101,11 @@ class ObjectRegistry { private: Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - SafeMap<JDWP::ObjectId, Object*> map_; + SafeMap<JDWP::ObjectId, mirror::Object*> map_; }; struct AllocRecordStackTraceElement { - AbstractMethod* method; + mirror::AbstractMethod* method; uint32_t dex_pc; int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -104,7 +114,7 @@ struct AllocRecordStackTraceElement { }; struct AllocRecord { - Class* type; + mirror::Class* type; size_t byte_count; uint16_t thin_lock_id; AllocRecordStackTraceElement stack[kMaxAllocRecordStackDepth]; // Unused entries have NULL method. @@ -119,9 +129,9 @@ struct AllocRecord { }; struct Breakpoint { - AbstractMethod* method; + mirror::AbstractMethod* method; uint32_t dex_pc; - Breakpoint(AbstractMethod* method, uint32_t dex_pc) : method(method), dex_pc(dex_pc) {} + Breakpoint(mirror::AbstractMethod* method, uint32_t dex_pc) : method(method), dex_pc(dex_pc) {} }; static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs) @@ -138,7 +148,7 @@ struct SingleStepControl { JDWP::JdwpStepSize step_size; JDWP::JdwpStepDepth step_depth; - const AbstractMethod* method; + const mirror::AbstractMethod* method; int32_t line_number; // Or -1 for native methods. std::set<uint32_t> dex_pcs; int stack_depth; @@ -180,7 +190,7 @@ static size_t gAllocRecordCount GUARDED_BY(gAllocTrackerLock) = 0; static std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_); static SingleStepControl gSingleStepControl GUARDED_BY(Locks::breakpoint_lock_); -static bool IsBreakpoint(AbstractMethod* m, uint32_t dex_pc) +static bool IsBreakpoint(mirror::AbstractMethod* m, uint32_t dex_pc) LOCKS_EXCLUDED(Locks::breakpoint_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); @@ -200,9 +210,9 @@ static bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thr return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0; } -static Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) +static mirror::Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = gRegistry->Get<Object*>(id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(id); if (o == NULL || o == kInvalidObject) { status = JDWP::ERR_INVALID_OBJECT; return NULL; @@ -215,9 +225,9 @@ static Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) return o->AsArray(); } -static Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) +static mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = gRegistry->Get<Object*>(id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(id); if (o == NULL || o == kInvalidObject) { status = JDWP::ERR_INVALID_OBJECT; return NULL; @@ -234,13 +244,13 @@ static JDWP::JdwpError DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::Obje EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* thread_peer = gRegistry->Get<Object*>(thread_id); + mirror::Object* thread_peer = gRegistry->Get<mirror::Object*>(thread_id); if (thread_peer == NULL || thread_peer == kInvalidObject) { // This isn't even an object. return JDWP::ERR_INVALID_OBJECT; } - Class* java_lang_Thread = soa.Decode<Class*>(WellKnownClasses::java_lang_Thread); + mirror::Class* java_lang_Thread = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) { // This isn't a thread. return JDWP::ERR_INVALID_THREAD; @@ -260,7 +270,7 @@ static JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) { return static_cast<JDWP::JdwpTag>(descriptor[0]); } -static JDWP::JdwpTag TagFromClass(Class* c) +static JDWP::JdwpTag TagFromClass(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(c != NULL); if (c->IsArrayClass()) { @@ -291,7 +301,7 @@ static JDWP::JdwpTag TagFromClass(Class* c) * * Null objects are tagged JT_OBJECT. */ -static JDWP::JdwpTag TagFromObject(const Object* o) +static JDWP::JdwpTag TagFromObject(const mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(o->GetClass()); } @@ -567,14 +577,14 @@ void Dbg::Exit(int status) { exit(status); // This is all dalvik did. } -void Dbg::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void Dbg::VisitRoots(RootVisitor* visitor, void* arg) { if (gRegistry != NULL) { gRegistry->VisitRoots(visitor, arg); } } std::string Dbg::GetClassName(JDWP::RefTypeId class_id) { - Object* o = gRegistry->Get<Object*>(class_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id); if (o == NULL) { return "NULL"; } @@ -589,7 +599,7 @@ std::string Dbg::GetClassName(JDWP::RefTypeId class_id) { JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) { JDWP::JdwpError status; - Class* c = DecodeClass(id, status); + mirror::Class* c = DecodeClass(id, status); if (c == NULL) { return status; } @@ -599,7 +609,7 @@ JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_ob JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id) { JDWP::JdwpError status; - Class* c = DecodeClass(id, status); + mirror::Class* c = DecodeClass(id, status); if (c == NULL) { return status; } @@ -613,7 +623,7 @@ JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& supercla } JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { - Object* o = gRegistry->Get<Object*>(id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(id); if (o == NULL || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -623,7 +633,7 @@ JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Class* c = DecodeClass(id, status); + mirror::Class* c = DecodeClass(id, status); if (c == NULL) { return status; } @@ -641,7 +651,7 @@ JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if (o == NULL || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -699,14 +709,14 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, return true; } - static void AppendOwnedMonitors(Object* owned_monitor, void* arg) { + static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg) { OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg); visitor->monitors.push_back(owned_monitor); visitor->stack_depths.push_back(visitor->current_stack_depth); } size_t current_stack_depth; - std::vector<Object*> monitors; + std::vector<mirror::Object*> monitors; std::vector<uint32_t> stack_depths; }; UniquePtr<Context> context(Context::Create()); @@ -743,11 +753,11 @@ JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class std::vector<uint64_t>& counts) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - std::vector<Class*> classes; + std::vector<mirror::Class*> classes; counts.clear(); for (size_t i = 0; i < class_ids.size(); ++i) { JDWP::JdwpError status; - Class* c = DecodeClass(class_ids[i], status); + mirror::Class* c = DecodeClass(class_ids[i], status); if (c == NULL) { return status; } @@ -762,12 +772,12 @@ JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, std::vector<JDWP::ObjectId>& instances) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } - std::vector<Object*> raw_instances; + std::vector<mirror::Object*> raw_instances; Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { instances.push_back(gRegistry->Add(raw_instances[i])); @@ -778,12 +788,12 @@ JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, s JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, std::vector<JDWP::ObjectId>& referring_objects) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if (o == NULL || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - std::vector<Object*> raw_instances; + std::vector<mirror::Object*> raw_instances; Runtime::Current()->GetHeap()->GetReferringObjects(o, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { referring_objects.push_back(gRegistry->Add(raw_instances[i])); @@ -793,7 +803,7 @@ JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_c JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -811,11 +821,11 @@ void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { explicit ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) { } - static bool Visit(Class* c, void* arg) { + static bool Visit(mirror::Class* c, void* arg) { return reinterpret_cast<ClassListCreator*>(arg)->Visit(c); } - bool Visit(Class* c) { + bool Visit(mirror::Class* c) { if (!c->IsPrimitive()) { classes.push_back(static_cast<JDWP::RefTypeId>(gRegistry->Add(c))); } @@ -831,7 +841,7 @@ void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -855,7 +865,7 @@ JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* p } void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) { - std::vector<Class*> classes; + std::vector<mirror::Class*> classes; Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes); ids.clear(); for (size_t i = 0; i < classes.size(); ++i) { @@ -864,7 +874,7 @@ void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::R } JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) { - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if (o == NULL || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -887,7 +897,7 @@ JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string& signature) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -897,7 +907,7 @@ JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string& signatu JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string& result) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -906,7 +916,7 @@ JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string& result } JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) { - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if (o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -946,7 +956,7 @@ size_t Dbg::GetTagWidth(JDWP::JdwpTag tag) { JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int& length) { JDWP::JdwpError status; - Array* a = DecodeArray(array_id, status); + mirror::Array* a = DecodeArray(array_id, status); if (a == NULL) { return status; } @@ -956,7 +966,7 @@ JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int& length) { JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Array* a = DecodeArray(array_id, status); + mirror::Array* a = DecodeArray(array_id, status); if (a == NULL) { return status; } @@ -988,9 +998,9 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, memcpy(dst, &src[offset * width], count * width); } } else { - ObjectArray<Object>* oa = a->AsObjectArray<Object>(); + mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>(); for (int i = 0; i < count; ++i) { - Object* element = oa->Get(offset + i); + mirror::Object* element = oa->Get(offset + i); JDWP::JdwpTag specific_tag = (element != NULL) ? TagFromObject(element) : tag; expandBufAdd1(pReply, specific_tag); expandBufAddObjectId(pReply, gRegistry->Add(element)); @@ -1004,7 +1014,7 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c const uint8_t* src) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JDWP::JdwpError status; - Array* a = DecodeArray(array_id, status); + mirror::Array* a = DecodeArray(array_id, status); if (a == NULL) { return status; } @@ -1040,10 +1050,10 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c memcpy(&dst[offset * width], src, count * width); } } else { - ObjectArray<Object>* oa = a->AsObjectArray<Object>(); + mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>(); for (int i = 0; i < count; ++i) { JDWP::ObjectId id = JDWP::ReadObjectId(&src); - Object* o = gRegistry->Get<Object*>(id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(id); if (o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -1055,12 +1065,12 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int c } JDWP::ObjectId Dbg::CreateString(const std::string& str) { - return gRegistry->Add(String::AllocFromModifiedUtf8(Thread::Current(), str.c_str())); + return gRegistry->Add(mirror::String::AllocFromModifiedUtf8(Thread::Current(), str.c_str())); } JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -1074,24 +1084,24 @@ JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, JDWP::ObjectId& new_array) { JDWP::JdwpError status; - Class* c = DecodeClass(array_class_id, status); + mirror::Class* c = DecodeClass(array_class_id, status); if (c == NULL) { return status; } - new_array = gRegistry->Add(Array::Alloc(Thread::Current(), c, length)); + new_array = gRegistry->Add(mirror::Array::Alloc(Thread::Current(), c, length)); return JDWP::ERR_NONE; } bool Dbg::MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id) { JDWP::JdwpError status; - Class* c1 = DecodeClass(instance_class_id, status); + mirror::Class* c1 = DecodeClass(instance_class_id, status); CHECK(c1 != NULL); - Class* c2 = DecodeClass(class_id, status); + mirror::Class* c2 = DecodeClass(class_id, status); CHECK(c2 != NULL); return c1->IsAssignableFrom(c2); } -static JDWP::FieldId ToFieldId(const Field* f) +static JDWP::FieldId ToFieldId(const mirror::Field* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(FATAL); @@ -1100,7 +1110,7 @@ static JDWP::FieldId ToFieldId(const Field* f) #endif } -static JDWP::MethodId ToMethodId(const AbstractMethod* m) +static JDWP::MethodId ToMethodId(const mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(FATAL); @@ -1109,30 +1119,30 @@ static JDWP::MethodId ToMethodId(const AbstractMethod* m) #endif } -static Field* FromFieldId(JDWP::FieldId fid) +static mirror::Field* FromFieldId(JDWP::FieldId fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(FATAL); #else - return reinterpret_cast<Field*>(static_cast<uintptr_t>(fid)); + return reinterpret_cast<mirror::Field*>(static_cast<uintptr_t>(fid)); #endif } -static AbstractMethod* FromMethodId(JDWP::MethodId mid) +static mirror::AbstractMethod* FromMethodId(JDWP::MethodId mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(FATAL); #else - return reinterpret_cast<AbstractMethod*>(static_cast<uintptr_t>(mid)); + return reinterpret_cast<mirror::AbstractMethod*>(static_cast<uintptr_t>(mid)); #endif } -static void SetLocation(JDWP::JdwpLocation& location, AbstractMethod* m, uint32_t dex_pc) +static void SetLocation(JDWP::JdwpLocation& location, mirror::AbstractMethod* m, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (m == NULL) { memset(&location, 0, sizeof(location)); } else { - Class* c = m->GetDeclaringClass(); + mirror::Class* c = m->GetDeclaringClass(); location.type_tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; location.class_id = gRegistry->Add(c); location.method_id = ToMethodId(m); @@ -1142,13 +1152,13 @@ static void SetLocation(JDWP::JdwpLocation& location, AbstractMethod* m, uint32_ std::string Dbg::GetMethodName(JDWP::MethodId method_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = FromMethodId(method_id); + mirror::AbstractMethod* m = FromMethodId(method_id); return MethodHelper(m).GetName(); } std::string Dbg::GetFieldName(JDWP::FieldId field_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* f = FromFieldId(field_id); + mirror::Field* f = FromFieldId(field_id); return FieldHelper(f).GetName(); } @@ -1190,7 +1200,7 @@ static uint16_t MangleSlot(uint16_t slot, const char* name) { return newSlot; } -static uint16_t DemangleSlot(uint16_t slot, AbstractMethod* m) +static uint16_t DemangleSlot(uint16_t slot, mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (slot == kEclipseWorkaroundSlot) { return 0; @@ -1204,7 +1214,7 @@ static uint16_t DemangleSlot(uint16_t slot, AbstractMethod* m) JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -1215,7 +1225,7 @@ JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_ge expandBufAdd4BE(pReply, instance_field_count + static_field_count); for (size_t i = 0; i < instance_field_count + static_field_count; ++i) { - Field* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count); + mirror::Field* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count); FieldHelper fh(f); expandBufAddFieldId(pReply, ToFieldId(f)); expandBufAddUtf8String(pReply, fh.GetName()); @@ -1232,7 +1242,7 @@ JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_ge JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -1243,7 +1253,7 @@ JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_g expandBufAdd4BE(pReply, direct_method_count + virtual_method_count); for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) { - AbstractMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count); + mirror::AbstractMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count); MethodHelper mh(m); expandBufAddMethodId(pReply, ToMethodId(m)); expandBufAddUtf8String(pReply, mh.GetName()); @@ -1259,7 +1269,7 @@ JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_g JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } @@ -1287,7 +1297,7 @@ void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::Expan return true; } }; - AbstractMethod* m = FromMethodId(method_id); + mirror::AbstractMethod* m = FromMethodId(method_id); MethodHelper mh(m); uint64_t start, end; if (m->IsNative()) { @@ -1341,14 +1351,14 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi ++pContext->variable_count; } }; - AbstractMethod* m = FromMethodId(method_id); + mirror::AbstractMethod* m = FromMethodId(method_id); MethodHelper mh(m); const DexFile::CodeItem* code_item = mh.GetCodeItem(); // arg_count considers doubles and longs to take 2 units. // variable_count considers everything to take 1 unit. std::string shorty(mh.GetShorty()); - expandBufAdd4BE(pReply, AbstractMethod::NumArgRegisters(shorty)); + expandBufAdd4BE(pReply, mirror::AbstractMethod::NumArgRegisters(shorty)); // We don't know the total number of variables yet, so leave a blank and update it later. size_t variable_count_offset = expandBufGetLength(pReply); @@ -1368,7 +1378,7 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, std::vector<uint8_t>& bytecodes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = FromMethodId(method_id); + mirror::AbstractMethod* m = FromMethodId(method_id); if (m == NULL) { return JDWP::ERR_INVALID_METHODID; } @@ -1396,18 +1406,18 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JDWP::JdwpError status; - Class* c = DecodeClass(ref_type_id, status); + mirror::Class* c = DecodeClass(ref_type_id, status); if (ref_type_id != 0 && c == NULL) { return status; } - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if ((!is_static && o == NULL) || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - Field* f = FromFieldId(field_id); + mirror::Field* f = FromFieldId(field_id); - Class* receiver_class = c; + mirror::Class* receiver_class = c; if (receiver_class == NULL && o != NULL) { receiver_class = o->GetClass(); } @@ -1448,7 +1458,7 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje LOG(FATAL) << "Unknown tag: " << tag; } } else { - Object* value = f->GetObject(o); + mirror::Object* value = f->GetObject(o); expandBufAdd1(pReply, TagFromObject(value)); expandBufAddObjectId(pReply, gRegistry->Add(value)); } @@ -1467,11 +1477,11 @@ JDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::Fiel static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value, int width, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Object* o = gRegistry->Get<Object*>(object_id); + mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if ((!is_static && o == NULL) || o == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - Field* f = FromFieldId(field_id); + mirror::Field* f = FromFieldId(field_id); // The RI only enforces the static/non-static mismatch in one direction. // TODO: should we change the tests and check both? @@ -1499,12 +1509,12 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId f->Set32(o, value); } } else { - Object* v = gRegistry->Get<Object*>(value); + mirror::Object* v = gRegistry->Get<mirror::Object*>(value); if (v == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } if (v != NULL) { - Class* field_type = FieldHelper(f).GetType(); + mirror::Class* field_type = FieldHelper(f).GetType(); if (!field_type->IsAssignableFrom(v->GetClass())) { return JDWP::ERR_INVALID_OBJECT; } @@ -1525,7 +1535,7 @@ JDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, } std::string Dbg::StringToUtf8(JDWP::ObjectId string_id) { - String* s = gRegistry->Get<String*>(string_id); + mirror::String* s = gRegistry->Get<mirror::String*>(string_id); return s->ToModifiedUtf8(); } @@ -1539,9 +1549,11 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string& name) } // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName. - Object* thread_object = gRegistry->Get<Object*>(thread_id); - Field* java_lang_Thread_name_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - String* s = reinterpret_cast<String*>(java_lang_Thread_name_field->GetObject(thread_object)); + mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); + mirror::Field* java_lang_Thread_name_field = + soa.DecodeField(WellKnownClasses::java_lang_Thread_name); + mirror::String* s = + reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object)); if (s != NULL) { name = s->ToModifiedUtf8(); } @@ -1550,7 +1562,7 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string& name) JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { ScopedObjectAccess soa(Thread::Current()); - Object* thread_object = gRegistry->Get<Object*>(thread_id); + mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); if (thread_object == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } @@ -1568,11 +1580,11 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p return error; } - Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Thread;"); + mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Thread;"); CHECK(c != NULL); - Field* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;"); + mirror::Field* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;"); CHECK(f != NULL); - Object* group = f->GetObject(thread_object); + mirror::Object* group = f->GetObject(thread_object); CHECK(group != NULL); JDWP::ObjectId thread_group_id = gRegistry->Add(group); @@ -1582,40 +1594,40 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { ScopedObjectAccess soa(Thread::Current()); - Object* thread_group = gRegistry->Get<Object*>(thread_group_id); + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); CHECK(thread_group != NULL); - Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); + mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); CHECK(c != NULL); - Field* f = c->FindInstanceField("name", "Ljava/lang/String;"); + mirror::Field* f = c->FindInstanceField("name", "Ljava/lang/String;"); CHECK(f != NULL); - String* s = reinterpret_cast<String*>(f->GetObject(thread_group)); + mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); return s->ToModifiedUtf8(); } JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { - Object* thread_group = gRegistry->Get<Object*>(thread_group_id); + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); CHECK(thread_group != NULL); - Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); + mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); CHECK(c != NULL); - Field* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;"); + mirror::Field* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;"); CHECK(f != NULL); - Object* parent = f->GetObject(thread_group); + mirror::Object* parent = f->GetObject(thread_group); return gRegistry->Add(parent); } JDWP::ObjectId Dbg::GetSystemThreadGroupId() { ScopedObjectAccessUnchecked soa(Thread::Current()); - Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); - Object* group = f->GetObject(f->GetDeclaringClass()); + mirror::Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); + mirror::Object* group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } JDWP::ObjectId Dbg::GetMainThreadGroupId() { ScopedObjectAccess soa(Thread::Current()); - Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup); - Object* group = f->GetObject(f->GetDeclaringClass()); + mirror::Field* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup); + mirror::Object* group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } @@ -1691,7 +1703,7 @@ JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) { void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) { class ThreadListVisitor { public: - ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, Object* desired_thread_group, + ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, mirror::Object* desired_thread_group, std::vector<JDWP::ObjectId>& thread_ids) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : soa_(soa), desired_thread_group_(desired_thread_group), thread_ids_(thread_ids) {} @@ -1708,20 +1720,20 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> // query all threads, so it's easier if we just don't tell them about this thread. return; } - Object* peer = t->GetPeer(); + mirror::Object* peer = t->GetPeer(); if (IsInDesiredThreadGroup(peer)) { thread_ids_.push_back(gRegistry->Add(peer)); } } private: - bool IsInDesiredThreadGroup(Object* peer) + bool IsInDesiredThreadGroup(mirror::Object* peer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // peer might be NULL if the thread is still starting up. if (peer == NULL) { // We can't tell the debugger about this thread yet. // TODO: if we identified threads to the debugger by their Thread* - // rather than their peer's Object*, we could fix this. + // rather than their peer's mirror::Object*, we could fix this. // Doing so might help us report ZOMBIE threads too. return false; } @@ -1729,17 +1741,17 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> if (desired_thread_group_ == NULL) { return true; } - Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer); + mirror::Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer); return (group == desired_thread_group_); } const ScopedObjectAccessUnchecked& soa_; - Object* const desired_thread_group_; + mirror::Object* const desired_thread_group_; std::vector<JDWP::ObjectId>& thread_ids_; }; ScopedObjectAccessUnchecked soa(Thread::Current()); - Object* thread_group = gRegistry->Get<Object*>(thread_group_id); + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); ThreadListVisitor tlv(soa, thread_group, thread_ids); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Runtime::Current()->GetThreadList()->ForEach(ThreadListVisitor::Visit, &tlv); @@ -1747,16 +1759,17 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids) { ScopedObjectAccess soa(Thread::Current()); - Object* thread_group = gRegistry->Get<Object*>(thread_group_id); + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); // Get the ArrayList<ThreadGroup> "groups" out of this thread group... - Field* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); - Object* groups_array_list = groups_field->GetObject(thread_group); + mirror::Field* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); + mirror::Object* groups_array_list = groups_field->GetObject(thread_group); // Get the array and size out of the ArrayList<ThreadGroup>... - Field* array_field = groups_array_list->GetClass()->FindInstanceField("array", "[Ljava/lang/Object;"); - Field* size_field = groups_array_list->GetClass()->FindInstanceField("size", "I"); - ObjectArray<Object>* groups_array = array_field->GetObject(groups_array_list)->AsObjectArray<Object>(); + mirror::Field* array_field = groups_array_list->GetClass()->FindInstanceField("array", "[Ljava/lang/Object;"); + mirror::Field* size_field = groups_array_list->GetClass()->FindInstanceField("size", "I"); + mirror::ObjectArray<mirror::Object>* groups_array = + array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>(); const int32_t size = size_field->GetInt(groups_array_list); // Copy the first 'size' elements out of the array into the result. @@ -1871,7 +1884,7 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspen ScopedLocalRef<jobject> peer(Thread::Current()->GetJniEnv(), NULL); { ScopedObjectAccess soa(Thread::Current()); - peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<Object*>(thread_id))); + peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id))); } if (peer.get() == NULL) { return JDWP::ERR_THREAD_NOT_ALIVE; @@ -1890,7 +1903,7 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspen void Dbg::ResumeThread(JDWP::ObjectId thread_id) { ScopedObjectAccessUnchecked soa(Thread::Current()); - Object* peer = gRegistry->Get<Object*>(thread_id); + mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id); Thread* thread; { MutexLock mu(soa.Self(), *Locks::thread_list_lock_); @@ -1925,21 +1938,21 @@ struct GetThisVisitor : public StackVisitor { if (frame_id != GetFrameId()) { return true; // continue } - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m->IsNative() || m->IsStatic()) { this_object = NULL; } else { uint16_t reg = DemangleSlot(0, m); - this_object = reinterpret_cast<Object*>(GetVReg(m, reg, kReferenceVReg)); + this_object = reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg)); } return false; } - Object* this_object; + mirror::Object* this_object; JDWP::FrameId frame_id; }; -static Object* GetThis(Thread* self, AbstractMethod* m, size_t frame_id) +static mirror::Object* GetThis(Thread* self, mirror::AbstractMethod* m, size_t frame_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // TODO: should we return the 'this' we passed through to non-static native methods? if (m->IsNative() || m->IsStatic()) { @@ -1989,7 +2002,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl return true; // Not our frame, carry on. } // TODO: check that the tag is compatible with the actual type of the slot! - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); uint16_t reg = DemangleSlot(slot_, m); switch (tag_) { @@ -2037,7 +2050,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl case JDWP::JT_ARRAY: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - Object* o = reinterpret_cast<Object*>(GetVReg(m, reg, kReferenceVReg)); + mirror::Object* o = reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg)); VLOG(jdwp) << "get array local " << reg << " = " << o; if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) { LOG(FATAL) << "Register " << reg << " expected to hold array: " << o; @@ -2053,7 +2066,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl case JDWP::JT_THREAD_GROUP: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - Object* o = reinterpret_cast<Object*>(GetVReg(m, reg, kReferenceVReg)); + mirror::Object* o = reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg)); VLOG(jdwp) << "get object local " << reg << " = " << o; if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) { LOG(FATAL) << "Register " << reg << " expected to hold object: " << o; @@ -2128,7 +2141,7 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl return true; // Not our frame, carry on. } // TODO: check that the tag is compatible with the actual type of the slot! - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); uint16_t reg = DemangleSlot(slot_, m); switch (tag_) { @@ -2155,7 +2168,7 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl case JDWP::JT_STRING: { CHECK_EQ(width_, sizeof(JDWP::ObjectId)); - Object* o = gRegistry->Get<Object*>(static_cast<JDWP::ObjectId>(value_)); + mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value_)); if (o == kInvalidObject) { UNIMPLEMENTED(FATAL) << "return an error code when given an invalid object to store"; } @@ -2198,8 +2211,8 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl visitor.WalkStack(); } -void Dbg::PostLocationEvent(const AbstractMethod* m, int dex_pc, Object* this_object, int event_flags) { - Class* c = m->GetDeclaringClass(); +void Dbg::PostLocationEvent(const mirror::AbstractMethod* m, int dex_pc, mirror::Object* this_object, int event_flags) { + mirror::Class* c = m->GetDeclaringClass(); JDWP::JdwpLocation location; location.type_tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; @@ -2220,8 +2233,9 @@ void Dbg::PostLocationEvent(const AbstractMethod* m, int dex_pc, Object* this_ob } void Dbg::PostException(Thread* thread, - JDWP::FrameId throw_frame_id, AbstractMethod* throw_method, uint32_t throw_dex_pc, - AbstractMethod* catch_method, uint32_t catch_dex_pc, Throwable* exception) { + JDWP::FrameId throw_frame_id, mirror::AbstractMethod* throw_method, + uint32_t throw_dex_pc, mirror::AbstractMethod* catch_method, + uint32_t catch_dex_pc, mirror::Throwable* exception) { if (!IsDebuggerActive()) { return; } @@ -2252,7 +2266,7 @@ void Dbg::PostException(Thread* thread, gJdwpState->PostException(&throw_location, exception_id, exception_class_id, &catch_location, this_id); } -void Dbg::PostClassPrepare(Class* c) { +void Dbg::PostClassPrepare(mirror::Class* c) { if (!IsDebuggerActive()) { return; } @@ -2271,7 +2285,7 @@ void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self) { } size_t frame_id; - AbstractMethod* m = self->GetCurrentMethod(NULL, &frame_id); + mirror::AbstractMethod* m = self->GetCurrentMethod(NULL, &frame_id); //LOG(INFO) << "UpdateDebugger " << PrettyMethod(m) << "@" << dex_pc << " frame " << frame_id; if (dex_pc == -1) { @@ -2375,14 +2389,14 @@ void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self) { void Dbg::WatchLocation(const JDWP::JdwpLocation* location) { MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); - AbstractMethod* m = FromMethodId(location->method_id); + mirror::AbstractMethod* m = FromMethodId(location->method_id); gBreakpoints.push_back(Breakpoint(m, location->dex_pc)); VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1]; } void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) { MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); - AbstractMethod* m = FromMethodId(location->method_id); + mirror::AbstractMethod* m = FromMethodId(location->method_id); for (size_t i = 0; i < gBreakpoints.size(); ++i) { if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == location->dex_pc) { VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i]; @@ -2428,11 +2442,11 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize // annotalysis. bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { Locks::breakpoint_lock_->AssertHeld(Thread::Current()); - const AbstractMethod* m = GetMethod(); + const mirror::AbstractMethod* m = GetMethod(); if (!m->IsRuntimeMethod()) { ++gSingleStepControl.stack_depth; if (gSingleStepControl.method == NULL) { - const DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache(); + const mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache(); gSingleStepControl.method = m; gSingleStepControl.line_number = -1; if (dex_cache != NULL) { @@ -2497,7 +2511,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize uint32_t last_pc; }; gSingleStepControl.dex_pcs.clear(); - const AbstractMethod* m = gSingleStepControl.method; + const mirror::AbstractMethod* m = gSingleStepControl.method; if (m->IsNative()) { gSingleStepControl.line_number = -1; } else { @@ -2618,23 +2632,23 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec } JDWP::JdwpError status; - Object* receiver = gRegistry->Get<Object*>(object_id); + mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id); if (receiver == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - Object* thread = gRegistry->Get<Object*>(thread_id); + mirror::Object* thread = gRegistry->Get<mirror::Object*>(thread_id); if (thread == kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } // TODO: check that 'thread' is actually a java.lang.Thread! - Class* c = DecodeClass(class_id, status); + mirror::Class* c = DecodeClass(class_id, status); if (c == NULL) { return status; } - AbstractMethod* m = FromMethodId(method_id); + mirror::AbstractMethod* m = FromMethodId(method_id); if (m->IsStatic() != (receiver == NULL)) { return JDWP::ERR_INVALID_METHODID; } @@ -2739,13 +2753,13 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { // We can be called while an exception is pending. We need // to preserve that across the method invocation. - SirtRef<Throwable> old_exception(soa.Self(), soa.Self()->GetException()); + SirtRef<mirror::Throwable> old_exception(soa.Self(), soa.Self()->GetException()); soa.Self()->ClearException(); // Translate the method through the vtable, unless the debugger wants to suppress it. - AbstractMethod* m = pReq->method_; + mirror::AbstractMethod* m = pReq->method_; if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) { - AbstractMethod* actual_method = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_); + mirror::AbstractMethod* actual_method = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_); if (actual_method != m) { VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m) << " to " << PrettyMethod(actual_method); m = actual_method; @@ -2764,7 +2778,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { pReq->exception = gRegistry->Add(soa.Self()->GetException()); pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty()); if (pReq->exception != 0) { - Object* exc = soa.Self()->GetException(); + mirror::Object* exc = soa.Self()->GetException(); VLOG(jdwp) << " JDWP invocation returning with exception=" << exc << " " << PrettyTypeOf(exc); soa.Self()->ClearException(); pReq->result_value.SetJ(0); @@ -2801,7 +2815,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { * throwing exceptions) we really want to do the registration late. */ void Dbg::RegisterObjectId(JDWP::ObjectId id) { - gRegistry->Add(reinterpret_cast<Object*>(id)); + gRegistry->Add(reinterpret_cast<mirror::Object*>(id)); } /* @@ -2949,7 +2963,7 @@ void Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) { } else { CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type; ScopedObjectAccessUnchecked soa(Thread::Current()); - SirtRef<String> name(soa.Self(), t->GetThreadName(soa)); + SirtRef<mirror::String> name(soa.Self(), t->GetThreadName(soa)); size_t char_count = (name.get() != NULL) ? name->GetLength() : 0; const jchar* chars = (name.get() != NULL) ? name->GetCharArray()->GetData() : NULL; @@ -3239,7 +3253,7 @@ class HeapChunkContext { Flush(); } } - const Object *obj = (const Object *)start; + const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(start); // Determine the type of this chunk. // OLD-TODO: if context.merge, see if this chunk is different from the last chunk. @@ -3282,7 +3296,7 @@ class HeapChunkContext { *p_++ = length - 1; } - uint8_t ExamineObject(const Object* o, bool is_native_heap) + uint8_t ExamineObject(const mirror::Object* o, bool is_native_heap) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { if (o == NULL) { return HPSG_STATE(SOLIDITY_FREE, 0); @@ -3300,7 +3314,7 @@ class HeapChunkContext { return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE); } - Class* c = o->GetClass(); + mirror::Class* c = o->GetClass(); if (c == NULL) { // The object was probably just created but hasn't been initialized yet. return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); @@ -3416,7 +3430,7 @@ struct AllocRecordStackVisitor : public StackVisitor { if (depth >= kMaxAllocRecordStackDepth) { return false; } - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (!m->IsRuntimeMethod()) { record->stack[depth].method = m; record->stack[depth].dex_pc = GetDexPc(); @@ -3437,7 +3451,7 @@ struct AllocRecordStackVisitor : public StackVisitor { size_t depth; }; -void Dbg::RecordAllocation(Class* type, size_t byte_count) { +void Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { Thread* self = Thread::Current(); CHECK(self != NULL); @@ -3499,7 +3513,7 @@ void Dbg::DumpRecentAllocations() { << PrettyClass(record->type); for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) { - const AbstractMethod* m = record->stack[stack_frame].method; + const mirror::AbstractMethod* m = record->stack[stack_frame].method; if (m == NULL) { break; } @@ -3619,7 +3633,7 @@ jbyteArray Dbg::GetRecentAllocations() { MethodHelper mh; for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) { - AbstractMethod* m = record->stack[i].method; + mirror::AbstractMethod* m = record->stack[i].method; if (m != NULL) { mh.ChangeMethod(m); class_names.Add(mh.GetDeclaringClassDescriptor()); diff --git a/src/debugger.h b/src/debugger.h index b34a401ceb..a7963496cc 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -26,10 +26,17 @@ #include <string> #include "jdwp/jdwp.h" -#include "object.h" +#include "jni.h" +#include "jvalue.h" +#include "root_visitor.h" namespace art { - +namespace mirror { +class AbstractMethod; +class Class; +class Object; +class Throwable; +} // namespace mirror struct AllocRecord; class Thread; @@ -53,10 +60,10 @@ struct DebugInvokeReq { bool invoke_needed_; /* request */ - Object* receiver_; /* not used for ClassType.InvokeMethod */ - Object* thread_; - Class* class_; - AbstractMethod* method_; + mirror::Object* receiver_; /* not used for ClassType.InvokeMethod */ + mirror::Object* thread_; + mirror::Class* class_; + mirror::AbstractMethod* method_; uint32_t arg_count_; uint64_t* arg_values_; /* will be NULL if arg_count_ == 0 */ uint32_t options_; @@ -118,7 +125,7 @@ class Dbg { static void Exit(int status); - static void VisitRoots(Heap::RootVisitor* visitor, void* arg); + static void VisitRoots(RootVisitor* visitor, void* arg); /* * Class, Object, Array @@ -311,17 +318,19 @@ class Dbg { kMethodEntry = 0x04, kMethodExit = 0x08, }; - static void PostLocationEvent(const AbstractMethod* method, int pcOffset, Object* thisPtr, int eventFlags) + static void PostLocationEvent(const mirror::AbstractMethod* method, int pcOffset, + mirror::Object* thisPtr, int eventFlags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void PostException(Thread* thread, JDWP::FrameId throw_frame_id, AbstractMethod* throw_method, - uint32_t throw_dex_pc, AbstractMethod* catch_method, uint32_t catch_dex_pc, - Throwable* exception) + static void PostException(Thread* thread, JDWP::FrameId throw_frame_id, + mirror::AbstractMethod* throw_method, + uint32_t throw_dex_pc, mirror::AbstractMethod* catch_method, + uint32_t catch_dex_pc, mirror::Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void PostThreadStart(Thread* t) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void PostThreadDeath(Thread* t) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void PostClassPrepare(Class* c) + static void PostClassPrepare(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void UpdateDebugger(int32_t dex_pc, Thread* self) @@ -373,12 +382,11 @@ class Dbg { /* * Recent allocation tracking support. */ - static void RecordAllocation(Class* type, size_t byte_count) + static void RecordAllocation(mirror::Class* type, size_t byte_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void SetAllocTrackingEnabled(bool enabled); static inline bool IsAllocTrackingEnabled() { return recent_allocation_records_ != NULL; } - static jbyteArray GetRecentAllocations() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static jbyteArray GetRecentAllocations() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DumpRecentAllocations(); enum HpifWhen { diff --git a/src/dex2oat.cc b/src/dex2oat.cc index a2d35e48ad..bc38bdcfc9 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -27,10 +27,14 @@ #include "base/stringpiece.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" -#include "class_loader.h" #include "compiler.h" #include "image_writer.h" #include "leb128.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "oat_writer.h" #include "object_utils.h" #include "os.h" @@ -161,7 +165,7 @@ class Dex2Oat { continue; } std::string descriptor(DotToDescriptor(dot.c_str())); - SirtRef<Class> klass(self, class_linker->FindSystemClass(descriptor.c_str())); + SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(descriptor.c_str())); if (klass.get() == NULL) { LOG(WARNING) << "Failed to find class " << descriptor; Thread::Current()->ClearException(); @@ -173,7 +177,7 @@ class Dex2Oat { // exceptions are resolved by the verifier when there is a catch block in an interested method. // Do this here so that exception classes appear to have been specified image classes. std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types; - SirtRef<Class> java_lang_Throwable(self, + SirtRef<mirror::Class> java_lang_Throwable(self, class_linker->FindSystemClass("Ljava/lang/Throwable;")); do { unresolved_exception_types.clear(); @@ -185,10 +189,10 @@ class Dex2Oat { it != end; ++it) { uint16_t exception_type_idx = it->first; const DexFile* dex_file = it->second; - DexCache* dex_cache = class_linker->FindDexCache(*dex_file); - ClassLoader* class_loader = NULL; - SirtRef<Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx, - dex_cache, class_loader)); + mirror::DexCache* dex_cache = class_linker->FindDexCache(*dex_file); + mirror:: ClassLoader* class_loader = NULL; + SirtRef<mirror::Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx, + dex_cache, class_loader)); if (klass.get() == NULL) { const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx); const char* descriptor = dex_file->GetTypeDescriptor(type_id); @@ -404,25 +408,25 @@ class Dex2Oat { } } - static bool ResolveCatchBlockExceptionsClassVisitor(Class* c, void* arg) + static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::set<std::pair<uint16_t, const DexFile*> >* exceptions_to_resolve = reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg); MethodHelper mh; for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { - AbstractMethod* m = c->GetVirtualMethod(i); + mirror::AbstractMethod* m = c->GetVirtualMethod(i); mh.ChangeMethod(m); ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); } for (size_t i = 0; i < c->NumDirectMethods(); ++i) { - AbstractMethod* m = c->GetDirectMethod(i); + mirror::AbstractMethod* m = c->GetDirectMethod(i); mh.ChangeMethod(m); ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); } return true; } - static bool RecordImageClassesVisitor(Class* klass, void* arg) + static bool RecordImageClassesVisitor(mirror::Class* klass, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::set<std::string>* image_classes = reinterpret_cast<std::set<std::string>*>(arg); if (klass->IsArrayClass() || klass->IsPrimitive()) { diff --git a/src/dex_file.cc b/src/dex_file.cc index 73986162b0..e67e767dba 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -30,7 +30,10 @@ #include "dex_file_verifier.h" #include "globals.h" #include "leb128.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/field.h" +#include "mirror/field-inl.h" +#include "mirror/string.h" #include "os.h" #include "safe_map.h" #include "thread.h" @@ -94,6 +97,14 @@ const DexFile* DexFile::Open(const std::string& filename, return DexFile::OpenFile(filename, location, true); } +int DexFile::GetPermissions() const { + if (mem_map_.get() == NULL) { + return 0; + } else { + return mem_map_->GetProtect(); + } +} + const DexFile* DexFile::OpenFile(const std::string& filename, const std::string& location, bool verify) { @@ -146,7 +157,6 @@ const DexFile* DexFile::OpenFile(const std::string& filename, const char* DexFile::kClassesDex = "classes.dex"; -// Open classes.dex from within a .zip, .jar, .apk, ... const DexFile* DexFile::OpenZip(const std::string& filename, const std::string& location) { UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename)); @@ -157,6 +167,16 @@ const DexFile* DexFile::OpenZip(const std::string& filename, return DexFile::Open(*zip_archive.get(), location); } +const DexFile* DexFile::OpenMemory(const std::string& location, + uint32_t location_checksum, + MemMap* mem_map) { + return OpenMemory(mem_map->Begin(), + mem_map->Size(), + location, + location_checksum, + mem_map); +} + const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) { CHECK(!location.empty()); UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex)); @@ -584,7 +604,7 @@ std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_ return descriptor; } -int32_t DexFile::GetLineNumFromPC(const AbstractMethod* method, uint32_t rel_pc) const { +int32_t DexFile::GetLineNumFromPC(const mirror::AbstractMethod* method, uint32_t rel_pc) const { // For native method, lineno should be -2 to indicate it is native. Note that // "line number == -2" is how libcore tells from StackTraceElement. if (method->GetCodeItemOffset() == 0) { @@ -601,6 +621,12 @@ int32_t DexFile::GetLineNumFromPC(const AbstractMethod* method, uint32_t rel_pc) return context.line_num_; } +const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) { + const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_]; + return reinterpret_cast<const TryItem*> + (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset; +} + int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size, uint32_t address) { // Note: Signed type is important for max and min. @@ -900,8 +926,8 @@ static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right } EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file, - DexCache* dex_cache, - ClassLoader* class_loader, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, ClassLinker* linker, const DexFile::ClassDef& class_def) : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker), @@ -976,7 +1002,7 @@ void EncodedStaticFieldValueIterator::Next() { ptr_ += width; } -void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const { +void EncodedStaticFieldValueIterator::ReadValueToField(mirror::Field* field) const { switch (type_) { case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); break; case kByte: field->SetByte(field->GetDeclaringClass(), jval_.b); break; @@ -988,12 +1014,12 @@ void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const { case kDouble: field->SetDouble(field->GetDeclaringClass(), jval_.d); break; case kNull: field->SetObject(field->GetDeclaringClass(), NULL); break; case kString: { - String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_); + mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_); field->SetObject(field->GetDeclaringClass(), resolved); break; } case kType: { - Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_); + mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_); field->SetObject(field->GetDeclaringClass(), resolved); break; } diff --git a/src/dex_file.h b/src/dex_file.h index 184d9507db..14b4ba0b68 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -29,10 +29,16 @@ #include "modifiers.h" #include "safe_map.h" #include "UniquePtr.h" -#include "utils.h" namespace art { +namespace mirror { +class AbstractMethod; +class ClassLoader; +class DexCache; +class Field; +} // namespace mirror +class ClassLinker; class ZipArchive; // TODO: move all of the macro functionality into the DexCache class. @@ -675,11 +681,7 @@ class DexFile { } } - static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset) { - const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_]; - return reinterpret_cast<const TryItem*> - (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset; - } + static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset); // Get the base of the encoded data for the given DexCode. static const byte* GetCatchHandlerData(const CodeItem& code_item, uint32_t offset) { @@ -775,7 +777,7 @@ class DexFile { // Returns -2 for native methods (as expected in exception traces). // // This is used by runtime; therefore use art::Method not art::DexFile::Method. - int32_t GetLineNumFromPC(const AbstractMethod* method, uint32_t rel_pc) const + int32_t GetLineNumFromPC(const mirror::AbstractMethod* method, uint32_t rel_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, @@ -790,13 +792,7 @@ class DexFile { } } - int GetPermissions() const { - if (mem_map_.get() == NULL) { - return 0; - } else { - return mem_map_->GetProtect(); - } - } + int GetPermissions() const; private: // Opens a .dex file @@ -811,13 +807,7 @@ class DexFile { // Opens a .dex file at the given address backed by a MemMap static const DexFile* OpenMemory(const std::string& location, uint32_t location_checksum, - MemMap* mem_map) { - return OpenMemory(mem_map->Begin(), - mem_map->Size(), - location, - location_checksum, - mem_map); - } + MemMap* mem_map); // Opens a .dex file at the given address, optionally backed by a MemMap static const DexFile* OpenMemory(const byte* dex_file, @@ -1116,19 +1106,14 @@ class ClassDataItemIterator { DISALLOW_IMPLICIT_CONSTRUCTORS(ClassDataItemIterator); }; -class ClassLinker; -class ClassLoader; -class DexCache; -class Field; - class EncodedStaticFieldValueIterator { public: - EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache, ClassLoader* class_loader, + EncodedStaticFieldValueIterator(const DexFile& dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, ClassLinker* linker, const DexFile::ClassDef& class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void ReadValueToField(Field* field) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void ReadValueToField(mirror::Field* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasNext() { return pos_ < array_size_; } @@ -1158,14 +1143,14 @@ class EncodedStaticFieldValueIterator { static const byte kEncodedValueArgShift = 5; const DexFile& dex_file_; - DexCache* dex_cache_; // dex cache to resolve literal objects - ClassLoader* class_loader_; // ClassLoader to resolve types - ClassLinker* linker_; // linker to resolve literal objects - size_t array_size_; // size of array - size_t pos_; // current position - const byte* ptr_; // pointer into encoded data array - ValueType type_; // type of current encoded value - jvalue jval_; // value of current encoded value + mirror::DexCache* dex_cache_; // Dex cache to resolve literal objects. + mirror::ClassLoader* class_loader_; // ClassLoader to resolve types. + ClassLinker* linker_; // Linker to resolve literal objects. + size_t array_size_; // Size of array. + size_t pos_; // Current position. + const byte* ptr_; // Pointer into encoded data array. + ValueType type_; // Type of current encoded value. + jvalue jval_; // Value of current encoded value. DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator); }; std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code); diff --git a/src/dex_file_verifier.cc b/src/dex_file_verifier.cc index 83ef31aada..2f9054e414 100644 --- a/src/dex_file_verifier.cc +++ b/src/dex_file_verifier.cc @@ -18,9 +18,10 @@ #include "base/stringprintf.h" #include "leb128.h" -#include "object.h" #include "safe_map.h" #include "UniquePtr.h" +#include "utf.h" +#include "utils.h" #include "zip_archive.h" namespace art { diff --git a/src/dex_instruction.cc b/src/dex_instruction.cc index d3aa2389ef..55f6eca326 100644 --- a/src/dex_instruction.cc +++ b/src/dex_instruction.cc @@ -17,6 +17,7 @@ #include "dex_instruction.h" #include "dex_file.h" +#include "utils.h" #include <iomanip> namespace art { diff --git a/src/exception_test.cc b/src/exception_test.cc index 58e6533058..240bf957db 100644 --- a/src/exception_test.cc +++ b/src/exception_test.cc @@ -18,6 +18,8 @@ #include "common_test.h" #include "dex_file.h" #include "gtest/gtest.h" +#include "mirror/object_array-inl.h" +#include "mirror/stack_trace_element.h" #include "runtime.h" #include "scoped_thread_state_change.h" #include "sirt_ref.h" @@ -32,8 +34,8 @@ class ExceptionTest : public CommonTest { CommonTest::SetUp(); ScopedObjectAccess soa(Thread::Current()); - SirtRef<ClassLoader> class_loader(soa.Self(), - soa.Decode<ClassLoader*>(LoadDex("ExceptionHandle"))); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle"))); my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader.get()); ASSERT_TRUE(my_klass_ != NULL); class_linker_->EnsureInitialized(my_klass_, false, true); @@ -90,11 +92,11 @@ class ExceptionTest : public CommonTest { std::vector<uint16_t> fake_vmap_table_data_; std::vector<uint8_t> fake_gc_map_; - AbstractMethod* method_f_; - AbstractMethod* method_g_; + mirror::AbstractMethod* method_f_; + mirror::AbstractMethod* method_g_; private: - Class* my_klass_; + mirror::Class* my_klass_; }; TEST_F(ExceptionTest, FindCatchHandler) { @@ -193,8 +195,8 @@ TEST_F(ExceptionTest, StackTraceElement) { ASSERT_TRUE(internal != NULL); jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal); ASSERT_TRUE(ste_array != NULL); - ObjectArray<StackTraceElement>* trace_array = - soa.Decode<ObjectArray<StackTraceElement>*>(ste_array); + mirror::ObjectArray<mirror::StackTraceElement>* trace_array = + soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array); ASSERT_TRUE(trace_array != NULL); ASSERT_TRUE(trace_array->Get(0) != NULL); diff --git a/src/gc/atomic_stack.h b/src/gc/atomic_stack.h index cd1781dcb9..0197bce992 100644 --- a/src/gc/atomic_stack.h +++ b/src/gc/atomic_stack.h @@ -101,11 +101,11 @@ class AtomicStack { } T* Begin() { - return const_cast<Object**>(begin_ + front_index_); + return const_cast<mirror::Object**>(begin_ + front_index_); } T* End() { - return const_cast<Object**>(begin_ + back_index_); + return const_cast<mirror::Object**>(begin_ + back_index_); } size_t Capacity() const { @@ -159,6 +159,8 @@ class AtomicStack { DISALLOW_COPY_AND_ASSIGN(AtomicStack); }; +typedef AtomicStack<mirror::Object*> ObjectStack; + } // namespace art #endif // ART_SRC_MARK_STACK_H_ diff --git a/src/gc/card_table-inl.h b/src/gc/card_table-inl.h new file mode 100644 index 0000000000..13590b70a9 --- /dev/null +++ b/src/gc/card_table-inl.h @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_CARDTABLE_INL_H_ +#define ART_SRC_GC_CARDTABLE_INL_H_ + +#include "base/logging.h" +#include "card_table.h" +#include "cutils/atomic-inline.h" +#include "space_bitmap.h" +#include "utils.h" + +namespace art { + +static inline bool byte_cas(byte old_value, byte new_value, byte* address) { + // Little endian means most significant byte is on the left. + const size_t shift = reinterpret_cast<uintptr_t>(address) % sizeof(uintptr_t); + // Align the address down. + address -= shift; + int32_t* word_address = reinterpret_cast<int32_t*>(address); + // Word with the byte we are trying to cas cleared. + const int32_t cur_word = *word_address & ~(0xFF << shift); + const int32_t old_word = cur_word | (static_cast<int32_t>(old_value) << shift); + const int32_t new_word = cur_word | (static_cast<int32_t>(new_value) << shift); + bool success = android_atomic_cas(old_word, new_word, word_address) == 0; + return success; +} + +template <typename Visitor, typename FingerVisitor> +inline void CardTable::Scan(SpaceBitmap* bitmap, byte* scan_begin, byte* scan_end, + const Visitor& visitor, const FingerVisitor& finger_visitor, + const byte minimum_age) const { + DCHECK(bitmap->HasAddress(scan_begin)); + DCHECK(bitmap->HasAddress(scan_end - 1)); // scan_end is the byte after the last byte we scan. + byte* card_cur = CardFromAddr(scan_begin); + byte* card_end = CardFromAddr(scan_end); + CheckCardValid(card_cur); + CheckCardValid(card_end); + + // Handle any unaligned cards at the start. + while (!IsAligned<sizeof(word)>(card_cur) && card_cur < card_end) { + if (*card_cur >= minimum_age) { + uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); + uintptr_t end = start + kCardSize; + bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); + } + ++card_cur; + } + + byte* aligned_end = card_end - + (reinterpret_cast<uintptr_t>(card_end) & (sizeof(uintptr_t) - 1)); + + // Now we have the words, we can send these to be processed in parallel. + uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); + uintptr_t* word_end = reinterpret_cast<uintptr_t*>(aligned_end); + + // TODO: Parallelize + while (word_cur < word_end) { + // Find the first dirty card. + while (*word_cur == 0 && word_cur < word_end) { + word_cur++; + } + if (word_cur >= word_end) { + break; + } + uintptr_t start_word = *word_cur; + for (size_t i = 0; i < sizeof(uintptr_t); ++i) { + if ((start_word & 0xFF) >= minimum_age) { + byte* card = reinterpret_cast<byte*>(word_cur) + i; + const byte card_byte = *card; + DCHECK(card_byte == (start_word & 0xFF) || card_byte == kCardDirty) + << "card " << static_cast<size_t>(card_byte) << " word " << (start_word & 0xFF); + uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card)); + uintptr_t end = start + kCardSize; + bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); + } + start_word >>= 8; + } + ++word_cur; + } + + // Handle any unaligned cards at the end. + card_cur = reinterpret_cast<byte*>(word_end); + while (card_cur < card_end) { + if (*card_cur >= minimum_age) { + uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); + uintptr_t end = start + kCardSize; + bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); + } + ++card_cur; + } +} + +/* + * Visitor is expected to take in a card and return the new value. When a value is modified, the + * modify visitor is called. + * visitor: The visitor which modifies the cards. Returns the new value for a card given an old + * value. + * modified: Whenever the visitor modifies a card, this visitor is called on the card. Enables + * us to know which cards got cleared. + */ +template <typename Visitor, typename ModifiedVisitor> +inline void CardTable::ModifyCardsAtomic(byte* scan_begin, byte* scan_end, const Visitor& visitor, + const ModifiedVisitor& modified) { + byte* card_cur = CardFromAddr(scan_begin); + byte* card_end = CardFromAddr(scan_end); + CheckCardValid(card_cur); + CheckCardValid(card_end); + + // Handle any unaligned cards at the start. + while (!IsAligned<sizeof(word)>(card_cur) && card_cur < card_end) { + byte expected, new_value; + do { + expected = *card_cur; + new_value = visitor(expected); + } while (expected != new_value && UNLIKELY(!byte_cas(expected, new_value, card_cur))); + if (expected != new_value) { + modified(card_cur, expected, new_value); + } + ++card_cur; + } + + // Handle unaligned cards at the end. + while (!IsAligned<sizeof(word)>(card_end) && card_end > card_cur) { + --card_end; + byte expected, new_value; + do { + expected = *card_end; + new_value = visitor(expected); + } while (expected != new_value && UNLIKELY(!byte_cas(expected, new_value, card_end))); + if (expected != new_value) { + modified(card_cur, expected, new_value); + } + } + + // Now we have the words, we can process words in parallel. + uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); + uintptr_t* word_end = reinterpret_cast<uintptr_t*>(card_end); + uintptr_t expected_word; + uintptr_t new_word; + + // TODO: Parallelize. + while (word_cur < word_end) { + while ((expected_word = *word_cur) != 0) { + new_word = + (visitor((expected_word >> 0) & 0xFF) << 0) | + (visitor((expected_word >> 8) & 0xFF) << 8) | + (visitor((expected_word >> 16) & 0xFF) << 16) | + (visitor((expected_word >> 24) & 0xFF) << 24); + if (new_word == expected_word) { + // No need to do a cas. + break; + } + if (LIKELY(android_atomic_cas(expected_word, new_word, + reinterpret_cast<int32_t*>(word_cur)) == 0)) { + for (size_t i = 0; i < sizeof(uintptr_t); ++i) { + const byte expected_byte = (expected_word >> (8 * i)) & 0xFF; + const byte new_byte = (new_word >> (8 * i)) & 0xFF; + if (expected_byte != new_byte) { + modified(reinterpret_cast<byte*>(word_cur) + i, expected_byte, new_byte); + } + } + break; + } + } + ++word_cur; + } +} + +inline void* CardTable::AddrFromCard(const byte *card_addr) const { + DCHECK(IsValidCard(card_addr)) + << " card_addr: " << reinterpret_cast<const void*>(card_addr) + << " begin: " << reinterpret_cast<void*>(mem_map_->Begin() + offset_) + << " end: " << reinterpret_cast<void*>(mem_map_->End()); + uintptr_t offset = card_addr - biased_begin_; + return reinterpret_cast<void*>(offset << kCardShift); +} + +inline byte* CardTable::CardFromAddr(const void *addr) const { + byte *card_addr = biased_begin_ + (reinterpret_cast<uintptr_t>(addr) >> kCardShift); + // Sanity check the caller was asking for address covered by the card table + DCHECK(IsValidCard(card_addr)) << "addr: " << addr + << " card_addr: " << reinterpret_cast<void*>(card_addr); + return card_addr; +} + +inline void CardTable::CheckCardValid(byte* card) const { + DCHECK(IsValidCard(card)) + << " card_addr: " << reinterpret_cast<const void*>(card) + << " begin: " << reinterpret_cast<void*>(mem_map_->Begin() + offset_) + << " end: " << reinterpret_cast<void*>(mem_map_->End()); +} + +} // namespace art + +#endif // ART_SRC_GC_CARDTABLE_INL_H_ diff --git a/src/gc/card_table.cc b/src/gc/card_table.cc index f27777bfd8..4331270131 100644 --- a/src/gc/card_table.cc +++ b/src/gc/card_table.cc @@ -19,6 +19,7 @@ #include <dynamic_annotations.h> #include "base/logging.h" +#include "gc/card_table-inl.h" #include "heap.h" #include "heap_bitmap.h" #include "runtime.h" diff --git a/src/gc/card_table.h b/src/gc/card_table.h index 8f1bc922f6..842fcc3aa2 100644 --- a/src/gc/card_table.h +++ b/src/gc/card_table.h @@ -17,19 +17,18 @@ #ifndef ART_SRC_GC_CARDTABLE_H_ #define ART_SRC_GC_CARDTABLE_H_ -#include "base/logging.h" #include "globals.h" +#include "locks.h" #include "mem_map.h" -#include "space_bitmap.h" #include "UniquePtr.h" -#include "utils.h" namespace art { - +namespace mirror { +class Object; +} // namespace mirror class Heap; class ContinuousSpace; class SpaceBitmap; -class Object; // Maintain a card table from the the write barrier. All writes of // non-NULL values to heap addresses should go through an entry in @@ -50,12 +49,12 @@ class CardTable { } // Is the object on a dirty card? - bool IsDirty(const Object* obj) const { + bool IsDirty(const mirror::Object* obj) const { return GetCard(obj) == kCardDirty; } // Return the state of the card at an address. - byte GetCard(const Object* obj) const { + byte GetCard(const mirror::Object* obj) const { return *CardFromAddr(obj); } @@ -88,71 +87,7 @@ class CardTable { */ template <typename Visitor, typename ModifiedVisitor> void ModifyCardsAtomic(byte* scan_begin, byte* scan_end, const Visitor& visitor, - const ModifiedVisitor& modified = VoidFunctor()) { - byte* card_cur = CardFromAddr(scan_begin); - byte* card_end = CardFromAddr(scan_end); - CheckCardValid(card_cur); - CheckCardValid(card_end); - - // Handle any unaligned cards at the start. - while (!IsAligned<sizeof(word)>(card_cur) && card_cur < card_end) { - byte expected, new_value; - do { - expected = *card_cur; - new_value = visitor(expected); - } while (expected != new_value && UNLIKELY(byte_cas(expected, new_value, card_cur) != 0)); - if (expected != new_value) { - modified(card_cur, expected, new_value); - } - ++card_cur; - } - - // Handle unaligned cards at the end. - while (!IsAligned<sizeof(word)>(card_end) && card_end > card_cur) { - --card_end; - byte expected, new_value; - do { - expected = *card_end; - new_value = visitor(expected); - } while (expected != new_value && UNLIKELY(byte_cas(expected, new_value, card_end) != 0)); - if (expected != new_value) { - modified(card_cur, expected, new_value); - } - } - - // Now we have the words, we can process words in parallel. - uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); - uintptr_t* word_end = reinterpret_cast<uintptr_t*>(card_end); - uintptr_t expected_word; - uintptr_t new_word; - - // TODO: Parallelize. - while (word_cur < word_end) { - while ((expected_word = *word_cur) != 0) { - new_word = - (visitor((expected_word >> 0) & 0xFF) << 0) | - (visitor((expected_word >> 8) & 0xFF) << 8) | - (visitor((expected_word >> 16) & 0xFF) << 16) | - (visitor((expected_word >> 24) & 0xFF) << 24); - if (new_word == expected_word) { - // No need to do a cas. - break; - } - if (LIKELY(android_atomic_cas(expected_word, new_word, - reinterpret_cast<int32_t*>(word_cur)) == 0)) { - for (size_t i = 0; i < sizeof(uintptr_t); ++i) { - const byte expected_byte = (expected_word >> (8 * i)) & 0xFF; - const byte new_byte = (new_word >> (8 * i)) & 0xFF; - if (expected_byte != new_byte) { - modified(reinterpret_cast<byte*>(word_cur) + i, expected_byte, new_byte); - } - } - break; - } - } - ++word_cur; - } - } + const ModifiedVisitor& modified); // For every dirty at least minumum age between begin and end invoke the visitor with the // specified argument. @@ -161,67 +96,7 @@ class CardTable { const Visitor& visitor, const FingerVisitor& finger_visitor, const byte minimum_age = kCardDirty) const EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(bitmap->HasAddress(scan_begin)); - DCHECK(bitmap->HasAddress(scan_end - 1)); // scan_end is the byte after the last byte we scan. - byte* card_cur = CardFromAddr(scan_begin); - byte* card_end = CardFromAddr(scan_end); - CheckCardValid(card_cur); - CheckCardValid(card_end); - - // Handle any unaligned cards at the start. - while (!IsAligned<sizeof(word)>(card_cur) && card_cur < card_end) { - if (*card_cur >= minimum_age) { - uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); - uintptr_t end = start + kCardSize; - bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); - } - ++card_cur; - } - - byte* aligned_end = card_end - - (reinterpret_cast<uintptr_t>(card_end) & (sizeof(uintptr_t) - 1)); - - // Now we have the words, we can send these to be processed in parallel. - uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); - uintptr_t* word_end = reinterpret_cast<uintptr_t*>(aligned_end); - - // TODO: Parallelize - while (word_cur < word_end) { - // Find the first dirty card. - while (*word_cur == 0 && word_cur < word_end) { - word_cur++; - } - if (word_cur >= word_end) { - break; - } - uintptr_t start_word = *word_cur; - for (size_t i = 0; i < sizeof(uintptr_t); ++i) { - if ((start_word & 0xFF) >= minimum_age) { - byte* card = reinterpret_cast<byte*>(word_cur) + i; - const byte card_byte = *card; - DCHECK(card_byte == (start_word & 0xFF) || card_byte == kCardDirty) - << "card " << static_cast<size_t>(card_byte) << " word " << (start_word & 0xFF); - uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card)); - uintptr_t end = start + kCardSize; - bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); - } - start_word >>= 8; - } - ++word_cur; - } - - // Handle any unaligned cards at the end. - card_cur = reinterpret_cast<byte*>(word_end); - while (card_cur < card_end) { - if (*card_cur >= minimum_age) { - uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); - uintptr_t end = start + kCardSize; - bitmap->VisitMarkedRange(start, end, visitor, finger_visitor); - } - ++card_cur; - } - } + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Assertion used to check the given address is covered by the card table void CheckAddrIsInCardTable(const byte* addr) const; @@ -233,40 +108,14 @@ class CardTable { void ClearSpaceCards(ContinuousSpace* space); // Returns the first address in the heap which maps to this card. - void* AddrFromCard(const byte *card_addr) const { - DCHECK(IsValidCard(card_addr)) - << " card_addr: " << reinterpret_cast<const void*>(card_addr) - << " begin: " << reinterpret_cast<void*>(mem_map_->Begin() + offset_) - << " end: " << reinterpret_cast<void*>(mem_map_->End()); - uintptr_t offset = card_addr - biased_begin_; - return reinterpret_cast<void*>(offset << kCardShift); - } + void* AddrFromCard(const byte *card_addr) const; // Returns the address of the relevant byte in the card table, given an address on the heap. - byte* CardFromAddr(const void *addr) const { - byte *card_addr = biased_begin_ + (reinterpret_cast<uintptr_t>(addr) >> kCardShift); - // Sanity check the caller was asking for address covered by the card table - DCHECK(IsValidCard(card_addr)) << "addr: " << addr - << " card_addr: " << reinterpret_cast<void*>(card_addr); - return card_addr; - } + byte* CardFromAddr(const void *addr) const; bool AddrIsInCardTable(const void* addr) const; private: - static int byte_cas(byte old_value, byte new_value, byte* address) { - // Little endian means most significant byte is on the left. - const size_t shift = reinterpret_cast<uintptr_t>(address) % sizeof(uintptr_t); - // Align the address down. - address -= shift; - int32_t* word_address = reinterpret_cast<int32_t*>(address); - // Word with the byte we are trying to cas cleared. - const int32_t cur_word = *word_address & ~(0xFF << shift); - const int32_t old_word = cur_word | (static_cast<int32_t>(old_value) << shift); - const int32_t new_word = cur_word | (static_cast<int32_t>(new_value) << shift); - return android_atomic_cas(old_word, new_word, word_address); - } - CardTable(MemMap* begin, byte* biased_begin, size_t offset); // Returns true iff the card table address is within the bounds of the card table. @@ -276,12 +125,7 @@ class CardTable { return card_addr >= begin && card_addr < end; } - void CheckCardValid(byte* card) const { - DCHECK(IsValidCard(card)) - << " card_addr: " << reinterpret_cast<const void*>(card) - << " begin: " << reinterpret_cast<void*>(mem_map_->Begin() + offset_) - << " end: " << reinterpret_cast<void*>(mem_map_->End()); - } + void CheckCardValid(byte* card) const; // Verifies that all gray objects are on a dirty card. void VerifyCardTable(); diff --git a/src/gc/garbage_collector.cc b/src/gc/garbage_collector.cc index bcc7b63e73..fbcdbafd0a 100644 --- a/src/gc/garbage_collector.cc +++ b/src/gc/garbage_collector.cc @@ -15,6 +15,7 @@ */ #include "garbage_collector.h" +#include "thread.h" #include "thread_list.h" namespace art { diff --git a/src/gc/garbage_collector.h b/src/gc/garbage_collector.h index 9ddf45f646..a1014c2c7f 100644 --- a/src/gc/garbage_collector.h +++ b/src/gc/garbage_collector.h @@ -14,11 +14,13 @@ * limitations under the License. */ -#ifndef ART_SRC_GC_GARBAGE_COLLECTR_H_ -#define ART_SRC_GC_GARBAGE_COLLECTR_H_ +#ifndef ART_SRC_GC_GARBAGE_COLLECTOR_H_ +#define ART_SRC_GC_GARBAGE_COLLECTOR_H_ #include "locks.h" -#include "utils.h" + +#include <stdint.h> +#include <vector> namespace art { @@ -56,7 +58,7 @@ class GarbageCollector { void RegisterPause(uint64_t nano_length); protected: - // The initial phase. Done with mutators upaused. + // The initial phase. Done without mutators paused. virtual void InitializePhase() = 0; // Mark all reachable objects, done concurrently. @@ -68,7 +70,7 @@ class GarbageCollector { // Called with mutators running. virtual void ReclaimPhase() = 0; - // Called after the GC is finished. Done with mutators upaused. + // Called after the GC is finished. Done without mutators paused. virtual void FinishPhase() = 0; Heap* heap_; @@ -78,4 +80,4 @@ class GarbageCollector { } // namespace art -#endif // ART_SRC_GC_GARBAGE_COLLECTR_H_ +#endif // ART_SRC_GC_GARBAGE_COLLECTOR_H_ diff --git a/src/gc/gc_type.h b/src/gc/gc_type.h new file mode 100644 index 0000000000..908f038ff2 --- /dev/null +++ b/src/gc/gc_type.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_GC_TYPE_H_ +#define ART_SRC_GC_GC_TYPE_H_ + +namespace art { + +// The ordering of the enum matters, it is used to determine which GCs are run first. +enum GcType { + // No Gc + kGcTypeNone, + // Sticky mark bits "generational" GC. + kGcTypeSticky, + // Partial GC, over only the alloc space. + kGcTypePartial, + // Full GC + kGcTypeFull, + // Number of different Gc types. + kGcTypeMax, +}; +std::ostream& operator<<(std::ostream& os, const GcType& policy); + +} // namespace art + +#endif // ART_SRC_GC_GC_TYPE_H_ diff --git a/src/gc/heap_bitmap-inl.h b/src/gc/heap_bitmap-inl.h new file mode 100644 index 0000000000..281118359b --- /dev/null +++ b/src/gc/heap_bitmap-inl.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_HEAP_BITMAP_INL_H_ +#define ART_SRC_GC_HEAP_BITMAP_INL_H_ + +#include "heap_bitmap.h" + +namespace art { + +template <typename Visitor> +inline void HeapBitmap::Visit(const Visitor& visitor) { + // TODO: C++0x auto + for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); ++it) { + SpaceBitmap* bitmap = *it; + bitmap->VisitMarkedRange(bitmap->HeapBegin(), bitmap->HeapLimit(), visitor, VoidFunctor()); + } + large_objects_->Visit(visitor); +} + +} // namespace art + +#endif // ART_SRC_GC_HEAP_BITMAP_INL_H_ diff --git a/src/gc/heap_bitmap.h b/src/gc/heap_bitmap.h index 42c4166ba0..87e08483f5 100644 --- a/src/gc/heap_bitmap.h +++ b/src/gc/heap_bitmap.h @@ -14,96 +14,91 @@ * limitations under the License. */ -#ifndef ART_SRC_HEAP_BITMAP_H_ -#define ART_SRC_HEAP_BITMAP_H_ +#ifndef ART_SRC_GC_HEAP_BITMAP_H_ +#define ART_SRC_GC_HEAP_BITMAP_H_ +#include "locks.h" #include "space_bitmap.h" namespace art { - class Heap; - class SpaceBitmap; - - class HeapBitmap { - public: - bool Test(const Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { - SpaceBitmap* bitmap = GetSpaceBitmap(obj); - if (LIKELY(bitmap != NULL)) { - return bitmap->Test(obj); - } else { - return large_objects_->Test(obj); - } +class Heap; + +class HeapBitmap { + public: + bool Test(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { + SpaceBitmap* bitmap = GetSpaceBitmap(obj); + if (LIKELY(bitmap != NULL)) { + return bitmap->Test(obj); + } else { + return large_objects_->Test(obj); } - - void Clear(const Object* obj) - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { - SpaceBitmap* bitmap = GetSpaceBitmap(obj); - if (LIKELY(bitmap != NULL)) { - bitmap->Clear(obj); - } else { - large_objects_->Clear(obj); - } + } + + void Clear(const mirror::Object* obj) + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { + SpaceBitmap* bitmap = GetSpaceBitmap(obj); + if (LIKELY(bitmap != NULL)) { + bitmap->Clear(obj); + } else { + large_objects_->Clear(obj); } - - void Set(const Object* obj) - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { - SpaceBitmap* bitmap = GetSpaceBitmap(obj); - if (LIKELY(bitmap != NULL)) { - bitmap->Set(obj); - } else { - large_objects_->Set(obj); - } + } + + void Set(const mirror::Object* obj) + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { + SpaceBitmap* bitmap = GetSpaceBitmap(obj); + if (LIKELY(bitmap != NULL)) { + bitmap->Set(obj); + } else { + large_objects_->Set(obj); } + } - SpaceBitmap* GetSpaceBitmap(const Object* obj) { - // TODO: C++0x auto - for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); ++it) { - if ((*it)->HasAddress(obj)) { - return *it; - } + SpaceBitmap* GetSpaceBitmap(const mirror::Object* obj) { + // TODO: C++0x auto + for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); ++it) { + if ((*it)->HasAddress(obj)) { + return *it; } - return NULL; } + return NULL; + } - void Walk(SpaceBitmap::Callback* callback, void* arg) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + void Walk(SpaceBitmap::Callback* callback, void* arg) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - template <typename Visitor> - void Visit(const Visitor& visitor) - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { - // TODO: C++0x auto - for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); ++it) { - SpaceBitmap* bitmap = *it; - bitmap->VisitMarkedRange(bitmap->HeapBegin(), bitmap->HeapLimit(), visitor, VoidFunctor()); - } - large_objects_->Visit(visitor); - } + template <typename Visitor> + void Visit(const Visitor& visitor) + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Find and replace a bitmap pointer, this is used by for the bitmap swapping in the GC. - void ReplaceBitmap(SpaceBitmap* old_bitmap, SpaceBitmap* new_bitmap) - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + // Find and replace a bitmap pointer, this is used by for the bitmap swapping in the GC. + void ReplaceBitmap(SpaceBitmap* old_bitmap, SpaceBitmap* new_bitmap) + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - HeapBitmap(Heap* heap); + HeapBitmap(Heap* heap); - inline SpaceSetMap* GetLargeObjects() const { - return large_objects_; - } + inline SpaceSetMap* GetLargeObjects() const { + return large_objects_; + } + + void SetLargeObjects(SpaceSetMap* large_objects); - void SetLargeObjects(SpaceSetMap* large_objects); + private: - private: + const Heap* const heap_; - const Heap* const heap_; + void AddSpaceBitmap(SpaceBitmap* bitmap); - void AddSpaceBitmap(SpaceBitmap* bitmap); + typedef std::vector<SpaceBitmap*> Bitmaps; + Bitmaps bitmaps_; - typedef std::vector<SpaceBitmap*> Bitmaps; - Bitmaps bitmaps_; + // Large object sets. + SpaceSetMap* large_objects_; - // Large object sets. - SpaceSetMap* large_objects_; + friend class Heap; +}; - friend class Heap; - }; } // namespace art -#endif // ART_SRC_HEAP_BITMAP_H_ +#endif // ART_SRC_GC_HEAP_BITMAP_H_ diff --git a/src/gc/large_object_space.cc b/src/gc/large_object_space.cc index 1b93e5d570..69320faffd 100644 --- a/src/gc/large_object_space.cc +++ b/src/gc/large_object_space.cc @@ -22,6 +22,7 @@ #include "image.h" #include "os.h" #include "space_bitmap.h" +#include "thread.h" #include "utils.h" namespace art { @@ -58,13 +59,13 @@ LargeObjectMapSpace* LargeObjectMapSpace::Create(const std::string& name) { return new LargeObjectMapSpace(name); } -Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes) { +mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes) { MemMap* mem_map = MemMap::MapAnonymous("allocation", NULL, num_bytes, PROT_READ | PROT_WRITE); if (mem_map == NULL) { return NULL; } MutexLock mu(self, lock_); - Object* obj = reinterpret_cast<Object*>(mem_map->Begin()); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(mem_map->Begin()); large_objects_.push_back(obj); mem_maps_.Put(obj, mem_map); size_t allocation_size = mem_map->Size(); @@ -75,7 +76,7 @@ Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes) { return obj; } -size_t LargeObjectMapSpace::Free(Thread* self, Object* ptr) { +size_t LargeObjectMapSpace::Free(Thread* self, mirror::Object* ptr) { MutexLock mu(self, lock_); MemMaps::iterator found = mem_maps_.find(ptr); CHECK(found != mem_maps_.end()) << "Attempted to free large object which was not live"; @@ -88,14 +89,14 @@ size_t LargeObjectMapSpace::Free(Thread* self, Object* ptr) { return allocation_size; } -size_t LargeObjectMapSpace::AllocationSize(const Object* obj) { +size_t LargeObjectMapSpace::AllocationSize(const mirror::Object* obj) { MutexLock mu(Thread::Current(), lock_); - MemMaps::iterator found = mem_maps_.find(const_cast<Object*>(obj)); + MemMaps::iterator found = mem_maps_.find(const_cast<mirror::Object*>(obj)); CHECK(found != mem_maps_.end()) << "Attempted to get size of a large object which is not live"; return found->second->Size(); } -size_t LargeObjectSpace::FreeList(Thread* self, size_t num_ptrs, Object** ptrs) { +size_t LargeObjectSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) { size_t total = 0; for (size_t i = 0; i < num_ptrs; ++i) { if (kDebugSpaces) { @@ -115,9 +116,9 @@ void LargeObjectMapSpace::Walk(DlMallocSpace::WalkCallback callback, void* arg) } } -bool LargeObjectMapSpace::Contains(const Object* obj) const { +bool LargeObjectMapSpace::Contains(const mirror::Object* obj) const { MutexLock mu(Thread::Current(), lock_); - return mem_maps_.find(const_cast<Object*>(obj)) != mem_maps_.end(); + return mem_maps_.find(const_cast<mirror::Object*>(obj)) != mem_maps_.end(); } FreeListSpace* FreeListSpace::Create(const std::string& name, byte* requested_begin, size_t size) { @@ -191,7 +192,7 @@ void FreeListSpace::Walk(DlMallocSpace::WalkCallback callback, void* arg) { } } -size_t FreeListSpace::Free(Thread* self, Object* obj) { +size_t FreeListSpace::Free(Thread* self, mirror::Object* obj) { MutexLock mu(self, lock_); CHECK(Contains(obj)); // Check adjacent chunks to see if we need to combine. @@ -220,7 +221,7 @@ size_t FreeListSpace::Free(Thread* self, Object* obj) { return allocation_size; } -bool FreeListSpace::Contains(const Object* obj) const { +bool FreeListSpace::Contains(const mirror::Object* obj) const { return mem_map_->HasAddress(obj); } @@ -228,13 +229,13 @@ FreeListSpace::Chunk* FreeListSpace::GetNextChunk(Chunk* chunk) { return chunk + chunk->GetSize() / kAlignment; } -size_t FreeListSpace::AllocationSize(const Object* obj) { - Chunk* chunk = ChunkFromAddr(const_cast<Object*>(obj)); +size_t FreeListSpace::AllocationSize(const mirror::Object* obj) { + Chunk* chunk = ChunkFromAddr(const_cast<mirror::Object*>(obj)); CHECK(!chunk->IsFree()); return chunk->GetSize(); } -Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes) { +mirror::Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes) { MutexLock mu(self, lock_); num_bytes = RoundUp(num_bytes, kAlignment); Chunk temp; @@ -261,7 +262,7 @@ Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes) { total_objects_allocated_++; num_bytes_allocated_ += num_bytes; total_bytes_allocated_ += num_bytes; - return reinterpret_cast<Object*>(addr); + return reinterpret_cast<mirror::Object*>(addr); } void FreeListSpace::Dump(std::ostream& os) const{ diff --git a/src/gc/large_object_space.h b/src/gc/large_object_space.h index 979fce6078..c34dbcc30c 100644 --- a/src/gc/large_object_space.h +++ b/src/gc/large_object_space.h @@ -18,8 +18,13 @@ #define ART_SRC_GC_LARGE_OBJECT_SPACE_H_ #include "space.h" +#include "safe_map.h" + +#include <set> +#include <vector> namespace art { +class SpaceSetMap; class LargeObjectSpace : public DiscontinuousSpace, public AllocSpace { public: @@ -64,7 +69,7 @@ class LargeObjectSpace : public DiscontinuousSpace, public AllocSpace { return total_objects_allocated_; } - size_t FreeList(Thread* self, size_t num_ptrs, Object** ptrs); + size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs); protected: @@ -90,19 +95,19 @@ class LargeObjectMapSpace : public LargeObjectSpace { static LargeObjectMapSpace* Create(const std::string& name); // Return the storage space required by obj. - virtual size_t AllocationSize(const Object* obj); - virtual Object* Alloc(Thread* self, size_t num_bytes); - size_t Free(Thread* self, Object* ptr); + virtual size_t AllocationSize(const mirror::Object* obj); + virtual mirror::Object* Alloc(Thread* self, size_t num_bytes); + size_t Free(Thread* self, mirror::Object* ptr); virtual void Walk(DlMallocSpace::WalkCallback, void* arg); - virtual bool Contains(const Object* obj) const; + virtual bool Contains(const mirror::Object* obj) const; private: LargeObjectMapSpace(const std::string& name); virtual ~LargeObjectMapSpace() {} // Used to ensure mutual exclusion when the allocation spaces data structures are being modified. mutable Mutex lock_; - std::vector<Object*> large_objects_; - typedef SafeMap<Object*, MemMap*> MemMaps; + std::vector<mirror::Object*> large_objects_; + typedef SafeMap<mirror::Object*, MemMap*> MemMaps; MemMaps mem_maps_; }; @@ -111,10 +116,10 @@ class FreeListSpace : public LargeObjectSpace { virtual ~FreeListSpace(); static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity); - size_t AllocationSize(const Object* obj); - Object* Alloc(Thread* self, size_t num_bytes); - size_t Free(Thread* self, Object* obj); - bool Contains(const Object* obj) const; + size_t AllocationSize(const mirror::Object* obj); + mirror::Object* Alloc(Thread* self, size_t num_bytes); + size_t Free(Thread* self, mirror::Object* obj); + bool Contains(const mirror::Object* obj) const; void Walk(DlMallocSpace::WalkCallback callback, void* arg); // Address at which the space begins diff --git a/src/gc/mark_sweep-inl.h b/src/gc/mark_sweep-inl.h new file mode 100644 index 0000000000..726502330b --- /dev/null +++ b/src/gc/mark_sweep-inl.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_MARK_SWEEP_INL_H_ +#define ART_SRC_GC_MARK_SWEEP_INL_H_ + +#include "heap.h" +#include "mirror/class.h" +#include "mirror/field.h" +#include "mirror/object_array.h" + +namespace art { + +template <typename MarkVisitor> +inline void MarkSweep::ScanObjectVisit(const mirror::Object* obj, const MarkVisitor& visitor) { + DCHECK(obj != NULL); + if (kIsDebugBuild && !IsMarked(obj)) { + heap_->DumpSpaces(); + LOG(FATAL) << "Scanning unmarked object " << obj; + } + mirror::Class* klass = obj->GetClass(); + DCHECK(klass != NULL); + if (klass == java_lang_Class_) { + DCHECK_EQ(klass->GetClass(), java_lang_Class_); + if (kCountScannedTypes) { + ++class_count_; + } + VisitClassReferences(klass, obj, visitor); + } else if (klass->IsArrayClass()) { + if (kCountScannedTypes) { + ++array_count_; + } + visitor(obj, klass, mirror::Object::ClassOffset(), false); + if (klass->IsObjectArrayClass()) { + VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor); + } + } else { + if (kCountScannedTypes) { + ++other_count_; + } + VisitOtherReferences(klass, obj, visitor); + if (UNLIKELY(klass->IsReferenceClass())) { + DelayReferenceReferent(const_cast<mirror::Object*>(obj)); + } + } +} + +template <typename Visitor> +inline void MarkSweep::VisitObjectReferences(const mirror::Object* obj, const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, + Locks::mutator_lock_) { + DCHECK(obj != NULL); + DCHECK(obj->GetClass() != NULL); + + mirror::Class* klass = obj->GetClass(); + DCHECK(klass != NULL); + if (klass == mirror::Class::GetJavaLangClass()) { + DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass()); + VisitClassReferences(klass, obj, visitor); + } else { + if (klass->IsArrayClass()) { + visitor(obj, klass, mirror::Object::ClassOffset(), false); + if (klass->IsObjectArrayClass()) { + VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor); + } + } else { + VisitOtherReferences(klass, obj, visitor); + } + } +} + +template <typename Visitor> +inline void MarkSweep::VisitInstanceFieldsReferences(const mirror::Class* klass, + const mirror::Object* obj, + const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { + DCHECK(obj != NULL); + DCHECK(klass != NULL); + VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor); +} + +template <typename Visitor> +inline void MarkSweep::VisitClassReferences(const mirror::Class* klass, const mirror::Object* obj, + const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { + VisitInstanceFieldsReferences(klass, obj, visitor); + VisitStaticFieldsReferences(obj->AsClass(), visitor); +} + +template <typename Visitor> +inline void MarkSweep::VisitStaticFieldsReferences(const mirror::Class* klass, + const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { + DCHECK(klass != NULL); + VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor); +} + +template <typename Visitor> +inline void MarkSweep::VisitFieldsReferences(const mirror::Object* obj, uint32_t ref_offsets, + bool is_static, const Visitor& visitor) { + if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) { + // Found a reference offset bitmap. Mark the specified offsets. + while (ref_offsets != 0) { + size_t right_shift = CLZ(ref_offsets); + MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); + const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false); + visitor(obj, ref, field_offset, is_static); + ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); + } + } else { + // There is no reference offset bitmap. In the non-static case, + // walk up the class inheritance hierarchy and find reference + // offsets the hard way. In the static case, just consider this + // class. + for (const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass(); + klass != NULL; + klass = is_static ? NULL : klass->GetSuperClass()) { + size_t num_reference_fields = (is_static + ? klass->NumReferenceStaticFields() + : klass->NumReferenceInstanceFields()); + for (size_t i = 0; i < num_reference_fields; ++i) { + mirror::Field* field = (is_static ? klass->GetStaticField(i) + : klass->GetInstanceField(i)); + MemberOffset field_offset = field->GetOffset(); + const mirror::Object* ref = obj->GetFieldObject<const mirror::Object*>(field_offset, false); + visitor(obj, ref, field_offset, is_static); + } + } + } +} + +template <typename Visitor> +inline void MarkSweep::VisitObjectArrayReferences(const mirror::ObjectArray<mirror::Object>* array, + const Visitor& visitor) { + const int32_t length = array->GetLength(); + for (int32_t i = 0; i < length; ++i) { + const mirror::Object* element = array->GetWithoutChecks(i); + const size_t width = sizeof(mirror::Object*); + MemberOffset offset = MemberOffset(i * width + mirror::Array::DataOffset(width).Int32Value()); + visitor(array, element, offset, false); + } +} + +} // namespace art + +#endif // ART_SRC_GC_MARK_SWEEP_INL_H_ diff --git a/src/gc/mark_sweep.cc b/src/gc/mark_sweep.cc index 7c52c83292..40102b2036 100644 --- a/src/gc/mark_sweep.cc +++ b/src/gc/mark_sweep.cc @@ -25,22 +25,32 @@ #include "base/logging.h" #include "base/macros.h" #include "card_table.h" -#include "class_loader.h" -#include "dex_cache.h" +#include "card_table-inl.h" #include "heap.h" #include "indirect_reference_table.h" #include "intern_table.h" #include "jni_internal.h" #include "large_object_space.h" #include "monitor.h" -#include "object.h" +#include "mark_sweep-inl.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/dex_cache.h" +#include "mirror/field.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array.h" +#include "mirror/object_array-inl.h" #include "runtime.h" #include "space.h" +#include "space_bitmap-inl.h" #include "timing_logger.h" #include "thread.h" #include "thread_list.h" #include "verifier/method_verifier.h" +using namespace art::mirror; + namespace art { // Performance options. @@ -186,7 +196,7 @@ bool MarkSweep::HandleDirtyObjectsPhase() { timings_.AddSplit("ReMarkRoots"); // Scan dirty objects, this is only required if we are not doing concurrent GC. - RecursiveMarkDirtyObjects(); + RecursiveMarkDirtyObjects(CardTable::kCardDirty); } ProcessReferences(self); @@ -700,7 +710,7 @@ void MarkSweep::ReMarkRoots() { Runtime::Current()->VisitRoots(ReMarkObjectVisitor, this); } -void MarkSweep::SweepJniWeakGlobals(Heap::IsMarkedTester is_marked, void* arg) { +void MarkSweep::SweepJniWeakGlobals(IsMarkedTester is_marked, void* arg) { JavaVMExt* vm = Runtime::Current()->GetJavaVM(); MutexLock mu(Thread::Current(), vm->weak_globals_lock); IndirectReferenceTable* table = &vm->weak_globals; diff --git a/src/gc/mark_sweep.h b/src/gc/mark_sweep.h index 3581d98772..0d43bee795 100644 --- a/src/gc/mark_sweep.h +++ b/src/gc/mark_sweep.h @@ -14,28 +14,38 @@ * limitations under the License. */ -#ifndef ART_SRC_MARK_SWEEP_H_ -#define ART_SRC_MARK_SWEEP_H_ +#ifndef ART_SRC_GC_MARK_SWEEP_H_ +#define ART_SRC_GC_MARK_SWEEP_H_ -#include "atomic_stack.h" +#include "atomic_integer.h" #include "base/macros.h" +#include "base/mutex.h" #include "garbage_collector.h" -#include "heap_bitmap.h" -#include "object.h" +#include "gc_type.h" #include "offsets.h" +#include "root_visitor.h" +#include "timing_logger.h" +#include "UniquePtr.h" namespace art { - +namespace mirror { +class Class; +class Object; +template<class T> class ObjectArray; +} +template <typename T> class AtomicStack; class Barrier; class CheckObjectVisitor; -class Class; +class ContinuousSpace; class Heap; class MarkIfReachesAllocspaceVisitor; class ModUnionClearCardVisitor; class ModUnionVisitor; class ModUnionTableBitmap; -class Object; -class TimingLogger; +typedef AtomicStack<mirror::Object*> ObjectStack; +class SpaceBitmap; +class StackVisitor; +class Thread; class MarkStackChunk; class MarkSweep : public GarbageCollector { @@ -79,7 +89,9 @@ class MarkSweep : public GarbageCollector { EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Verify that image roots point to only marked objects within the alloc space. - void VerifyImageRoots() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + void VerifyImageRoots() + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Builds a mark stack and recursively mark until it empties. void RecursiveMark() @@ -88,8 +100,8 @@ class MarkSweep : public GarbageCollector { // Make a space immune, immune spaces are assumed to have all live objects marked. void ImmuneSpace(ContinuousSpace* space) - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);; + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Bind the live bits to the mark bits of bitmaps based on the gc type. virtual void BindBitmaps() @@ -102,7 +114,7 @@ class MarkSweep : public GarbageCollector { EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Builds a mark stack with objects on dirty cards and recursively mark until it empties. - void RecursiveMarkDirtyObjects(byte minimum_age = CardTable::kCardDirty) + void RecursiveMarkDirtyObjects(byte minimum_age) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -130,61 +142,31 @@ class MarkSweep : public GarbageCollector { virtual void SwapBitmaps() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); void SwapLargeObjects() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - Object* GetClearedReferences() { + mirror::Object* GetClearedReferences() { return cleared_reference_list_; } // Proxy for external access to ScanObject. - void ScanRoot(const Object* obj) + void ScanRoot(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Blackens an object. - void ScanObject(const Object* obj) + void ScanObject(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // TODO: enable thread safety analysis when in use by multiple worker threads. template <typename MarkVisitor> - void ScanObjectVisit(const Object* obj, const MarkVisitor& visitor) - NO_THREAD_SAFETY_ANALYSIS { - DCHECK(obj != NULL); - if (kIsDebugBuild && !IsMarked(obj)) { - heap_->DumpSpaces(); - LOG(FATAL) << "Scanning unmarked object " << obj; - } - Class* klass = obj->GetClass(); - DCHECK(klass != NULL); - if (klass == java_lang_Class_) { - DCHECK_EQ(klass->GetClass(), java_lang_Class_); - if (kCountScannedTypes) { - ++class_count_; - } - VisitClassReferences(klass, obj, visitor); - } else if (klass->IsArrayClass()) { - if (kCountScannedTypes) { - ++array_count_; - } - visitor(obj, klass, Object::ClassOffset(), false); - if (klass->IsObjectArrayClass()) { - VisitObjectArrayReferences(obj->AsObjectArray<Object>(), visitor); - } - } else { - if (kCountScannedTypes) { - ++other_count_; - } - VisitOtherReferences(klass, obj, visitor); - if (UNLIKELY(klass->IsReferenceClass())) { - DelayReferenceReferent(const_cast<Object*>(obj)); - } - } - } + void ScanObjectVisit(const mirror::Object* obj, const MarkVisitor& visitor) + NO_THREAD_SAFETY_ANALYSIS; - void SetFinger(Object* new_finger) { + void SetFinger(mirror::Object* new_finger) { finger_ = new_finger; } void DisableFinger() { - SetFinger(reinterpret_cast<Object*>(~static_cast<uintptr_t>(0))); + SetFinger(reinterpret_cast<mirror::Object*>(~static_cast<uintptr_t>(0))); } size_t GetFreedBytes() const { @@ -212,7 +194,7 @@ class MarkSweep : public GarbageCollector { } // Everything inside the immune range is assumed to be marked. - void SetImmuneRange(Object* begin, Object* end); + void SetImmuneRange(mirror::Object* begin, mirror::Object* end); void SweepSystemWeaks() SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); @@ -221,52 +203,33 @@ class MarkSweep : public GarbageCollector { void SweepSystemWeaksArray(ObjectStack* allocations) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static bool VerifyIsLiveCallback(const Object* obj, void* arg) + static bool VerifyIsLiveCallback(const mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); void VerifySystemWeaks() SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Verify that an object is live, either in a live bitmap or in the allocation stack. - void VerifyIsLive(const Object* obj) + void VerifyIsLive(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); template <typename Visitor> - static void VisitObjectReferences(const Object* obj, const Visitor& visitor) + static void VisitObjectReferences(const mirror::Object* obj, const Visitor& visitor) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, - Locks::mutator_lock_) { - DCHECK(obj != NULL); - DCHECK(obj->GetClass() != NULL); - - Class* klass = obj->GetClass(); - DCHECK(klass != NULL); - if (klass == Class::GetJavaLangClass()) { - DCHECK_EQ(klass->GetClass(), Class::GetJavaLangClass()); - VisitClassReferences(klass, obj, visitor); - } else { - if (klass->IsArrayClass()) { - visitor(obj, klass, Object::ClassOffset(), false); - if (klass->IsObjectArrayClass()) { - VisitObjectArrayReferences(obj->AsObjectArray<Object>(), visitor); - } - } else { - VisitOtherReferences(klass, obj, visitor); - } - } - } + Locks::mutator_lock_); - static void MarkObjectCallback(const Object* root, void* arg) + static void MarkObjectCallback(const mirror::Object* root, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static void MarkRootParallelCallback(const Object* root, void* arg); + static void MarkRootParallelCallback(const mirror::Object* root, void* arg); // Marks an object. - void MarkObject(const Object* obj) + void MarkObject(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - void MarkRoot(const Object* obj) + void MarkRoot(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); @@ -277,45 +240,46 @@ class MarkSweep : public GarbageCollector { protected: // Returns true if the object has its bit set in the mark bitmap. - bool IsMarked(const Object* object) const; + bool IsMarked(const mirror::Object* object) const; - static bool IsMarkedCallback(const Object* object, void* arg) + static bool IsMarkedCallback(const mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static bool IsMarkedArrayCallback(const Object* object, void* arg) + static bool IsMarkedArrayCallback(const mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static void ReMarkObjectVisitor(const Object* root, void* arg) + static void ReMarkObjectVisitor(const mirror::Object* root, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static void VerifyImageRootVisitor(Object* root, void* arg) + static void VerifyImageRootVisitor(mirror::Object* root, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); - void MarkObjectNonNull(const Object* obj, bool check_finger) + void MarkObjectNonNull(const mirror::Object* obj, bool check_finger) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - void MarkObjectNonNullParallel(const Object* obj, bool check_finger); + void MarkObjectNonNullParallel(const mirror::Object* obj, bool check_finger); - bool MarkLargeObject(const Object* obj) + bool MarkLargeObject(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Returns true if we need to add obj to a mark stack. - bool MarkObjectParallel(const Object* obj) NO_THREAD_SAFETY_ANALYSIS; + bool MarkObjectParallel(const mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS; - static void SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) + static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Special sweep for zygote that just marks objects / dirties cards. - static void ZygoteSweepCallback(size_t num_ptrs, Object** ptrs, void* arg) + static void ZygoteSweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - void CheckReference(const Object* obj, const Object* ref, MemberOffset offset, bool is_static) + void CheckReference(const mirror::Object* obj, const mirror::Object* ref, MemberOffset offset, + bool is_static) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); - void CheckObject(const Object* obj) + void CheckObject(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); // Verify the roots of the heap and print out information related to any invalid roots. @@ -326,90 +290,41 @@ class MarkSweep : public GarbageCollector { // Expand mark stack to 2x its current size. Thread safe. void ExpandMarkStack(); - static void VerifyRootCallback(const Object* root, void* arg, size_t vreg, + static void VerifyRootCallback(const mirror::Object* root, void* arg, size_t vreg, const StackVisitor *visitor); - void VerifyRoot(const Object* root, size_t vreg, const StackVisitor* visitor) + void VerifyRoot(const mirror::Object* root, size_t vreg, const StackVisitor* visitor) NO_THREAD_SAFETY_ANALYSIS; template <typename Visitor> - static void VisitInstanceFieldsReferences(const Class* klass, const Object* obj, + static void VisitInstanceFieldsReferences(const mirror::Class* klass, const mirror::Object* obj, const Visitor& visitor) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { - DCHECK(obj != NULL); - DCHECK(klass != NULL); - VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor); - } + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); // Visit the header, static field references, and interface pointers of a class object. template <typename Visitor> - static void VisitClassReferences(const Class* klass, const Object* obj, + static void VisitClassReferences(const mirror::Class* klass, const mirror::Object* obj, const Visitor& visitor) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { - VisitInstanceFieldsReferences(klass, obj, visitor); - VisitStaticFieldsReferences(obj->AsClass(), visitor); - } + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); template <typename Visitor> - static void VisitStaticFieldsReferences(const Class* klass, const Visitor& visitor) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { - DCHECK(klass != NULL); - VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor); - } + static void VisitStaticFieldsReferences(const mirror::Class* klass, const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); template <typename Visitor> - static void VisitFieldsReferences(const Object* obj, uint32_t ref_offsets, bool is_static, - const Visitor& visitor) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { - if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) { - // Found a reference offset bitmap. Mark the specified offsets. - while (ref_offsets != 0) { - size_t right_shift = CLZ(ref_offsets); - MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); - const Object* ref = obj->GetFieldObject<const Object*>(field_offset, false); - visitor(obj, ref, field_offset, is_static); - ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); - } - } else { - // There is no reference offset bitmap. In the non-static case, - // walk up the class inheritance hierarchy and find reference - // offsets the hard way. In the static case, just consider this - // class. - for (const Class* klass = is_static ? obj->AsClass() : obj->GetClass(); - klass != NULL; - klass = is_static ? NULL : klass->GetSuperClass()) { - size_t num_reference_fields = (is_static - ? klass->NumReferenceStaticFields() - : klass->NumReferenceInstanceFields()); - for (size_t i = 0; i < num_reference_fields; ++i) { - Field* field = (is_static - ? klass->GetStaticField(i) - : klass->GetInstanceField(i)); - MemberOffset field_offset = field->GetOffset(); - const Object* ref = obj->GetFieldObject<const Object*>(field_offset, false); - visitor(obj, ref, field_offset, is_static); - } - } - } - } + static void VisitFieldsReferences(const mirror::Object* obj, uint32_t ref_offsets, bool is_static, + const Visitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); // Visit all of the references in an object array. template <typename Visitor> - static void VisitObjectArrayReferences(const ObjectArray<Object>* array, + static void VisitObjectArrayReferences(const mirror::ObjectArray<mirror::Object>* array, const Visitor& visitor) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { - const int32_t length = array->GetLength(); - for (int32_t i = 0; i < length; ++i) { - const Object* element = array->GetWithoutChecks(i); - const size_t width = sizeof(Object*); - MemberOffset offset = MemberOffset(i * width + Array::DataOffset(width).Int32Value()); - visitor(array, element, offset, false); - } - } + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); // Visits the header and field references of a data object. template <typename Visitor> - static void VisitOtherReferences(const Class* klass, const Object* obj, + static void VisitOtherReferences(const mirror::Class* klass, const mirror::Object* obj, const Visitor& visitor) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { return VisitInstanceFieldsReferences(klass, obj, visitor); @@ -421,7 +336,7 @@ class MarkSweep : public GarbageCollector { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Schedules an unmarked object for reference processing. - void DelayReferenceReferent(Object* reference) + void DelayReferenceReferent(mirror::Object* reference) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); // Recursively blackens objects on the mark stack. @@ -433,25 +348,25 @@ class MarkSweep : public GarbageCollector { EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void EnqueueFinalizerReferences(Object** ref) + void EnqueueFinalizerReferences(mirror::Object** ref) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void PreserveSomeSoftReferences(Object** ref) + void PreserveSomeSoftReferences(mirror::Object** ref) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void ClearWhiteReferences(Object** list) + void ClearWhiteReferences(mirror::Object** list) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); - void ProcessReferences(Object** soft_references, bool clear_soft_references, - Object** weak_references, - Object** finalizer_references, - Object** phantom_references) + void ProcessReferences(mirror::Object** soft_references, bool clear_soft_references, + mirror::Object** weak_references, + mirror::Object** finalizer_references, + mirror::Object** phantom_references) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SweepJniWeakGlobals(Heap::IsMarkedTester is_marked, void* arg) + void SweepJniWeakGlobals(IsMarkedTester is_marked, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Whether or not we count how many of each type of object were scanned. @@ -461,21 +376,21 @@ class MarkSweep : public GarbageCollector { SpaceBitmap* current_mark_bitmap_; // Cache java.lang.Class for optimization. - Class* java_lang_Class_; + mirror::Class* java_lang_Class_; ObjectStack* mark_stack_; - Object* finger_; + mirror::Object* finger_; // Immune range, every object inside the immune range is assumed to be marked. - Object* immune_begin_; - Object* immune_end_; + mirror::Object* immune_begin_; + mirror::Object* immune_end_; - Object* soft_reference_list_; - Object* weak_reference_list_; - Object* finalizer_reference_list_; - Object* phantom_reference_list_; - Object* cleared_reference_list_; + mirror::Object* soft_reference_list_; + mirror::Object* weak_reference_list_; + mirror::Object* finalizer_reference_list_; + mirror::Object* phantom_reference_list_; + mirror::Object* cleared_reference_list_; AtomicInteger freed_bytes_; AtomicInteger freed_objects_; @@ -529,4 +444,4 @@ class MarkSweep : public GarbageCollector { } // namespace art -#endif // ART_SRC_MARK_SWEEP_H_ +#endif // ART_SRC_GC_MARK_SWEEP_H_ diff --git a/src/gc/mod_union_table-inl.h b/src/gc/mod_union_table-inl.h new file mode 100644 index 0000000000..c1c69fb379 --- /dev/null +++ b/src/gc/mod_union_table-inl.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_MOD_UNION_TABLE_INL_H_ +#define ART_SRC_GC_MOD_UNION_TABLE_INL_H_ + +#include "mod_union_table.h" + +namespace art { + +template <typename Implementation> +class ModUnionTableToZygoteAllocspace : public Implementation { +public: + ModUnionTableToZygoteAllocspace(Heap* heap) : Implementation(heap) { + } + + bool AddReference(const mirror::Object* /* obj */, const mirror::Object* ref) { + const Spaces& spaces = Implementation::GetHeap()->GetSpaces(); + for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { + if ((*it)->Contains(ref)) { + return (*it)->IsAllocSpace(); + } + } + // Assume it points to a large object. + // TODO: Check. + return true; + } +}; + +template <typename Implementation> +class ModUnionTableToAllocspace : public Implementation { +public: + ModUnionTableToAllocspace(Heap* heap) : Implementation(heap) { + } + + bool AddReference(const mirror::Object* /* obj */, const mirror::Object* ref) { + const Spaces& spaces = Implementation::GetHeap()->GetSpaces(); + for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { + if ((*it)->Contains(ref)) { + return (*it)->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect; + } + } + // Assume it points to a large object. + // TODO: Check. + return true; + } +}; + +} // namespace art + +#endif // ART_SRC_GC_MOD_UNION_TABLE_INL_H_ diff --git a/src/gc/mod_union_table.cc b/src/gc/mod_union_table.cc index 8953c5ac61..da950bb9b8 100644 --- a/src/gc/mod_union_table.cc +++ b/src/gc/mod_union_table.cc @@ -17,12 +17,22 @@ #include "mod_union_table.h" #include "base/stl_util.h" +#include "card_table-inl.h" #include "heap.h" #include "heap_bitmap.h" #include "mark_sweep.h" +#include "mark_sweep-inl.h" +#include "mirror/object-inl.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/object_array-inl.h" #include "space.h" +#include "space_bitmap-inl.h" +#include "thread.h" #include "UniquePtr.h" +using namespace art::mirror; + namespace art { class MarkIfReachesAllocspaceVisitor { @@ -260,7 +270,7 @@ class CheckReferenceVisitor { // TODO: Fixme when anotatalysis works with visitors. void operator ()(const Object* obj, const Object* ref, const MemberOffset& /* offset */, bool /* is_static */) const - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { Heap* heap = mod_union_table_->GetHeap(); if (ref != NULL && mod_union_table_->AddReference(obj, ref) && references_.find(ref) == references_.end()) { diff --git a/src/gc/mod_union_table.h b/src/gc/mod_union_table.h index f3da41c841..23c0a516e3 100644 --- a/src/gc/mod_union_table.h +++ b/src/gc/mod_union_table.h @@ -14,23 +14,30 @@ * limitations under the License. */ -#ifndef ART_SRC_MOD_UNION_TABLE_H_ -#define ART_SRC_MOD_UNION_TABLE_H_ +#ifndef ART_SRC_GC_MOD_UNION_TABLE_H_ +#define ART_SRC_GC_MOD_UNION_TABLE_H_ -#include "heap.h" +#include "globals.h" #include "safe_map.h" -#include "space.h" -namespace art { +#include <set> +#include <vector> +namespace art { +namespace mirror { +class Object; +} +class ContinuousSpace; class Heap; class HeapBitmap; +class MarkSweep; class Space; +class SpaceBitmap; // Base class class ModUnionTable { public: - typedef std::vector<const Object*> ReferenceArray; + typedef std::vector<const mirror::Object*> ReferenceArray; typedef std::set<byte*> ClearedCards; ModUnionTable(Heap* heap) : heap_(heap) { @@ -118,7 +125,7 @@ class ModUnionTableReferenceCache : public ModUnionTable { void Verify() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Function that tells whether or not to add a reference to the table. - virtual bool AddReference(const Object* obj, const Object* ref) = 0; + virtual bool AddReference(const mirror::Object* obj, const mirror::Object* ref) = 0; protected: // Cleared card array, used to update the mod-union table. @@ -155,44 +162,6 @@ class ModUnionTableCardCache : public ModUnionTable { ClearedCards cleared_cards_; }; -template <typename Implementation> -class ModUnionTableToZygoteAllocspace : public Implementation { -public: - ModUnionTableToZygoteAllocspace(Heap* heap) : Implementation(heap) { - } - - bool AddReference(const Object* /* obj */, const Object* ref) { - const Spaces& spaces = Implementation::GetHeap()->GetSpaces(); - for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { - if ((*it)->Contains(ref)) { - return (*it)->IsAllocSpace(); - } - } - // Assume it points to a large object. - // TODO: Check. - return true; - } -}; - -template <typename Implementation> -class ModUnionTableToAllocspace : public Implementation { -public: - ModUnionTableToAllocspace(Heap* heap) : Implementation(heap) { - } - - bool AddReference(const Object* /* obj */, const Object* ref) { - const Spaces& spaces = Implementation::GetHeap()->GetSpaces(); - for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { - if ((*it)->Contains(ref)) { - return (*it)->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect; - } - } - // Assume it points to a large object. - // TODO: Check. - return true; - } -}; - } // namespace art -#endif // ART_SRC_MOD_UNION_TABLE_H_ +#endif // ART_SRC_GC_MOD_UNION_TABLE_H_ diff --git a/src/gc/partial_mark_sweep.cc b/src/gc/partial_mark_sweep.cc index 64f09ff91e..f9c1787045 100644 --- a/src/gc/partial_mark_sweep.cc +++ b/src/gc/partial_mark_sweep.cc @@ -14,32 +14,38 @@ * limitations under the License. */ +#include "partial_mark_sweep.h" + +#include "heap.h" #include "large_object_space.h" #include "partial_mark_sweep.h" #include "space.h" +#include "thread.h" namespace art { - PartialMarkSweep::PartialMarkSweep(Heap* heap, bool is_concurrent) - : MarkSweep(heap, is_concurrent) { - cumulative_timings_.SetName(GetName()); - } - PartialMarkSweep::~PartialMarkSweep() { +PartialMarkSweep::PartialMarkSweep(Heap* heap, bool is_concurrent) + : MarkSweep(heap, is_concurrent) { + cumulative_timings_.SetName(GetName()); +} - } +PartialMarkSweep::~PartialMarkSweep() { - void PartialMarkSweep::BindBitmaps() { - MarkSweep::BindBitmaps(); - - Spaces& spaces = GetHeap()->GetSpaces(); - WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); - // For partial GCs we need to bind the bitmap of the zygote space so that all objects in the - // zygote space are viewed as marked. - for (Spaces::iterator it = spaces.begin(); it != spaces.end(); ++it) { - ContinuousSpace* space = *it; - if (space->GetGcRetentionPolicy() == kGcRetentionPolicyFullCollect) { - ImmuneSpace(space); - } +} + +void PartialMarkSweep::BindBitmaps() { + MarkSweep::BindBitmaps(); + + Spaces& spaces = GetHeap()->GetSpaces(); + WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); + // For partial GCs we need to bind the bitmap of the zygote space so that all objects in the + // zygote space are viewed as marked. + for (Spaces::iterator it = spaces.begin(); it != spaces.end(); ++it) { + ContinuousSpace* space = *it; + if (space->GetGcRetentionPolicy() == kGcRetentionPolicyFullCollect) { + ImmuneSpace(space); } } +} + } // namespace art diff --git a/src/gc/partial_mark_sweep.h b/src/gc/partial_mark_sweep.h index 80a15630ae..64c0bcd8f8 100644 --- a/src/gc/partial_mark_sweep.h +++ b/src/gc/partial_mark_sweep.h @@ -14,27 +14,14 @@ * limitations under the License. */ -#ifndef ART_SRC_PARTIAL_MARK_SWEEP_H_ -#define ART_SRC_PARTIAL_MARK_SWEEP_H_ +#ifndef ART_SRC_GC_PARTIAL_MARK_SWEEP_H_ +#define ART_SRC_GC_PARTIAL_MARK_SWEEP_H_ #include "locks.h" #include "mark_sweep.h" -#include "utils.h" namespace art { -class Barrier; -class CheckObjectVisitor; -class Class; -class Heap; -class MarkIfReachesAllocspaceVisitor; -class ModUnionClearCardVisitor; -class ModUnionVisitor; -class ModUnionTableBitmap; -class Object; -class TimingLogger; -class MarkStackChunk; - class PartialMarkSweep : public MarkSweep { public: virtual GcType GetGcType() const { @@ -53,4 +40,4 @@ protected: } // namespace art -#endif // ART_SRC_PARTIAL_MARK_SWEEP_H_ +#endif // ART_SRC_GC_PARTIAL_MARK_SWEEP_H_ diff --git a/src/gc/space.cc b/src/gc/space.cc index 04f932dc9b..9db84f24ba 100644 --- a/src/gc/space.cc +++ b/src/gc/space.cc @@ -19,10 +19,16 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" +#include "card_table.h" #include "dlmalloc.h" #include "image.h" +#include "mirror/array.h" +#include "mirror/abstract_method.h" #include "os.h" +#include "runtime.h" #include "space_bitmap.h" +#include "space_bitmap-inl.h" +#include "thread.h" #include "UniquePtr.h" #include "utils.h" @@ -204,12 +210,12 @@ void DlMallocSpace::SwapBitmaps() { mark_bitmap_->SetName(temp_name); } -Object* DlMallocSpace::AllocWithoutGrowthLocked(size_t num_bytes) { +mirror::Object* DlMallocSpace::AllocWithoutGrowthLocked(size_t num_bytes) { if (kDebugSpaces) { num_bytes += sizeof(word); } - Object* result = reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes)); + mirror::Object* result = reinterpret_cast<mirror::Object*>(mspace_calloc(mspace_, 1, num_bytes)); if (kDebugSpaces && result != NULL) { CHECK(Contains(result)) << "Allocation (" << reinterpret_cast<void*>(result) << ") not in bounds of allocation space " << *this; @@ -225,18 +231,18 @@ Object* DlMallocSpace::AllocWithoutGrowthLocked(size_t num_bytes) { return result; } -Object* DlMallocSpace::Alloc(Thread* self, size_t num_bytes) { +mirror::Object* DlMallocSpace::Alloc(Thread* self, size_t num_bytes) { MutexLock mu(self, lock_); return AllocWithoutGrowthLocked(num_bytes); } -Object* DlMallocSpace::AllocWithGrowth(Thread* self, size_t num_bytes) { +mirror::Object* DlMallocSpace::AllocWithGrowth(Thread* self, size_t num_bytes) { MutexLock mu(self, lock_); // Grow as much as possible within the mspace. size_t max_allowed = Capacity(); mspace_set_footprint_limit(mspace_, max_allowed); // Try the allocation. - Object* result = AllocWithoutGrowthLocked(num_bytes); + mirror::Object* result = AllocWithoutGrowthLocked(num_bytes); // Shrink back down as small as possible. size_t footprint = mspace_footprint(mspace_); mspace_set_footprint_limit(mspace_, footprint); @@ -301,7 +307,7 @@ DlMallocSpace* DlMallocSpace::CreateZygoteSpace() { return alloc_space; } -size_t DlMallocSpace::Free(Thread* self, Object* ptr) { +size_t DlMallocSpace::Free(Thread* self, mirror::Object* ptr) { MutexLock mu(self, lock_); if (kDebugSpaces) { CHECK(ptr != NULL); @@ -317,13 +323,13 @@ size_t DlMallocSpace::Free(Thread* self, Object* ptr) { return bytes_freed; } -size_t DlMallocSpace::FreeList(Thread* self, size_t num_ptrs, Object** ptrs) { +size_t DlMallocSpace::FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) { DCHECK(ptrs != NULL); // Don't need the lock to calculate the size of the freed pointers. size_t bytes_freed = 0; for (size_t i = 0; i < num_ptrs; i++) { - Object* ptr = ptrs[i]; + mirror::Object* ptr = ptrs[i]; const size_t look_ahead = 8; if (kPrefetchDuringDlMallocFreeList && i + look_ahead < num_ptrs) { // The head of chunk for the allocation is sizeof(size_t) behind the allocation. @@ -397,12 +403,12 @@ void* DlMallocSpace::MoreCore(intptr_t increment) { } // Virtual functions can't get inlined. -inline size_t DlMallocSpace::InternalAllocationSize(const Object* obj) { +inline size_t DlMallocSpace::InternalAllocationSize(const mirror::Object* obj) { return mspace_usable_size(const_cast<void*>(reinterpret_cast<const void*>(obj))) + kChunkOverhead; } -size_t DlMallocSpace::AllocationSize(const Object* obj) { +size_t DlMallocSpace::AllocationSize(const mirror::Object* obj) { return InternalAllocationSize(obj); } @@ -504,29 +510,29 @@ ImageSpace* ImageSpace::Create(const std::string& image_file_name) { DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader))); Runtime* runtime = Runtime::Current(); - Object* jni_stub_array = image_header.GetImageRoot(ImageHeader::kJniStubArray); - runtime->SetJniDlsymLookupStub(down_cast<ByteArray*>(jni_stub_array)); + mirror::Object* jni_stub_array = image_header.GetImageRoot(ImageHeader::kJniStubArray); + runtime->SetJniDlsymLookupStub(down_cast<mirror::ByteArray*>(jni_stub_array)); - Object* ame_stub_array = image_header.GetImageRoot(ImageHeader::kAbstractMethodErrorStubArray); - runtime->SetAbstractMethodErrorStubArray(down_cast<ByteArray*>(ame_stub_array)); + mirror::Object* ame_stub_array = image_header.GetImageRoot(ImageHeader::kAbstractMethodErrorStubArray); + runtime->SetAbstractMethodErrorStubArray(down_cast<mirror::ByteArray*>(ame_stub_array)); - Object* resolution_stub_array = + mirror::Object* resolution_stub_array = image_header.GetImageRoot(ImageHeader::kStaticResolutionStubArray); runtime->SetResolutionStubArray( - down_cast<ByteArray*>(resolution_stub_array), Runtime::kStaticMethod); + down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kStaticMethod); resolution_stub_array = image_header.GetImageRoot(ImageHeader::kUnknownMethodResolutionStubArray); runtime->SetResolutionStubArray( - down_cast<ByteArray*>(resolution_stub_array), Runtime::kUnknownMethod); + down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kUnknownMethod); - Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod); - runtime->SetResolutionMethod(down_cast<AbstractMethod*>(resolution_method)); + mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod); + runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method)); - Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod); - runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kSaveAll); + mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod); + runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kSaveAll); callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod); - runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kRefsOnly); + runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsOnly); callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod); - runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs); + runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs); ImageSpace* space = new ImageSpace(image_file_name, map.release()); if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { @@ -548,7 +554,7 @@ void ImageSpace::RecordImageAllocations(SpaceBitmap* live_bitmap) const { byte* end = End(); while (current < end) { DCHECK_ALIGNED(current, kObjectAlignment); - const Object* obj = reinterpret_cast<const Object*>(current); + const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current); live_bitmap->Set(obj); current += RoundUp(obj->SizeOf(), kObjectAlignment); } diff --git a/src/gc/space.h b/src/gc/space.h index 2ed4988f75..d2bcd53725 100644 --- a/src/gc/space.h +++ b/src/gc/space.h @@ -31,10 +31,12 @@ namespace art { static const bool kDebugSpaces = kIsDebugBuild; +namespace mirror { +class Object; +} // namespace mirror class DlMallocSpace; class ImageSpace; class LargeObjectSpace; -class Object; class SpaceBitmap; enum GcRetentionPolicy { @@ -57,7 +59,7 @@ class Space { public: virtual bool CanAllocateInto() const = 0; virtual bool IsCompactible() const = 0; - virtual bool Contains(const Object* obj) const = 0; + virtual bool Contains(const mirror::Object* obj) const = 0; virtual SpaceType GetType() const = 0; virtual GcRetentionPolicy GetGcRetentionPolicy() const = 0; virtual std::string GetName() const = 0; @@ -108,16 +110,16 @@ class AllocSpace { virtual uint64_t GetTotalObjectsAllocated() const = 0; // Allocate num_bytes without allowing growth. - virtual Object* Alloc(Thread* self, size_t num_bytes) = 0; + virtual mirror::Object* Alloc(Thread* self, size_t num_bytes) = 0; // Return the storage space required by obj. - virtual size_t AllocationSize(const Object* obj) = 0; + virtual size_t AllocationSize(const mirror::Object* obj) = 0; // Returns how many bytes were freed. - virtual size_t Free(Thread* self, Object* ptr) = 0; + virtual size_t Free(Thread* self, mirror::Object* ptr) = 0; // Returns how many bytes were freed. - virtual size_t FreeList(Thread* self, size_t num_ptrs, Object** ptrs) = 0; + virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) = 0; protected: AllocSpace() {} @@ -149,12 +151,12 @@ class ContinuousSpace : public Space { virtual SpaceBitmap* GetMarkBitmap() const = 0; // Is object within this space? - bool HasAddress(const Object* obj) const { + bool HasAddress(const mirror::Object* obj) const { const byte* byte_ptr = reinterpret_cast<const byte*>(obj); return Begin() <= byte_ptr && byte_ptr < End(); } - virtual bool Contains(const Object* obj) const { + virtual bool Contains(const mirror::Object* obj) const { return HasAddress(obj); } @@ -188,7 +190,7 @@ class ContinuousSpace : public Space { class DiscontinuousSpace : public virtual Space { public: // Is object within this space? - virtual bool Contains(const Object* obj) const = 0; + virtual bool Contains(const mirror::Object* obj) const = 0; virtual std::string GetName() const { return name_; @@ -267,15 +269,15 @@ class DlMallocSpace : public MemMapSpace, public AllocSpace { size_t capacity, byte* requested_begin); // Allocate num_bytes without allowing the underlying mspace to grow. - virtual Object* AllocWithGrowth(Thread* self, size_t num_bytes); + virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes); // Allocate num_bytes allowing the underlying mspace to grow. - virtual Object* Alloc(Thread* self, size_t num_bytes); + virtual mirror::Object* Alloc(Thread* self, size_t num_bytes); // Return the storage space required by obj. - virtual size_t AllocationSize(const Object* obj); - virtual size_t Free(Thread* self, Object* ptr); - virtual size_t FreeList(Thread* self, size_t num_ptrs, Object** ptrs); + virtual size_t AllocationSize(const mirror::Object* obj); + virtual size_t Free(Thread* self, mirror::Object* ptr); + virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs); void* MoreCore(intptr_t increment); @@ -353,8 +355,8 @@ class DlMallocSpace : public MemMapSpace, public AllocSpace { } private: - size_t InternalAllocationSize(const Object* obj); - Object* AllocWithoutGrowthLocked(size_t num_bytes) EXCLUSIVE_LOCKS_REQUIRED(lock_); + size_t InternalAllocationSize(const mirror::Object* obj); + mirror::Object* AllocWithoutGrowthLocked(size_t num_bytes) EXCLUSIVE_LOCKS_REQUIRED(lock_); UniquePtr<SpaceBitmap> live_bitmap_; UniquePtr<SpaceBitmap> mark_bitmap_; diff --git a/src/gc/space_bitmap-inl.h b/src/gc/space_bitmap-inl.h new file mode 100644 index 0000000000..e1fdd29d8d --- /dev/null +++ b/src/gc/space_bitmap-inl.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_GC_SPACE_BITMAP_INL_H_ +#define ART_SRC_GC_SPACE_BITMAP_INL_H_ + +#include "base/logging.h" +#include "cutils/atomic.h" + +namespace art { + +inline bool SpaceBitmap::AtomicTestAndSet(const mirror::Object* obj) { + uintptr_t addr = reinterpret_cast<uintptr_t>(obj); + DCHECK_GE(addr, heap_begin_); + const uintptr_t offset = addr - heap_begin_; + const size_t index = OffsetToIndex(offset); + const word mask = OffsetToMask(offset); + word* const address = &bitmap_begin_[index]; + DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; + word old_word; + do { + old_word = *address; + // Fast path: The bit is already set. + if ((old_word & mask) != 0) { + return true; + } + } while (UNLIKELY(android_atomic_cas(old_word, old_word | mask, address) != 0)); + return false; +} + +inline bool SpaceBitmap::Test(const mirror::Object* obj) const { + uintptr_t addr = reinterpret_cast<uintptr_t>(obj); + DCHECK(HasAddress(obj)) << obj; + DCHECK(bitmap_begin_ != NULL); + DCHECK_GE(addr, heap_begin_); + const uintptr_t offset = addr - heap_begin_; + return (bitmap_begin_[OffsetToIndex(offset)] & OffsetToMask(offset)) != 0; +} + +template <typename Visitor, typename FingerVisitor> +void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end, + const Visitor& visitor, + const FingerVisitor& finger_visitor) const { + DCHECK_LT(visit_begin, visit_end); + + const size_t word_span = kAlignment * kBitsPerWord; // Equals IndexToOffset(1). + const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment; + const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment; + + size_t word_start = bit_index_start / kBitsPerWord; + size_t word_end = bit_index_end / kBitsPerWord; + DCHECK_LT(word_end * kWordSize, Size()); + + // Trim off left_bits of left bits. + size_t edge_word = bitmap_begin_[word_start]; + + // Handle bits on the left first as a special case + size_t left_bits = bit_index_start & (kBitsPerWord - 1); + if (left_bits != 0) { + edge_word &= (1 << (kBitsPerWord - left_bits)) - 1; + } + + // If word_start == word_end then handle this case at the same place we handle the right edge. + if (edge_word != 0 && word_start < word_end) { + uintptr_t ptr_base = IndexToOffset(word_start) + heap_begin_; + finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); + do { + const size_t shift = CLZ(edge_word); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); + visitor(obj); + edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; + } while (edge_word != 0); + } + word_start++; + + for (size_t i = word_start; i < word_end; i++) { + size_t w = bitmap_begin_[i]; + if (w != 0) { + uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; + finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); + do { + const size_t shift = CLZ(w); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); + visitor(obj); + w ^= static_cast<size_t>(kWordHighBitMask) >> shift; + } while (w != 0); + } + } + + // Handle the right edge, and also the left edge if both edges are on the same word. + size_t right_bits = bit_index_end & (kBitsPerWord - 1); + + // If word_start == word_end then we need to use the word which we removed the left bits. + if (word_start <= word_end) { + edge_word = bitmap_begin_[word_end]; + } + + // Bits that we trim off the right. + edge_word &= ~((static_cast<size_t>(kWordHighBitMask) >> right_bits) - 1); + uintptr_t ptr_base = IndexToOffset(word_end) + heap_begin_; + finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); + while (edge_word != 0) { + const size_t shift = CLZ(edge_word); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); + visitor(obj); + edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; + } +} + +inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) { + uintptr_t addr = reinterpret_cast<uintptr_t>(obj); + DCHECK_GE(addr, heap_begin_); + const uintptr_t offset = addr - heap_begin_; + const size_t index = OffsetToIndex(offset); + const word mask = OffsetToMask(offset); + DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; + word* address = &bitmap_begin_[index]; + word old_word = *address; + if (do_set) { + *address = old_word | mask; + } else { + *address = old_word & ~mask; + } + return (old_word & mask) != 0; +} +} // namespace art + +#endif // ART_SRC_GC_SPACE_BITMAP_INL_H_ diff --git a/src/gc/space_bitmap.cc b/src/gc/space_bitmap.cc index 25fa672ee1..d90c090187 100644 --- a/src/gc/space_bitmap.cc +++ b/src/gc/space_bitmap.cc @@ -17,6 +17,11 @@ #include "heap_bitmap.h" #include "base/logging.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "space_bitmap-inl.h" #include "UniquePtr.h" #include "utils.h" @@ -32,7 +37,7 @@ void SpaceBitmap::SetName(const std::string& name) { void SpaceSetMap::Walk(SpaceBitmap::Callback* callback, void* arg) { for (Objects::iterator it = contained_.begin(); it != contained_.end(); ++it) { - callback(const_cast<Object*>(*it), arg); + callback(const_cast<mirror::Object*>(*it), arg); } } @@ -98,7 +103,7 @@ void SpaceBitmap::Walk(SpaceBitmap::Callback* callback, void* arg) { uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; do { const size_t shift = CLZ(w); - Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); (*callback)(obj, arg); w ^= static_cast<size_t>(kWordHighBitMask) >> shift; } while (w != 0); @@ -127,10 +132,10 @@ void SpaceBitmap::SweepWalk(const SpaceBitmap& live_bitmap, return; } - // TODO: rewrite the callbacks to accept a std::vector<Object*> rather than a Object**? + // TODO: rewrite the callbacks to accept a std::vector<mirror::Object*> rather than a mirror::Object**? const size_t buffer_size = kWordSize * kBitsPerWord; - Object* pointer_buf[buffer_size]; - Object** pb = &pointer_buf[0]; + mirror::Object* pointer_buf[buffer_size]; + mirror::Object** pb = &pointer_buf[0]; size_t start = OffsetToIndex(sweep_begin - live_bitmap.heap_begin_); size_t end = OffsetToIndex(sweep_end - live_bitmap.heap_begin_ - 1); CHECK_LT(end, live_bitmap.Size() / kWordSize); @@ -143,7 +148,7 @@ void SpaceBitmap::SweepWalk(const SpaceBitmap& live_bitmap, do { const size_t shift = CLZ(garbage); garbage ^= static_cast<size_t>(kWordHighBitMask) >> shift; - *pb++ = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); + *pb++ = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); } while (garbage != 0); // Make sure that there are always enough slots available for an // entire word of one bits. @@ -161,32 +166,32 @@ void SpaceBitmap::SweepWalk(const SpaceBitmap& live_bitmap, } // namespace art // Support needed for in order traversal -#include "object.h" +#include "mirror/object.h" #include "object_utils.h" namespace art { -static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callback, Object* obj, +static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callback, mirror::Object* obj, void* arg); // Walk instance fields of the given Class. Separate function to allow recursion on the super // class. -static void WalkInstanceFields(SpaceBitmap* visited, SpaceBitmap::Callback* callback, Object* obj, - Class* klass, void* arg) +static void WalkInstanceFields(SpaceBitmap* visited, SpaceBitmap::Callback* callback, mirror::Object* obj, + mirror::Class* klass, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Visit fields of parent classes first. - Class* super = klass->GetSuperClass(); + mirror::Class* super = klass->GetSuperClass(); if (super != NULL) { WalkInstanceFields(visited, callback, obj, super, arg); } // Walk instance fields - ObjectArray<Field>* fields = klass->GetIFields(); + mirror::ObjectArray<mirror::Field>* fields = klass->GetIFields(); if (fields != NULL) { for (int32_t i = 0; i < fields->GetLength(); i++) { - Field* field = fields->Get(i); + mirror::Field* field = fields->Get(i); FieldHelper fh(field); if (!fh.IsPrimitiveType()) { - Object* value = field->GetObj(obj); + mirror::Object* value = field->GetObj(obj); if (value != NULL) { WalkFieldsInOrder(visited, callback, value, arg); } @@ -196,7 +201,7 @@ static void WalkInstanceFields(SpaceBitmap* visited, SpaceBitmap::Callback* call } // For an unvisited object, visit it then all its children found via fields. -static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callback, Object* obj, +static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callback, mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (visited->Test(obj)) { @@ -206,17 +211,17 @@ static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callb (*callback)(obj, arg); visited->Set(obj); // Walk instance fields of all objects - Class* klass = obj->GetClass(); + mirror::Class* klass = obj->GetClass(); WalkInstanceFields(visited, callback, obj, klass, arg); // Walk static fields of a Class if (obj->IsClass()) { - ObjectArray<Field>* fields = klass->GetSFields(); + mirror::ObjectArray<mirror::Field>* fields = klass->GetSFields(); if (fields != NULL) { for (int32_t i = 0; i < fields->GetLength(); i++) { - Field* field = fields->Get(i); + mirror::Field* field = fields->Get(i); FieldHelper fh(field); if (!fh.IsPrimitiveType()) { - Object* value = field->GetObj(NULL); + mirror::Object* value = field->GetObj(NULL); if (value != NULL) { WalkFieldsInOrder(visited, callback, value, arg); } @@ -225,10 +230,10 @@ static void WalkFieldsInOrder(SpaceBitmap* visited, SpaceBitmap::Callback* callb } } else if (obj->IsObjectArray()) { // Walk elements of an object array - ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>(); + mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>(); int32_t length = obj_array->GetLength(); for (int32_t i = 0; i < length; i++) { - Object* value = obj_array->Get(i); + mirror::Object* value = obj_array->Get(i); if (value != NULL) { WalkFieldsInOrder(visited, callback, value, arg); } @@ -251,7 +256,7 @@ void SpaceBitmap::InOrderWalk(SpaceBitmap::Callback* callback, void* arg) { uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; while (w != 0) { const size_t shift = CLZ(w); - Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); WalkFieldsInOrder(visited.get(), callback, obj, arg); w ^= static_cast<size_t>(kWordHighBitMask) >> shift; } diff --git a/src/gc/space_bitmap.h b/src/gc/space_bitmap.h index dd2f47d8f8..6bc06d600d 100644 --- a/src/gc/space_bitmap.h +++ b/src/gc/space_bitmap.h @@ -14,35 +14,33 @@ * limitations under the License. */ -#ifndef ART_SRC_SPACE_BITMAP_H_ -#define ART_SRC_SPACE_BITMAP_H_ +#ifndef ART_SRC_GC_SPACE_BITMAP_H_ +#define ART_SRC_GC_SPACE_BITMAP_H_ + +#include "locks.h" +#include "globals.h" +#include "mem_map.h" +#include "UniquePtr.h" #include <limits.h> #include <set> #include <stdint.h> #include <vector> -#include "base/logging.h" -#include "cutils/atomic.h" -#include "cutils/atomic-inline.h" -#include "UniquePtr.h" -#include "globals.h" -#include "mem_map.h" -#include "utils.h" - namespace art { - +namespace mirror { class Object; +} // namespace mirror class SpaceBitmap { public: static const size_t kAlignment = 8; - typedef void Callback(Object* obj, void* arg); + typedef void Callback(mirror::Object* obj, void* arg); - typedef void ScanCallback(Object* obj, void* finger, void* arg); + typedef void ScanCallback(mirror::Object* obj, void* finger, void* arg); - typedef void SweepCallback(size_t ptr_count, Object** ptrs, void* arg); + typedef void SweepCallback(size_t ptr_count, mirror::Object** ptrs, void* arg); // Initialize a HeapBitmap so that it points to a bitmap large enough to cover a heap at // heap_begin of heap_capacity bytes, where objects are guaranteed to be kAlignment-aligned. @@ -66,44 +64,20 @@ class SpaceBitmap { return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset_ / kAlignment) % kBitsPerWord); } - inline bool Set(const Object* obj) { + inline bool Set(const mirror::Object* obj) { return Modify(obj, true); } - inline bool Clear(const Object* obj) { + inline bool Clear(const mirror::Object* obj) { return Modify(obj, false); } // Returns true if the object was previously marked. - inline bool AtomicTestAndSet(const Object* obj) { - uintptr_t addr = reinterpret_cast<uintptr_t>(obj); - DCHECK_GE(addr, heap_begin_); - const uintptr_t offset = addr - heap_begin_; - const size_t index = OffsetToIndex(offset); - const word mask = OffsetToMask(offset); - word* const address = &bitmap_begin_[index]; - DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; - word old_word; - do { - old_word = *address; - // Fast path: The bit is already set. - if ((old_word & mask) != 0) { - return true; - } - } while (UNLIKELY(android_atomic_cas(old_word, old_word | mask, address) != 0)); - return false; - } + bool AtomicTestAndSet(const mirror::Object* obj); void Clear(); - inline bool Test(const Object* obj) const { - uintptr_t addr = reinterpret_cast<uintptr_t>(obj); - DCHECK(HasAddress(obj)) << obj; - DCHECK(bitmap_begin_ != NULL); - DCHECK_GE(addr, heap_begin_); - const uintptr_t offset = addr - heap_begin_; - return (bitmap_begin_[OffsetToIndex(offset)] & OffsetToMask(offset)) != 0; - } + bool Test(const mirror::Object* obj) const; // Return true iff <obj> is within the range of pointers that this bitmap could potentially cover, // even if a bit has not been set for it. @@ -123,7 +97,7 @@ class SpaceBitmap { : bitmap_(bitmap) { } - void operator ()(Object* obj) const { + void operator ()(mirror::Object* obj) const { bitmap_->Clear(obj); } private: @@ -133,86 +107,21 @@ class SpaceBitmap { template <typename Visitor> void VisitRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const { for (; visit_begin < visit_end; visit_begin += kAlignment ) { - visitor(reinterpret_cast<Object*>(visit_begin)); + visitor(reinterpret_cast<mirror::Object*>(visit_begin)); } } template <typename Visitor, typename FingerVisitor> void VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor, const FingerVisitor& finger_visitor) const - EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { - DCHECK_LT(visit_begin, visit_end); - - const size_t word_span = kAlignment * kBitsPerWord; // Equals IndexToOffset(1). - const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment; - const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment; - - size_t word_start = bit_index_start / kBitsPerWord; - size_t word_end = bit_index_end / kBitsPerWord; - DCHECK_LT(word_end * kWordSize, Size()); - - // Trim off left_bits of left bits. - size_t edge_word = bitmap_begin_[word_start]; - - // Handle bits on the left first as a special case - size_t left_bits = bit_index_start & (kBitsPerWord - 1); - if (left_bits != 0) { - edge_word &= (1 << (kBitsPerWord - left_bits)) - 1; - } - - // If word_start == word_end then handle this case at the same place we handle the right edge. - if (edge_word != 0 && word_start < word_end) { - uintptr_t ptr_base = IndexToOffset(word_start) + heap_begin_; - finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); - do { - const size_t shift = CLZ(edge_word); - Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); - visitor(obj); - edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; - } while (edge_word != 0); - } - word_start++; - - for (size_t i = word_start; i < word_end; i++) { - size_t w = bitmap_begin_[i]; - if (w != 0) { - uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; - finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); - do { - const size_t shift = CLZ(w); - Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); - visitor(obj); - w ^= static_cast<size_t>(kWordHighBitMask) >> shift; - } while (w != 0); - } - } - - // Handle the right edge, and also the left edge if both edges are on the same word. - size_t right_bits = bit_index_end & (kBitsPerWord - 1); - - // If word_start == word_end then we need to use the word which we removed the left bits. - if (word_start <= word_end) { - edge_word = bitmap_begin_[word_end]; - } - - // Bits that we trim off the right. - edge_word &= ~((static_cast<size_t>(kWordHighBitMask) >> right_bits) - 1); - uintptr_t ptr_base = IndexToOffset(word_end) + heap_begin_; - finger_visitor(reinterpret_cast<void*>(ptr_base + word_span)); - while (edge_word != 0) { - const size_t shift = CLZ(edge_word); - Object* obj = reinterpret_cast<Object*>(ptr_base + shift * kAlignment); - visitor(obj); - edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; - } - } + EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Walk(Callback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); void InOrderWalk(Callback* callback, void* arg) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); static void SweepWalk(const SpaceBitmap& live, const SpaceBitmap& mark, @@ -251,7 +160,7 @@ class SpaceBitmap { std::string GetName() const; void SetName(const std::string& name); - const void* GetObjectWordAddress(const Object* obj) const { + const void* GetObjectWordAddress(const mirror::Object* obj) const { uintptr_t addr = reinterpret_cast<uintptr_t>(obj); const uintptr_t offset = addr - heap_begin_; const size_t index = OffsetToIndex(offset); @@ -265,22 +174,7 @@ class SpaceBitmap { heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)), name_(name) {} - inline bool Modify(const Object* obj, bool do_set) { - uintptr_t addr = reinterpret_cast<uintptr_t>(obj); - DCHECK_GE(addr, heap_begin_); - const uintptr_t offset = addr - heap_begin_; - const size_t index = OffsetToIndex(offset); - const word mask = OffsetToMask(offset); - DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; - word* address = &bitmap_begin_[index]; - word old_word = *address; - if (do_set) { - *address = old_word | mask; - } else { - *address = old_word & ~mask; - } - return (old_word & mask) != 0; - } + bool Modify(const mirror::Object* obj, bool do_set); // Backing storage for bitmap. UniquePtr<MemMap> mem_map_; @@ -302,17 +196,17 @@ class SpaceBitmap { // Like a bitmap except it keeps track of objects using sets. class SpaceSetMap { public: - typedef std::set<const Object*> Objects; + typedef std::set<const mirror::Object*> Objects; bool IsEmpty() const { return contained_.empty(); } - inline void Set(const Object* obj) { + inline void Set(const mirror::Object* obj) { contained_.insert(obj); } - inline void Clear(const Object* obj) { + inline void Clear(const mirror::Object* obj) { Objects::iterator found = contained_.find(obj); if (found != contained_.end()) { contained_.erase(found); @@ -323,7 +217,7 @@ class SpaceSetMap { contained_.clear(); } - inline bool Test(const Object* obj) const { + inline bool Test(const mirror::Object* obj) const { return contained_.find(obj) != contained_.end(); } @@ -357,4 +251,4 @@ std::ostream& operator << (std::ostream& stream, const SpaceBitmap& bitmap); } // namespace art -#endif // ART_SRC_SPACE_BITMAP_H_ +#endif // ART_SRC_GC_SPACE_BITMAP_H_ diff --git a/src/gc/space_bitmap_test.cc b/src/gc/space_bitmap_test.cc index a2f1afc304..5a829e4f66 100644 --- a/src/gc/space_bitmap_test.cc +++ b/src/gc/space_bitmap_test.cc @@ -19,6 +19,7 @@ #include "common_test.h" #include "dlmalloc.h" #include "globals.h" +#include "space_bitmap-inl.h" #include "UniquePtr.h" #include <stdint.h> @@ -39,20 +40,20 @@ TEST_F(SpaceBitmapTest, Init) { class BitmapVerify { public: - BitmapVerify(SpaceBitmap* bitmap, const Object* begin, const Object* end) + BitmapVerify(SpaceBitmap* bitmap, const mirror::Object* begin, const mirror::Object* end) : bitmap_(bitmap), begin_(begin), end_(end) {} - void operator ()(const Object* obj) { + void operator ()(const mirror::Object* obj) { EXPECT_TRUE(obj >= begin_); EXPECT_TRUE(obj <= end_); EXPECT_TRUE(bitmap_->Test(obj) == ((reinterpret_cast<uintptr_t>(obj) & 0xF) != 0)); } SpaceBitmap* bitmap_; - const Object* begin_; - const Object* end_; + const mirror::Object* begin_; + const mirror::Object* end_; }; TEST_F(SpaceBitmapTest, ScanRange) { @@ -65,7 +66,8 @@ TEST_F(SpaceBitmapTest, ScanRange) { // Set all the odd bits in the first BitsPerWord * 3 to one. for (size_t j = 0;j < kBitsPerWord * 3; ++j) { - const Object* obj = reinterpret_cast<Object*>(heap_begin + j * SpaceBitmap::kAlignment); + const mirror::Object* obj = + reinterpret_cast<mirror::Object*>(heap_begin + j * SpaceBitmap::kAlignment); if (reinterpret_cast<uintptr_t>(obj) & 0xF) { space_bitmap->Set(obj); } @@ -75,9 +77,11 @@ TEST_F(SpaceBitmapTest, ScanRange) { // This handles all the cases, having runs which start and end on the same word, and different // words. for (size_t i = 0; i < static_cast<size_t>(kBitsPerWord); ++i) { - Object* start = reinterpret_cast<Object*>(heap_begin + i * SpaceBitmap::kAlignment); + mirror::Object* start = + reinterpret_cast<mirror::Object*>(heap_begin + i * SpaceBitmap::kAlignment); for (size_t j = 0; j < static_cast<size_t>(kBitsPerWord * 2); ++j) { - Object* end = reinterpret_cast<Object*>(heap_begin + (i + j) * SpaceBitmap::kAlignment); + mirror::Object* end = + reinterpret_cast<mirror::Object*>(heap_begin + (i + j) * SpaceBitmap::kAlignment); BitmapVerify(space_bitmap.get(), start, end); } } diff --git a/src/gc/space_test.cc b/src/gc/space_test.cc index 2e03eae0cc..372ec7710c 100644 --- a/src/gc/space_test.cc +++ b/src/gc/space_test.cc @@ -83,23 +83,23 @@ TEST_F(SpaceTest, ZygoteSpace) { Thread* self = Thread::Current(); // Succeeds, fits without adjusting the footprint limit. - Object* ptr1 = space->Alloc(self, 1 * MB); + mirror::Object* ptr1 = space->Alloc(self, 1 * MB); EXPECT_TRUE(ptr1 != NULL); // Fails, requires a higher footprint limit. - Object* ptr2 = space->Alloc(self, 8 * MB); + mirror::Object* ptr2 = space->Alloc(self, 8 * MB); EXPECT_TRUE(ptr2 == NULL); // Succeeds, adjusts the footprint. - Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); + mirror::Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr3 != NULL); // Fails, requires a higher footprint limit. - Object* ptr4 = space->Alloc(self, 8 * MB); + mirror::Object* ptr4 = space->Alloc(self, 8 * MB); EXPECT_TRUE(ptr4 == NULL); // Also fails, requires a higher allowed footprint. - Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); + mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr5 == NULL); // Release some memory. @@ -151,23 +151,23 @@ TEST_F(SpaceTest, AllocAndFree) { Runtime::Current()->GetHeap()->AddSpace(space); // Succeeds, fits without adjusting the footprint limit. - Object* ptr1 = space->Alloc(self, 1 * MB); + mirror::Object* ptr1 = space->Alloc(self, 1 * MB); EXPECT_TRUE(ptr1 != NULL); // Fails, requires a higher footprint limit. - Object* ptr2 = space->Alloc(self, 8 * MB); + mirror::Object* ptr2 = space->Alloc(self, 8 * MB); EXPECT_TRUE(ptr2 == NULL); // Succeeds, adjusts the footprint. - Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); + mirror::Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr3 != NULL); // Fails, requires a higher footprint limit. - Object* ptr4 = space->Alloc(self, 8 * MB); + mirror::Object* ptr4 = space->Alloc(self, 8 * MB); EXPECT_TRUE(ptr4 == NULL); // Also fails, requires a higher allowed footprint. - Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); + mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr5 == NULL); // Release some memory. @@ -194,7 +194,7 @@ TEST_F(SpaceTest, AllocAndFreeList) { Thread* self = Thread::Current(); // Succeeds, fits without adjusting the max allowed footprint. - Object* lots_of_objects[1024]; + mirror::Object* lots_of_objects[1024]; for (size_t i = 0; i < arraysize(lots_of_objects); i++) { lots_of_objects[i] = space->Alloc(self, 16); EXPECT_TRUE(lots_of_objects[i] != NULL); @@ -252,7 +252,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(DlMallocSpace* space, intptr // Fill the space with lots of small objects up to the growth limit size_t max_objects = (growth_limit / (object_size > 0 ? object_size : 8)) + 1; - UniquePtr<Object*[]> lots_of_objects(new Object*[max_objects]); + UniquePtr<mirror::Object*[]> lots_of_objects(new mirror::Object*[max_objects]); size_t last_object = 0; // last object for which allocation succeeded size_t amount_allocated = 0; // amount of space allocated Thread* self = Thread::Current(); @@ -269,7 +269,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(DlMallocSpace* space, intptr alloc_size = 8; } } - Object* object; + mirror::Object* object; if (round <= 1) { object = space->Alloc(self, alloc_size); } else { @@ -326,7 +326,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(DlMallocSpace* space, intptr // Free some objects for (size_t i = 0; i < last_object; i += free_increment) { - Object* object = lots_of_objects.get()[i]; + mirror::Object* object = lots_of_objects.get()[i]; if (object == NULL) { continue; } @@ -347,7 +347,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(DlMallocSpace* space, intptr } // All memory was released, try a large allocation to check freed memory is being coalesced - Object* large_object; + mirror::Object* large_object; size_t three_quarters_space = (growth_limit / 2) + (growth_limit / 4); if (round <= 1) { large_object = space->Alloc(self, three_quarters_space); diff --git a/src/gc/sticky_mark_sweep.cc b/src/gc/sticky_mark_sweep.cc index 23196fda25..988d4e79e7 100644 --- a/src/gc/sticky_mark_sweep.cc +++ b/src/gc/sticky_mark_sweep.cc @@ -14,47 +14,51 @@ * limitations under the License. */ +#include "heap.h" #include "large_object_space.h" #include "space.h" #include "sticky_mark_sweep.h" +#include "thread.h" namespace art { - StickyMarkSweep::StickyMarkSweep(Heap* heap, bool is_concurrent) - : PartialMarkSweep(heap, is_concurrent) { - cumulative_timings_.SetName(GetName()); - } - StickyMarkSweep::~StickyMarkSweep() { +StickyMarkSweep::StickyMarkSweep(Heap* heap, bool is_concurrent) + : PartialMarkSweep(heap, is_concurrent) { + cumulative_timings_.SetName(GetName()); +} - } +StickyMarkSweep::~StickyMarkSweep() { - void StickyMarkSweep::BindBitmaps() { - PartialMarkSweep::BindBitmaps(); - - Spaces& spaces = GetHeap()->GetSpaces(); - WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); - // For sticky GC, we want to bind the bitmaps of both the zygote space and the alloc space. - // This lets us start with the mark bitmap of the previous garbage collection as the current - // mark bitmap of the alloc space. After the sticky GC finishes, we then unbind the bitmaps, - // making it so that the live bitmap of the alloc space is contains the newly marked objects - // from the sticky GC. - for (Spaces::iterator it = spaces.begin(); it != spaces.end(); ++it) { - if ((*it)->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect) { - BindLiveToMarkBitmap(*it); - } - } +} - GetHeap()->GetLargeObjectsSpace()->CopyLiveToMarked(); - } +void StickyMarkSweep::BindBitmaps() { + PartialMarkSweep::BindBitmaps(); - void StickyMarkSweep::MarkReachableObjects() { - DisableFinger(); - RecursiveMarkDirtyObjects(CardTable::kCardDirty - 1); + Spaces& spaces = GetHeap()->GetSpaces(); + WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); + // For sticky GC, we want to bind the bitmaps of both the zygote space and the alloc space. + // This lets us start with the mark bitmap of the previous garbage collection as the current + // mark bitmap of the alloc space. After the sticky GC finishes, we then unbind the bitmaps, + // making it so that the live bitmap of the alloc space is contains the newly marked objects + // from the sticky GC. + for (Spaces::iterator it = spaces.begin(); it != spaces.end(); ++it) { + if ((*it)->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect) { + BindLiveToMarkBitmap(*it); + } } - void StickyMarkSweep::Sweep(TimingLogger& timings, bool swap_bitmaps) { - ObjectStack* live_stack = GetHeap()->GetLiveStack(); - SweepArray(timings_, live_stack, false); - timings_.AddSplit("SweepArray"); - } + GetHeap()->GetLargeObjectsSpace()->CopyLiveToMarked(); +} + +void StickyMarkSweep::MarkReachableObjects() { + DisableFinger(); + RecursiveMarkDirtyObjects(CardTable::kCardDirty - 1); +} + +void StickyMarkSweep::Sweep(TimingLogger& timings, bool swap_bitmaps) { + ObjectStack* live_stack = GetHeap()->GetLiveStack(); + SweepArray(timings_, live_stack, false); + timings_.AddSplit("SweepArray"); +} + } // namespace art diff --git a/src/gc/sticky_mark_sweep.h b/src/gc/sticky_mark_sweep.h index 8396bbe09a..41ab0cc807 100644 --- a/src/gc/sticky_mark_sweep.h +++ b/src/gc/sticky_mark_sweep.h @@ -14,28 +14,15 @@ * limitations under the License. */ -#ifndef ART_SRC_STICKY_MARK_SWEEP_H_ -#define ART_SRC_STICKY_MARK_SWEEP_H_ +#ifndef ART_SRC_GC_STICKY_MARK_SWEEP_H_ +#define ART_SRC_GC_STICKY_MARK_SWEEP_H_ #include "base/macros.h" #include "locks.h" #include "partial_mark_sweep.h" -#include "utils.h" namespace art { -class Barrier; -class CheckObjectVisitor; -class Class; -class Heap; -class MarkIfReachesAllocspaceVisitor; -class ModUnionClearCardVisitor; -class ModUnionVisitor; -class ModUnionTableBitmap; -class Object; -class TimingLogger; -class MarkStackChunk; - class StickyMarkSweep : public PartialMarkSweep { public: virtual GcType GetGcType() const { @@ -60,4 +47,4 @@ protected: } // namespace art -#endif // ART_SRC_STICKY_MARK_SWEEP_H_ +#endif // ART_SRC_GC_STICKY_MARK_SWEEP_H_ diff --git a/src/heap.cc b/src/heap.cc index 805d63c576..5c96decdd9 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -27,15 +27,24 @@ #include "debugger.h" #include "gc/atomic_stack.h" #include "gc/card_table.h" +#include "gc/card_table-inl.h" #include "gc/heap_bitmap.h" +#include "gc/heap_bitmap-inl.h" #include "gc/large_object_space.h" #include "gc/mark_sweep.h" +#include "gc/mark_sweep-inl.h" #include "gc/partial_mark_sweep.h" +#include "gc/space_bitmap-inl.h" #include "gc/sticky_mark_sweep.h" #include "gc/mod_union_table.h" +#include "gc/mod_union_table-inl.h" #include "gc/space.h" #include "image.h" -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/object.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "os.h" #include "ScopedLocalRef.h" @@ -431,7 +440,7 @@ Heap::~Heap() { delete gc_complete_lock_; } -ContinuousSpace* Heap::FindSpaceFromObject(const Object* obj) const { +ContinuousSpace* Heap::FindSpaceFromObject(const mirror::Object* obj) const { // TODO: C++0x auto for (Spaces::const_iterator it = spaces_.begin(); it != spaces_.end(); ++it) { if ((*it)->Contains(obj)) { @@ -465,13 +474,13 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void* } } -Object* Heap::AllocObject(Thread* self, Class* c, size_t byte_count) { - DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(Class)) || +mirror::Object* Heap::AllocObject(Thread* self, mirror::Class* c, size_t byte_count) { + DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) || (c->IsVariableSize() || c->GetObjectSize() == byte_count) || strlen(ClassHelper(c).GetDescriptor()) == 0); - DCHECK_GE(byte_count, sizeof(Object)); + DCHECK_GE(byte_count, sizeof(mirror::Object)); - Object* obj = NULL; + mirror::Object* obj = NULL; size_t size = 0; uint64_t allocation_start = 0; if (measure_allocation_time_) { @@ -513,7 +522,7 @@ Object* Heap::AllocObject(Thread* self, Class* c, size_t byte_count) { // concurrent_start_bytes_. concurrent_start_bytes_ = std::numeric_limits<size_t>::max(); // The SirtRef is necessary since the calls in RequestConcurrentGC are a safepoint. - SirtRef<Object> ref(self, obj); + SirtRef<mirror::Object> ref(self, obj); RequestConcurrentGC(self); } VerifyObject(obj); @@ -547,7 +556,7 @@ Object* Heap::AllocObject(Thread* self, Class* c, size_t byte_count) { return NULL; } -bool Heap::IsHeapAddress(const Object* obj) { +bool Heap::IsHeapAddress(const mirror::Object* obj) { // Note: we deliberately don't take the lock here, and mustn't test anything that would // require taking the lock. if (obj == NULL) { @@ -566,7 +575,7 @@ bool Heap::IsHeapAddress(const Object* obj) { return large_object_space_->Contains(obj); } -bool Heap::IsLiveObjectLocked(const Object* obj) { +bool Heap::IsLiveObjectLocked(const mirror::Object* obj) { Locks::heap_bitmap_lock_->AssertReaderHeld(Thread::Current()); return IsHeapAddress(obj) && GetLiveBitmap()->Test(obj); } @@ -596,7 +605,7 @@ void Heap::DumpSpaces() { } } -void Heap::VerifyObjectBody(const Object* obj) { +void Heap::VerifyObjectBody(const mirror::Object* obj) { if (!IsAligned<kObjectAlignment>(obj)) { LOG(FATAL) << "Object isn't aligned: " << obj; } @@ -618,8 +627,8 @@ void Heap::VerifyObjectBody(const Object* obj) { // Ignore early dawn of the universe verifications if (!VERIFY_OBJECT_FAST && GetObjectsAllocated() > 10) { const byte* raw_addr = reinterpret_cast<const byte*>(obj) + - Object::ClassOffset().Int32Value(); - const Class* c = *reinterpret_cast<Class* const *>(raw_addr); + mirror::Object::ClassOffset().Int32Value(); + const mirror::Class* c = *reinterpret_cast<mirror::Class* const *>(raw_addr); if (c == NULL) { LOG(FATAL) << "Null class in object: " << obj; } else if (!IsAligned<kObjectAlignment>(c)) { @@ -630,15 +639,15 @@ void Heap::VerifyObjectBody(const Object* obj) { // Check obj.getClass().getClass() == obj.getClass().getClass().getClass() // Note: we don't use the accessors here as they have internal sanity checks // that we don't want to run - raw_addr = reinterpret_cast<const byte*>(c) + Object::ClassOffset().Int32Value(); - const Class* c_c = *reinterpret_cast<Class* const *>(raw_addr); - raw_addr = reinterpret_cast<const byte*>(c_c) + Object::ClassOffset().Int32Value(); - const Class* c_c_c = *reinterpret_cast<Class* const *>(raw_addr); + raw_addr = reinterpret_cast<const byte*>(c) + mirror::Object::ClassOffset().Int32Value(); + const mirror::Class* c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr); + raw_addr = reinterpret_cast<const byte*>(c_c) + mirror::Object::ClassOffset().Int32Value(); + const mirror::Class* c_c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr); CHECK_EQ(c_c, c_c_c); } } -void Heap::VerificationCallback(Object* obj, void* arg) { +void Heap::VerificationCallback(mirror::Object* obj, void* arg) { DCHECK(obj != NULL); reinterpret_cast<Heap*>(arg)->VerifyObjectBody(obj); } @@ -648,7 +657,7 @@ void Heap::VerifyHeap() { GetLiveBitmap()->Walk(Heap::VerificationCallback, this); } -void Heap::RecordAllocation(size_t size, Object* obj) { +void Heap::RecordAllocation(size_t size, mirror::Object* obj) { DCHECK(obj != NULL); DCHECK_GT(size, 0u); num_bytes_allocated_ += size; @@ -687,7 +696,7 @@ void Heap::RecordFree(size_t freed_objects, size_t freed_bytes) { } } -Object* Heap::TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) { +mirror::Object* Heap::TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) { // Should we try to use a CAS here and fix up num_bytes_allocated_ later with AllocationSize? if (num_bytes_allocated_ + alloc_size > max_allowed_footprint_) { // max_allowed_footprint_ <= growth_limit_ so it is safe to check in here. @@ -711,13 +720,13 @@ Object* Heap::TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, return space->Alloc(self, alloc_size); } -Object* Heap::Allocate(Thread* self, AllocSpace* space, size_t alloc_size) { +mirror::Object* Heap::Allocate(Thread* self, AllocSpace* space, size_t alloc_size) { // Since allocation can cause a GC which will need to SuspendAll, make sure all allocations are // done in the runnable state where suspension is expected. DCHECK_EQ(self->GetState(), kRunnable); self->AssertThreadSuspensionIsAllowable(); - Object* ptr = TryToAllocate(self, space, alloc_size, false); + mirror::Object* ptr = TryToAllocate(self, space, alloc_size, false); if (ptr != NULL) { return ptr; } @@ -838,14 +847,14 @@ size_t Heap::GetTotalBytesAllocated() const { class InstanceCounter { public: - InstanceCounter(const std::vector<Class*>& classes, bool use_is_assignable_from, uint64_t* counts) + InstanceCounter(const std::vector<mirror::Class*>& classes, bool use_is_assignable_from, uint64_t* counts) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : classes_(classes), use_is_assignable_from_(use_is_assignable_from), counts_(counts) { } - void operator()(const Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { for (size_t i = 0; i < classes_.size(); ++i) { - const Class* instance_class = o->GetClass(); + const mirror::Class* instance_class = o->GetClass(); if (use_is_assignable_from_) { if (instance_class != NULL && classes_[i]->IsAssignableFrom(instance_class)) { ++counts_[i]; @@ -859,14 +868,14 @@ class InstanceCounter { } private: - const std::vector<Class*>& classes_; + const std::vector<mirror::Class*>& classes_; bool use_is_assignable_from_; uint64_t* const counts_; DISALLOW_COPY_AND_ASSIGN(InstanceCounter); }; -void Heap::CountInstances(const std::vector<Class*>& classes, bool use_is_assignable_from, +void Heap::CountInstances(const std::vector<mirror::Class*>& classes, bool use_is_assignable_from, uint64_t* counts) { // We only want reachable instances, so do a GC. This also ensures that the alloc stack // is empty, so the live bitmap is the only place we need to look. @@ -882,29 +891,30 @@ void Heap::CountInstances(const std::vector<Class*>& classes, bool use_is_assign class InstanceCollector { public: - InstanceCollector(Class* c, int32_t max_count, std::vector<Object*>& instances) + InstanceCollector(mirror::Class* c, int32_t max_count, std::vector<mirror::Object*>& instances) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : class_(c), max_count_(max_count), instances_(instances) { } - void operator()(const Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const Class* instance_class = o->GetClass(); + void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const mirror::Class* instance_class = o->GetClass(); if (instance_class == class_) { if (max_count_ == 0 || instances_.size() < max_count_) { - instances_.push_back(const_cast<Object*>(o)); + instances_.push_back(const_cast<mirror::Object*>(o)); } } } private: - Class* class_; + mirror::Class* class_; uint32_t max_count_; - std::vector<Object*>& instances_; + std::vector<mirror::Object*>& instances_; DISALLOW_COPY_AND_ASSIGN(InstanceCollector); }; -void Heap::GetInstances(Class* c, int32_t max_count, std::vector<Object*>& instances) { +void Heap::GetInstances(mirror::Class* c, int32_t max_count, + std::vector<mirror::Object*>& instances) { // We only want reachable instances, so do a GC. This also ensures that the alloc stack // is empty, so the live bitmap is the only place we need to look. Thread* self = Thread::Current(); @@ -919,7 +929,8 @@ void Heap::GetInstances(Class* c, int32_t max_count, std::vector<Object*>& insta class ReferringObjectsFinder { public: - ReferringObjectsFinder(Object* object, int32_t max_count, std::vector<Object*>& referring_objects) + ReferringObjectsFinder(mirror::Object* object, int32_t max_count, + std::vector<mirror::Object*>& referring_objects) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : object_(object), max_count_(max_count), referring_objects_(referring_objects) { } @@ -927,27 +938,28 @@ class ReferringObjectsFinder { // For bitmap Visit. // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for // annotalysis on visitors. - void operator()(const Object* o) const NO_THREAD_SAFETY_ANALYSIS { + void operator()(const mirror::Object* o) const NO_THREAD_SAFETY_ANALYSIS { MarkSweep::VisitObjectReferences(o, *this); } // For MarkSweep::VisitObjectReferences. - void operator ()(const Object* referrer, const Object* object, const MemberOffset&, bool) const { + void operator ()(const mirror::Object* referrer, const mirror::Object* object, + const MemberOffset&, bool) const { if (object == object_ && (max_count_ == 0 || referring_objects_.size() < max_count_)) { - referring_objects_.push_back(const_cast<Object*>(referrer)); + referring_objects_.push_back(const_cast<mirror::Object*>(referrer)); } } private: - Object* object_; + mirror::Object* object_; uint32_t max_count_; - std::vector<Object*>& referring_objects_; + std::vector<mirror::Object*>& referring_objects_; DISALLOW_COPY_AND_ASSIGN(ReferringObjectsFinder); }; -void Heap::GetReferringObjects(Object* o, int32_t max_count, - std::vector<Object*>& referring_objects) { +void Heap::GetReferringObjects(mirror::Object* o, int32_t max_count, + std::vector<mirror::Object*>& referring_objects) { // We only want reachable instances, so do a GC. This also ensures that the alloc stack // is empty, so the live bitmap is the only place we need to look. Thread* self = Thread::Current(); @@ -1026,9 +1038,9 @@ size_t Heap::GetUsedMemorySize() const { } void Heap::MarkAllocStack(SpaceBitmap* bitmap, SpaceSetMap* large_objects, ObjectStack* stack) { - Object** limit = stack->End(); - for (Object** it = stack->Begin(); it != limit; ++it) { - const Object* obj = *it; + mirror::Object** limit = stack->End(); + for (mirror::Object** it = stack->Begin(); it != limit; ++it) { + const mirror::Object* obj = *it; DCHECK(obj != NULL); if (LIKELY(bitmap->HasAddress(obj))) { bitmap->Set(obj); @@ -1039,9 +1051,9 @@ void Heap::MarkAllocStack(SpaceBitmap* bitmap, SpaceSetMap* large_objects, Objec } void Heap::UnMarkAllocStack(SpaceBitmap* bitmap, SpaceSetMap* large_objects, ObjectStack* stack) { - Object** limit = stack->End(); - for (Object** it = stack->Begin(); it != limit; ++it) { - const Object* obj = *it; + mirror::Object** limit = stack->End(); + for (mirror::Object** it = stack->Begin(); it != limit; ++it) { + const mirror::Object* obj = *it; DCHECK(obj != NULL); if (LIKELY(bitmap->HasAddress(obj))) { bitmap->Clear(obj); @@ -1187,8 +1199,8 @@ void Heap::UpdateAndMarkModUnion(MarkSweep* mark_sweep, TimingLogger& timings, G timings.AddSplit("MarkImageToAllocSpaceReferences"); } -void Heap::RootMatchesObjectVisitor(const Object* root, void* arg) { - Object* obj = reinterpret_cast<Object*>(arg); +void Heap::RootMatchesObjectVisitor(const mirror::Object* root, void* arg) { + mirror::Object* obj = reinterpret_cast<mirror::Object*>(arg); if (root == obj) { LOG(INFO) << "Object " << obj << " is a root"; } @@ -1196,7 +1208,7 @@ void Heap::RootMatchesObjectVisitor(const Object* root, void* arg) { class ScanVisitor { public: - void operator ()(const Object* obj) const { + void operator ()(const mirror::Object* obj) const { LOG(INFO) << "Would have rescanned object " << obj; } }; @@ -1212,8 +1224,9 @@ class VerifyReferenceVisitor { // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for smarter // analysis. - void operator ()(const Object* obj, const Object* ref, const MemberOffset& /* offset */, - bool /* is_static */) const NO_THREAD_SAFETY_ANALYSIS { + void operator ()(const mirror::Object* obj, const mirror::Object* ref, + const MemberOffset& /* offset */, bool /* is_static */) const + NO_THREAD_SAFETY_ANALYSIS { // Verify that the reference is live. if (ref != NULL && !IsLive(ref)) { CardTable* card_table = heap_->GetCardTable(); @@ -1260,7 +1273,7 @@ class VerifyReferenceVisitor { } } - bool IsLive(const Object* obj) const NO_THREAD_SAFETY_ANALYSIS { + bool IsLive(const mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS { if (heap_->GetLiveBitmap()->Test(obj)) { return true; } @@ -1284,7 +1297,7 @@ class VerifyObjectVisitor { } - void operator ()(const Object* obj) const + void operator ()(const mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { VerifyReferenceVisitor visitor(heap_, const_cast<bool*>(&failed_)); MarkSweep::VisitObjectReferences(obj, visitor); @@ -1328,8 +1341,8 @@ class VerifyReferenceCardVisitor { // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for // annotalysis on visitors. - void operator ()(const Object* obj, const Object* ref, const MemberOffset& offset, - bool is_static) const NO_THREAD_SAFETY_ANALYSIS { + void operator ()(const mirror::Object* obj, const mirror::Object* ref, const MemberOffset& offset, + bool is_static) const NO_THREAD_SAFETY_ANALYSIS { // Filter out class references since changing an object's class does not mark the card as dirty. // Also handles large objects, since the only reference they hold is a class reference. if (ref != NULL && !ref->IsClass()) { @@ -1355,12 +1368,13 @@ class VerifyReferenceCardVisitor { // Print which field of the object is dead. if (!obj->IsObjectArray()) { - const Class* klass = is_static ? obj->AsClass() : obj->GetClass(); + const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass(); CHECK(klass != NULL); - const ObjectArray<Field>* fields = is_static ? klass->GetSFields() : klass->GetIFields(); + const mirror::ObjectArray<mirror::Field>* fields = is_static ? klass->GetSFields() + : klass->GetIFields(); CHECK(fields != NULL); for (int32_t i = 0; i < fields->GetLength(); ++i) { - const Field* cur = fields->Get(i); + const mirror::Field* cur = fields->Get(i); if (cur->GetOffset().Int32Value() == offset.Int32Value()) { LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is " << PrettyField(cur); @@ -1368,7 +1382,8 @@ class VerifyReferenceCardVisitor { } } } else { - const ObjectArray<Object>* object_array = obj->AsObjectArray<Object>(); + const mirror::ObjectArray<mirror::Object>* object_array = + obj->AsObjectArray<mirror::Object>(); for (int32_t i = 0; i < object_array->GetLength(); ++i) { if (object_array->Get(i) == ref) { LOG(ERROR) << (is_static ? "Static " : "") << "obj[" << i << "] = ref"; @@ -1395,7 +1410,7 @@ class VerifyLiveStackReferences { } - void operator ()(const Object* obj) const + void operator ()(const mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { VerifyReferenceCardVisitor visitor(heap_, const_cast<bool*>(&failed_)); MarkSweep::VisitObjectReferences(obj, visitor); @@ -1419,7 +1434,7 @@ bool Heap::VerifyMissingCardMarks() { GetLiveBitmap()->Visit(visitor); // We can verify objects in the live stack since none of these should reference dead objects. - for (Object** it = live_stack_->Begin(); it != live_stack_->End(); ++it) { + for (mirror::Object** it = live_stack_->Begin(); it != live_stack_->End(); ++it) { visitor(*it); } @@ -1636,34 +1651,36 @@ void Heap::SetReferenceOffsets(MemberOffset reference_referent_offset, CHECK_NE(finalizer_reference_zombie_offset_.Uint32Value(), 0U); } -Object* Heap::GetReferenceReferent(Object* reference) { +mirror::Object* Heap::GetReferenceReferent(mirror::Object* reference) { DCHECK(reference != NULL); DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U); - return reference->GetFieldObject<Object*>(reference_referent_offset_, true); + return reference->GetFieldObject<mirror::Object*>(reference_referent_offset_, true); } -void Heap::ClearReferenceReferent(Object* reference) { +void Heap::ClearReferenceReferent(mirror::Object* reference) { DCHECK(reference != NULL); DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U); reference->SetFieldObject(reference_referent_offset_, NULL, true); } // Returns true if the reference object has not yet been enqueued. -bool Heap::IsEnqueuable(const Object* ref) { +bool Heap::IsEnqueuable(const mirror::Object* ref) { DCHECK(ref != NULL); - const Object* queue = ref->GetFieldObject<Object*>(reference_queue_offset_, false); - const Object* queue_next = ref->GetFieldObject<Object*>(reference_queueNext_offset_, false); + const mirror::Object* queue = + ref->GetFieldObject<mirror::Object*>(reference_queue_offset_, false); + const mirror::Object* queue_next = + ref->GetFieldObject<mirror::Object*>(reference_queueNext_offset_, false); return (queue != NULL) && (queue_next == NULL); } -void Heap::EnqueueReference(Object* ref, Object** cleared_reference_list) { +void Heap::EnqueueReference(mirror::Object* ref, mirror::Object** cleared_reference_list) { DCHECK(ref != NULL); - CHECK(ref->GetFieldObject<Object*>(reference_queue_offset_, false) != NULL); - CHECK(ref->GetFieldObject<Object*>(reference_queueNext_offset_, false) == NULL); + CHECK(ref->GetFieldObject<mirror::Object*>(reference_queue_offset_, false) != NULL); + CHECK(ref->GetFieldObject<mirror::Object*>(reference_queueNext_offset_, false) == NULL); EnqueuePendingReference(ref, cleared_reference_list); } -void Heap::EnqueuePendingReference(Object* ref, Object** list) { +void Heap::EnqueuePendingReference(mirror::Object* ref, mirror::Object** list) { DCHECK(ref != NULL); DCHECK(list != NULL); @@ -1673,17 +1690,19 @@ void Heap::EnqueuePendingReference(Object* ref, Object** list) { ref->SetFieldObject(reference_pendingNext_offset_, ref, false); *list = ref; } else { - Object* head = (*list)->GetFieldObject<Object*>(reference_pendingNext_offset_, false); + mirror::Object* head = + (*list)->GetFieldObject<mirror::Object*>(reference_pendingNext_offset_, false); ref->SetFieldObject(reference_pendingNext_offset_, head, false); (*list)->SetFieldObject(reference_pendingNext_offset_, ref, false); } } -Object* Heap::DequeuePendingReference(Object** list) { +mirror::Object* Heap::DequeuePendingReference(mirror::Object** list) { DCHECK(list != NULL); DCHECK(*list != NULL); - Object* head = (*list)->GetFieldObject<Object*>(reference_pendingNext_offset_, false); - Object* ref; + mirror::Object* head = (*list)->GetFieldObject<mirror::Object*>(reference_pendingNext_offset_, + false); + mirror::Object* ref; // Note: the following code is thread-safe because it is only called from ProcessReferences which // is single threaded. @@ -1691,7 +1710,8 @@ Object* Heap::DequeuePendingReference(Object** list) { ref = *list; *list = NULL; } else { - Object* next = head->GetFieldObject<Object*>(reference_pendingNext_offset_, false); + mirror::Object* next = head->GetFieldObject<mirror::Object*>(reference_pendingNext_offset_, + false); (*list)->SetFieldObject(reference_pendingNext_offset_, next, false); ref = head; } @@ -1699,7 +1719,7 @@ Object* Heap::DequeuePendingReference(Object** list) { return ref; } -void Heap::AddFinalizerReference(Thread* self, Object* object) { +void Heap::AddFinalizerReference(Thread* self, mirror::Object* object) { ScopedObjectAccess soa(self); JValue args[1]; args[0].SetL(object); @@ -1731,7 +1751,7 @@ size_t Heap::GetConcurrentMinFree() const { return concurrent_min_free_; } -void Heap::EnqueueClearedReferences(Object** cleared) { +void Heap::EnqueueClearedReferences(mirror::Object** cleared) { DCHECK(cleared != NULL); if (*cleared != NULL) { // When a runtime isn't started there are no reference queues to care about so ignore. diff --git a/src/heap.h b/src/heap.h index b7fc34d8ff..9981f835c8 100644 --- a/src/heap.h +++ b/src/heap.h @@ -24,6 +24,7 @@ #include "atomic_integer.h" #include "gc/atomic_stack.h" #include "gc/card_table.h" +#include "gc/gc_type.h" #include "gc/heap_bitmap.h" #include "globals.h" #include "gtest/gtest.h" @@ -39,9 +40,11 @@ #define VERIFY_OBJECT_FAST 1 namespace art { - -class AllocSpace; +namespace mirror { class Class; +class Object; +} // namespace mirror +class AllocSpace; class ConditionVariable; class DlMallocSpace; class GarbageCollector; @@ -51,14 +54,12 @@ class LargeObjectSpace; class MarkSweep; class ModUnionTable; class Mutex; -class Object; class Space; class SpaceTest; class StackVisitor; class Thread; class TimingLogger; -typedef AtomicStack<Object*> ObjectStack; typedef std::vector<ContinuousSpace*> Spaces; class AgeCardVisitor { @@ -72,21 +73,6 @@ class AgeCardVisitor { } }; -// The ordering of the enum matters, it is used to determine which GCs are run first. -enum GcType { - // No Gc - kGcTypeNone, - // Sticky mark bits "generational" GC. - kGcTypeSticky, - // Partial GC, over only the alloc space. - kGcTypePartial, - // Full GC - kGcTypeFull, - // Number of different Gc types. - kGcTypeMax, -}; -std::ostream& operator<<(std::ostream& os, const GcType& policy); - enum GcCause { kGcCauseForAlloc, kGcCauseBackground, @@ -107,11 +93,6 @@ class Heap { // Used so that we don't overflow the allocation time atomic integer. static const size_t kTimeAdjust = 1024; - typedef void (RootVisitor)(const Object* root, void* arg); - typedef void (VerifyRootVisitor)(const Object* root, void* arg, size_t vreg, - const StackVisitor* visitor); - typedef bool (IsMarkedTester)(const Object* object, void* arg); - // Create a heap with the requested sizes. The possible empty // image_file_names names specify Spaces to load based on // ImageWriter output. @@ -122,19 +103,19 @@ class Heap { ~Heap(); // Allocates and initializes storage for an object instance. - Object* AllocObject(Thread* self, Class* klass, size_t num_bytes) + mirror::Object* AllocObject(Thread* self, mirror::Class* klass, size_t num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Check sanity of given reference. Requires the heap lock. #if VERIFY_OBJECT_ENABLED - void VerifyObject(const Object* o); + void VerifyObject(const mirror::Object* o); #else - void VerifyObject(const Object*) {} + void VerifyObject(const mirror::Object*) {} #endif // Check sanity of all live references. Requires the heap lock. void VerifyHeap() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_); - static void RootMatchesObjectVisitor(const Object* root, void* arg); + static void RootMatchesObjectVisitor(const mirror::Object* root, void* arg); bool VerifyHeapReferences() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -145,11 +126,11 @@ class Heap { // A weaker test than IsLiveObject or VerifyObject that doesn't require the heap lock, // and doesn't abort on error, allowing the caller to report more // meaningful diagnostics. - bool IsHeapAddress(const Object* obj); + bool IsHeapAddress(const mirror::Object* obj); // Returns true if 'obj' is a live heap object, false otherwise (including for invalid addresses). // Requires the heap lock to be held. - bool IsLiveObjectLocked(const Object* obj) + bool IsLiveObjectLocked(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); // Initiates an explicit garbage collection. @@ -169,16 +150,16 @@ class Heap { // Implements VMDebug.countInstancesOfClass and JDWP VM_InstanceCount. // The boolean decides whether to use IsAssignableFrom or == when comparing classes. - void CountInstances(const std::vector<Class*>& classes, bool use_is_assignable_from, + void CountInstances(const std::vector<mirror::Class*>& classes, bool use_is_assignable_from, uint64_t* counts) LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Implements JDWP RT_Instances. - void GetInstances(Class* c, int32_t max_count, std::vector<Object*>& instances) + void GetInstances(mirror::Class* c, int32_t max_count, std::vector<mirror::Object*>& instances) LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Implements JDWP OR_ReferringObjects. - void GetReferringObjects(Object* o, int32_t max_count, std::vector<Object*>& referring_objects) + void GetReferringObjects(mirror::Object* o, int32_t max_count, std::vector<mirror::Object*>& referring_objects) LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -218,15 +199,15 @@ class Heap { MemberOffset reference_pendingNext_offset, MemberOffset finalizer_reference_zombie_offset); - Object* GetReferenceReferent(Object* reference); - void ClearReferenceReferent(Object* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Object* GetReferenceReferent(mirror::Object* reference); + void ClearReferenceReferent(mirror::Object* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns true if the reference object has not yet been enqueued. - bool IsEnqueuable(const Object* ref); - void EnqueueReference(Object* ref, Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void EnqueuePendingReference(Object* ref, Object** list) + bool IsEnqueuable(const mirror::Object* ref); + void EnqueueReference(mirror::Object* ref, mirror::Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void EnqueuePendingReference(mirror::Object* ref, mirror::Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* DequeuePendingReference(Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Object* DequeuePendingReference(mirror::Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); MemberOffset GetReferencePendingNextOffset() { DCHECK_NE(reference_pendingNext_offset_.Uint32Value(), 0U); @@ -257,12 +238,12 @@ class Heap { // Must be called if a field of an Object in the heap changes, and before any GC safe-point. // The call is not needed if NULL is stored in the field. - void WriteBarrierField(const Object* dst, MemberOffset /*offset*/, const Object* /*new_value*/) { + void WriteBarrierField(const mirror::Object* dst, MemberOffset /*offset*/, const mirror::Object* /*new_value*/) { card_table_->MarkCard(dst); } // Write barrier for array operations that update many field positions - void WriteBarrierArray(const Object* dst, int /*start_offset*/, + void WriteBarrierArray(const mirror::Object* dst, int /*start_offset*/, size_t /*length TODO: element_count or byte_count?*/) { card_table_->MarkCard(dst); } @@ -271,7 +252,7 @@ class Heap { return card_table_.get(); } - void AddFinalizerReference(Thread* self, Object* object); + void AddFinalizerReference(Thread* self, mirror::Object* object); size_t GetBytesAllocated() const; size_t GetObjectsAllocated() const; @@ -293,7 +274,7 @@ class Heap { // Functions for getting the bitmap which corresponds to an object's address. // This is probably slow, TODO: use better data structure like binary tree . - ContinuousSpace* FindSpaceFromObject(const Object*) const; + ContinuousSpace* FindSpaceFromObject(const mirror::Object*) const; void DumpForSigQuit(std::ostream& os); @@ -354,22 +335,22 @@ class Heap { private: // Allocates uninitialized storage. Passing in a null space tries to place the object in the // large object space. - Object* Allocate(Thread* self, AllocSpace* space, size_t num_bytes) + mirror::Object* Allocate(Thread* self, AllocSpace* space, size_t num_bytes) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Try to allocate a number of bytes, this function never does any GCs. - Object* TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) + mirror::Object* TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Pushes a list of cleared references out to the managed heap. - void EnqueueClearedReferences(Object** cleared_references); + void EnqueueClearedReferences(mirror::Object** cleared_references); void RequestHeapTrim() LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_); void RequestConcurrentGC(Thread* self) LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_); - void RecordAllocation(size_t size, Object* object) + void RecordAllocation(size_t size, mirror::Object* object) LOCKS_EXCLUDED(GlobalSynchronization::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -395,9 +376,9 @@ class Heap { // No thread saftey analysis since we call this everywhere and it is impossible to find a proper // lock ordering for it. - void VerifyObjectBody(const Object *obj) NO_THREAD_SAFETY_ANALYSIS; + void VerifyObjectBody(const mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS; - static void VerificationCallback(Object* obj, void* arg) + static void VerificationCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(GlobalSychronization::heap_bitmap_lock_); // Swap the allocation stack with the live stack. diff --git a/src/heap_test.cc b/src/heap_test.cc index 6db7416d06..79cc835471 100644 --- a/src/heap_test.cc +++ b/src/heap_test.cc @@ -15,6 +15,11 @@ */ #include "common_test.h" +#include "gc/card_table-inl.h" +#include "gc/space_bitmap-inl.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "sirt_ref.h" namespace art { @@ -37,12 +42,12 @@ TEST_F(HeapTest, GarbageCollectClassLinkerInit) { ScopedObjectAccess soa(Thread::Current()); // garbage is created during ClassLinker::Init - Class* c = class_linker_->FindSystemClass("[Ljava/lang/Object;"); + mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/Object;"); for (size_t i = 0; i < 1024; ++i) { - SirtRef<ObjectArray<Object> > array(soa.Self(), - ObjectArray<Object>::Alloc(soa.Self(), c, 2048)); + SirtRef<mirror::ObjectArray<mirror::Object> > array(soa.Self(), + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c, 2048)); for (size_t j = 0; j < 2048; ++j) { - array->Set(j, String::AllocFromModifiedUtf8(soa.Self(), "hello, world!")); + array->Set(j, mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!")); } } } @@ -53,7 +58,7 @@ TEST_F(HeapTest, HeapBitmapCapacityTest) { byte* heap_begin = reinterpret_cast<byte*>(0x1000); const size_t heap_capacity = SpaceBitmap::kAlignment * (sizeof(intptr_t) * 8 + 1); UniquePtr<SpaceBitmap> bitmap(SpaceBitmap::Create("test-bitmap", heap_begin, heap_capacity)); - bitmap->Set(reinterpret_cast<const Object*>(&heap_begin[heap_capacity - SpaceBitmap::kAlignment])); + bitmap->Set(reinterpret_cast<const mirror::Object*>(&heap_begin[heap_capacity - SpaceBitmap::kAlignment])); } } // namespace art diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc index c0e73bce0e..e0a4c05402 100644 --- a/src/hprof/hprof.cc +++ b/src/hprof/hprof.cc @@ -44,7 +44,11 @@ #include "debugger.h" #include "globals.h" #include "heap.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/field.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" #include "object_utils.h" #include "os.h" #include "safe_map.h" @@ -165,8 +169,8 @@ typedef uint32_t HprofId; typedef HprofId HprofStringId; typedef HprofId HprofObjectId; typedef HprofId HprofClassObjectId; -typedef std::set<Class*> ClassSet; -typedef std::set<Class*>::iterator ClassSetIterator; +typedef std::set<mirror::Class*> ClassSet; +typedef std::set<mirror::Class*>::iterator ClassSetIterator; typedef SafeMap<std::string, size_t> StringMap; typedef SafeMap<std::string, size_t>::iterator StringMapIterator; @@ -480,14 +484,14 @@ class Hprof { } private: - static void RootVisitor(const Object* obj, void* arg) + static void RootVisitor(const mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(arg != NULL); Hprof* hprof = reinterpret_cast<Hprof*>(arg); hprof->VisitRoot(obj); } - static void HeapBitmapCallback(Object* obj, void* arg) + static void HeapBitmapCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(obj != NULL); CHECK(arg != NULL); @@ -495,9 +499,9 @@ class Hprof { hprof->DumpHeapObject(obj); } - void VisitRoot(const Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void VisitRoot(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int DumpHeapObject(Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int DumpHeapObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Finish() { } @@ -507,7 +511,7 @@ class Hprof { uint32_t nextSerialNumber = 1; for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) { - const Class* c = *it; + const mirror::Class* c = *it; CHECK(c != NULL); int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME); @@ -567,9 +571,9 @@ class Hprof { current_heap_ = HPROF_HEAP_DEFAULT; } - int MarkRootObject(const Object* obj, jobject jniObj); + int MarkRootObject(const mirror::Object* obj, jobject jniObj); - HprofClassObjectId LookupClassId(Class* c) + HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (c == NULL) { // c is the superclass of java.lang.Object or a primitive @@ -577,7 +581,7 @@ class Hprof { } std::pair<ClassSetIterator, bool> result = classes_.insert(c); - const Class* present = *result.first; + const mirror::Class* present = *result.first; // Make sure that we've assigned a string ID for this class' name LookupClassNameId(c); @@ -586,7 +590,7 @@ class Hprof { return (HprofStringId) present; } - HprofStringId LookupStringId(String* string) { + HprofStringId LookupStringId(mirror::String* string) { return LookupStringId(string->ToModifiedUtf8()); } @@ -604,7 +608,7 @@ class Hprof { return id; } - HprofStringId LookupClassNameId(const Class* c) + HprofStringId LookupClassNameId(const mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return LookupStringId(PrettyDescriptor(c)); } @@ -740,7 +744,7 @@ static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t* // something when ctx->gc_scan_state_ is non-zero, which is usually // only true when marking the root set or unreachable // objects. Used to add rootset references to obj. -int Hprof::MarkRootObject(const Object* obj, jobject jniObj) { +int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) { HprofRecord* rec = ¤t_record_; HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_; @@ -823,11 +827,11 @@ int Hprof::MarkRootObject(const Object* obj, jobject jniObj) { return 0; } -static int StackTraceSerialNumber(const Object* /*obj*/) { +static int StackTraceSerialNumber(const mirror::Object* /*obj*/) { return HPROF_NULL_STACK_TRACE; } -int Hprof::DumpHeapObject(Object* obj) { +int Hprof::DumpHeapObject(mirror::Object* obj) { HprofRecord* rec = ¤t_record_; HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP; // TODO: zygote objects? @@ -859,7 +863,7 @@ int Hprof::DumpHeapObject(Object* obj) { current_heap_ = desiredHeap; } - Class* c = obj->GetClass(); + mirror::Class* c = obj->GetClass(); if (c == NULL) { // This object will bother HprofReader, because it has a NULL // class, so just don't dump it. It could be @@ -867,7 +871,7 @@ int Hprof::DumpHeapObject(Object* obj) { // allocated which hasn't been initialized yet. } else { if (obj->IsClass()) { - Class* thisClass = obj->AsClass(); + mirror::Class* thisClass = obj->AsClass(); // obj is a ClassObject. size_t sFieldCount = thisClass->NumStaticFields(); if (sFieldCount != 0) { @@ -896,7 +900,7 @@ int Hprof::DumpHeapObject(Object* obj) { if (thisClass->IsClassClass()) { // ClassObjects have their static fields appended, so aren't all the same size. // But they're at least this size. - rec->AddU4(sizeof(Class)); // instance size + rec->AddU4(sizeof(mirror::Class)); // instance size } else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) { rec->AddU4(0); } else { @@ -917,7 +921,7 @@ int Hprof::DumpHeapObject(Object* obj) { rec->AddId(CLASS_STATICS_ID(obj)); for (size_t i = 0; i < sFieldCount; ++i) { - Field* f = thisClass->GetStaticField(i); + mirror::Field* f = thisClass->GetStaticField(i); fh.ChangeField(f); size_t size; @@ -942,14 +946,14 @@ int Hprof::DumpHeapObject(Object* obj) { int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields(); rec->AddU2((uint16_t)iFieldCount); for (int i = 0; i < iFieldCount; ++i) { - Field* f = thisClass->GetInstanceField(i); + mirror::Field* f = thisClass->GetInstanceField(i); fh.ChangeField(f); HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL); rec->AddId(LookupStringId(fh.GetName())); rec->AddU1(t); } } else if (c->IsArrayClass()) { - const Array* aobj = obj->AsArray(); + const mirror::Array* aobj = obj->AsArray(); uint32_t length = aobj->GetLength(); if (obj->IsObjectArray()) { @@ -962,7 +966,7 @@ int Hprof::DumpHeapObject(Object* obj) { rec->AddId(LookupClassId(c)); // Dump the elements, which are always objects or NULL. - rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(Object*)), length); + rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(mirror::Object*)), length); } else { size_t size; HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size); @@ -1000,12 +1004,12 @@ int Hprof::DumpHeapObject(Object* obj) { // Write the instance data; fields for this class, followed by super class fields, // and so on. Don't write the klass or monitor fields of Object.class. - const Class* sclass = c; + const mirror::Class* sclass = c; FieldHelper fh; while (!sclass->IsObjectClass()) { int ifieldCount = sclass->NumInstanceFields(); for (int i = 0; i < ifieldCount; ++i) { - Field* f = sclass->GetInstanceField(i); + mirror::Field* f = sclass->GetInstanceField(i); fh.ChangeField(f); size_t size; SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size); @@ -1034,7 +1038,7 @@ int Hprof::DumpHeapObject(Object* obj) { return 0; } -void Hprof::VisitRoot(const Object* obj) { +void Hprof::VisitRoot(const mirror::Object* obj) { uint32_t threadId = 0; // TODO /*RootType*/ size_t type = 0; // TODO diff --git a/src/image.cc b/src/image.cc index a190f1015e..8eeb772a5d 100644 --- a/src/image.cc +++ b/src/image.cc @@ -16,9 +16,47 @@ #include "image.h" +#include "mirror/object_array.h" +#include "mirror/object_array-inl.h" +#include "utils.h" + namespace art { const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; const byte ImageHeader::kImageVersion[] = { '0', '0', '2', '\0' }; +ImageHeader::ImageHeader(uint32_t image_begin, + uint32_t image_roots, + uint32_t oat_checksum, + uint32_t oat_file_begin, + uint32_t oat_data_begin, + uint32_t oat_data_end, + uint32_t oat_file_end) + : image_begin_(image_begin), + oat_checksum_(oat_checksum), + oat_file_begin_(oat_file_begin), + oat_data_begin_(oat_data_begin), + oat_data_end_(oat_data_end), + oat_file_end_(oat_file_end), + image_roots_(image_roots) { + CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize)); + CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize)); + CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize)); + CHECK_LT(image_begin, image_roots); + CHECK_LT(image_roots, oat_file_begin); + CHECK_LE(oat_file_begin, oat_data_begin); + CHECK_LT(oat_data_begin, oat_data_end); + CHECK_LE(oat_data_end, oat_file_end); + memcpy(magic_, kImageMagic, sizeof(kImageMagic)); + memcpy(version_, kImageVersion, sizeof(kImageVersion)); +} + +mirror::Object* ImageHeader::GetImageRoot(ImageRoot image_root) const { + return GetImageRoots()->Get(image_root); +} + +mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const { + return reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(image_roots_); +} + } // namespace art diff --git a/src/image.h b/src/image.h index f38f04be8b..6501328300 100644 --- a/src/image.h +++ b/src/image.h @@ -20,7 +20,7 @@ #include <string.h> #include "globals.h" -#include "object.h" +#include "mirror/object.h" namespace art { @@ -35,25 +35,7 @@ class PACKED(4) ImageHeader { uint32_t oat_file_begin, uint32_t oat_data_begin, uint32_t oat_data_end, - uint32_t oat_file_end) - : image_begin_(image_begin), - oat_checksum_(oat_checksum), - oat_file_begin_(oat_file_begin), - oat_data_begin_(oat_data_begin), - oat_data_end_(oat_data_end), - oat_file_end_(oat_file_end), - image_roots_(image_roots) { - CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize)); - CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize)); - CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize)); - CHECK_LT(image_begin, image_roots); - CHECK_LT(image_roots, oat_file_begin); - CHECK_LE(oat_file_begin, oat_data_begin); - CHECK_LT(oat_data_begin, oat_data_end); - CHECK_LE(oat_data_end, oat_file_end); - memcpy(magic_, kImageMagic, sizeof(kImageMagic)); - memcpy(version_, kImageVersion, sizeof(kImageVersion)); - } + uint32_t oat_file_end); bool IsValid() const { if (memcmp(magic_, kImageMagic, sizeof(kImageMagic) != 0)) { @@ -113,15 +95,11 @@ class PACKED(4) ImageHeader { kImageRootsMax, }; - Object* GetImageRoot(ImageRoot image_root) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetImageRoots()->Get(image_root); - } + mirror::Object* GetImageRoot(ImageRoot image_root) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: - ObjectArray<Object>* GetImageRoots() const { - return reinterpret_cast<ObjectArray<Object>*>(image_roots_); - } + mirror::ObjectArray<mirror::Object>* GetImageRoots() const; static const byte kImageMagic[4]; static const byte kImageVersion[4]; diff --git a/src/image_test.cc b/src/image_test.cc index 89e3a05041..ed6426b7b1 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -54,7 +54,7 @@ TEST_F(ImageTest, WriteRead) { for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i); const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def); - Class* klass = class_linker_->FindSystemClass(descriptor); + mirror::Class* klass = class_linker_->FindSystemClass(descriptor); EXPECT_TRUE(klass != NULL) << descriptor; } } @@ -139,7 +139,7 @@ TEST_F(ImageTest, WriteRead) { for (size_t i = 0; i < dex->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = dex->GetClassDef(i); const char* descriptor = dex->GetClassDescriptor(class_def); - Class* klass = class_linker_->FindSystemClass(descriptor); + mirror::Class* klass = class_linker_->FindSystemClass(descriptor); EXPECT_TRUE(klass != NULL) << descriptor; EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor; EXPECT_LT(reinterpret_cast<byte*>(klass), image_end) << descriptor; diff --git a/src/image_writer.cc b/src/image_writer.cc index fc88cbbfc3..dc19d72cca 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -23,19 +23,25 @@ #include "base/logging.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" -#include "class_loader.h" #include "compiled_method.h" #include "compiler.h" -#include "dex_cache.h" +#include "gc/card_table-inl.h" #include "gc/large_object_space.h" #include "gc/space.h" #include "globals.h" #include "heap.h" #include "image.h" #include "intern_table.h" +#include "mirror/array-inl.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/dex_cache.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "oat.h" #include "oat_file.h" -#include "object.h" #include "object_utils.h" #include "runtime.h" #include "scoped_thread_state_change.h" @@ -43,6 +49,8 @@ #include "UniquePtr.h" #include "utils.h" +using namespace art::mirror; + namespace art { bool ImageWriter::Write(const std::string& image_filename, @@ -442,7 +450,7 @@ void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { DCHECK_LT(offset + n, image_writer->image_->Size()); memcpy(dst, src, n); Object* copy = reinterpret_cast<Object*>(dst); - copy->monitor_ = 0; // We may have inflated the lock during compilation. + copy->SetField32(Object::MonitorOffset(), 0, false); // We may have inflated the lock during compilation. image_writer->FixupObject(obj, copy); } @@ -476,13 +484,13 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) // Every type of method can have an invoke stub uint32_t invoke_stub_offset = orig->GetOatInvokeStubOffset(); const byte* invoke_stub = GetOatAddress(invoke_stub_offset); - copy->invoke_stub_ = reinterpret_cast<AbstractMethod::InvokeStub*>(const_cast<byte*>(invoke_stub)); + copy->SetInvokeStub(reinterpret_cast<AbstractMethod::InvokeStub*>(const_cast<byte*>(invoke_stub))); if (orig->IsAbstract()) { // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called ByteArray* orig_ame_stub_array_ = Runtime::Current()->GetAbstractMethodErrorStubArray(); ByteArray* copy_ame_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_ame_stub_array_)); - copy->code_ = copy_ame_stub_array_->GetData(); + copy->SetCode(copy_ame_stub_array_->GetData()); return; } @@ -492,7 +500,7 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod); CHECK(orig->GetCode() == orig_res_stub_array_->GetData()); ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_)); - copy->code_ = copy_res_stub_array_->GetData(); + copy->SetCode(copy_res_stub_array_->GetData()); return; } @@ -511,27 +519,27 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) if (code == NULL) { code = GetOatAddress(code_offset); } - copy->code_ = code; + copy->SetCode(code); if (orig->IsNative()) { // The native method's pointer is directed to a stub to lookup via dlsym. // Note this is not the code_ pointer, that is handled above. ByteArray* orig_jni_stub_array_ = Runtime::Current()->GetJniDlsymLookupStub(); ByteArray* copy_jni_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_jni_stub_array_)); - copy->native_method_ = copy_jni_stub_array_->GetData(); + copy->SetNativeMethod(copy_jni_stub_array_->GetData()); } else { // normal (non-abstract non-native) methods have mapping tables to relocate uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); const byte* mapping_table = GetOatAddress(mapping_table_off); - copy->mapping_table_ = reinterpret_cast<const uint32_t*>(mapping_table); + copy->SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table)); uint32_t vmap_table_offset = orig->GetOatVmapTableOffset(); const byte* vmap_table = GetOatAddress(vmap_table_offset); - copy->vmap_table_ = reinterpret_cast<const uint16_t*>(vmap_table); + copy->SetVmapTable(reinterpret_cast<const uint16_t*>(vmap_table)); uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset(); const byte* native_gc_map = GetOatAddress(native_gc_map_offset); - copy->native_gc_map_ = reinterpret_cast<const uint8_t*>(native_gc_map); + copy->SetNativeGcMap(reinterpret_cast<const uint8_t*>(native_gc_map)); } } diff --git a/src/image_writer.h b/src/image_writer.h index 64bac2ed1d..eff9ffb3de 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -24,10 +24,9 @@ #include <string> #include "compiler.h" -#include "dex_cache.h" #include "mem_map.h" #include "oat_file.h" -#include "object.h" +#include "mirror/dex_cache.h" #include "os.h" #include "safe_map.h" #include "gc/space.h" @@ -59,7 +58,7 @@ class ImageWriter { bool AllocMemory(); // we use the lock word to store the offset of the object in the image - void AssignImageOffset(Object* object) + void AssignImageOffset(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(object != NULL); SetImageOffset(object, image_end_); @@ -67,35 +66,35 @@ class ImageWriter { DCHECK_LT(image_end_, image_->Size()); } - void SetImageOffset(Object* object, size_t offset) { + void SetImageOffset(mirror::Object* object, size_t offset) { DCHECK(object != NULL); DCHECK_NE(offset, 0U); DCHECK(!IsImageOffsetAssigned(object)); offsets_.Put(object, offset); } - size_t IsImageOffsetAssigned(const Object* object) const { + size_t IsImageOffsetAssigned(const mirror::Object* object) const { DCHECK(object != NULL); return offsets_.find(object) != offsets_.end(); } - size_t GetImageOffset(const Object* object) const { + size_t GetImageOffset(const mirror::Object* object) const { DCHECK(object != NULL); DCHECK(IsImageOffsetAssigned(object)); return offsets_.find(object)->second; } - Object* GetImageAddress(const Object* object) const { + mirror::Object* GetImageAddress(const mirror::Object* object) const { if (object == NULL) { return NULL; } - return reinterpret_cast<Object*>(image_begin_ + GetImageOffset(object)); + return reinterpret_cast<mirror::Object*>(image_begin_ + GetImageOffset(object)); } - Object* GetLocalAddress(const Object* object) const { + mirror::Object* GetLocalAddress(const mirror::Object* object) const { size_t offset = GetImageOffset(object); byte* dst = image_->Begin() + offset; - return reinterpret_cast<Object*>(dst); + return reinterpret_cast<mirror::Object*>(dst); } const byte* GetOatAddress(uint32_t offset) const { @@ -106,50 +105,52 @@ class ImageWriter { return oat_data_begin_ + offset; } - bool IsImageClass(const Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsImageClass(const mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DumpImageClasses(); void ComputeLazyFieldsForImageClasses() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static bool ComputeLazyFieldsForClassesVisitor(Class* klass, void* arg) + static bool ComputeLazyFieldsForClassesVisitor(mirror::Class* klass, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Wire dex cache resolved strings to strings in the image to avoid runtime resolution void ComputeEagerResolvedStrings(); - static void ComputeEagerResolvedStringsCallback(Object* obj, void* arg) + static void ComputeEagerResolvedStringsCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void PruneNonImageClasses() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static bool NonImageClassesVisitor(Class* c, void* arg) + static bool NonImageClassesVisitor(mirror::Class* c, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void CheckNonImageClassesRemoved(); - static void CheckNonImageClassesRemovedCallback(Object* obj, void* arg) + static void CheckNonImageClassesRemovedCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_data_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<Object>* CreateImageRoots() const + mirror::ObjectArray<mirror::Object>* CreateImageRoots() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void CalculateNewObjectOffsetsCallback(Object* obj, void* arg) + static void CalculateNewObjectOffsetsCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void CopyAndFixupObjects(); - static void CopyAndFixupObjectsCallback(Object* obj, void* arg) + static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupClass(const Class* orig, Class* copy) + void FixupClass(const mirror::Class* orig, mirror::Class* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) + void FixupMethod(const mirror::AbstractMethod* orig, mirror::AbstractMethod* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupObject(const Object* orig, Object* copy) + void FixupObject(const mirror::Object* orig, mirror::Object* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) + void FixupObjectArray(const mirror::ObjectArray<mirror::Object>* orig, + mirror::ObjectArray<mirror::Object>* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupInstanceFields(const Object* orig, Object* copy) + void FixupInstanceFields(const mirror::Object* orig, mirror::Object* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupStaticFields(const Class* orig, Class* copy) + void FixupStaticFields(const mirror::Class* orig, mirror::Class* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FixupFields(const Object* orig, Object* copy, uint32_t ref_offsets, bool is_static) + void FixupFields(const mirror::Object* orig, mirror::Object* copy, uint32_t ref_offsets, + bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void PatchOatCodeAndMethods(const Compiler& compiler) @@ -157,7 +158,7 @@ class ImageWriter { void SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - SafeMap<const Object*, size_t> offsets_; + SafeMap<const mirror::Object*, size_t> offsets_; // oat file with code for this image OatFile* oat_file_; @@ -178,7 +179,7 @@ class ImageWriter { const byte* oat_data_begin_; // DexCaches seen while scanning for fixing up CodeAndDirectMethods - typedef std::set<DexCache*> Set; + typedef std::set<mirror::DexCache*> Set; Set dex_caches_; }; diff --git a/src/indirect_reference_table.cc b/src/indirect_reference_table.cc index 9bb6edc9cb..720380a2eb 100644 --- a/src/indirect_reference_table.cc +++ b/src/indirect_reference_table.cc @@ -40,9 +40,9 @@ IndirectReferenceTable::IndirectReferenceTable(size_t initialCount, CHECK_LE(initialCount, maxCount); CHECK_NE(desiredKind, kSirtOrInvalid); - table_ = reinterpret_cast<const Object**>(malloc(initialCount * sizeof(const Object*))); + table_ = reinterpret_cast<const mirror::Object**>(malloc(initialCount * sizeof(const mirror::Object*))); CHECK(table_ != NULL); - memset(table_, 0xd1, initialCount * sizeof(const Object*)); + memset(table_, 0xd1, initialCount * sizeof(const mirror::Object*)); slot_data_ = reinterpret_cast<IndirectRefSlot*>(calloc(initialCount, sizeof(IndirectRefSlot))); CHECK(slot_data_ != NULL); @@ -63,7 +63,7 @@ IndirectReferenceTable::~IndirectReferenceTable() { // Make sure that the entry at "idx" is correctly paired with "iref". bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const { - const Object* obj = table_[idx]; + const mirror::Object* obj = table_[idx]; IndirectRef checkRef = ToIndirectRef(obj, idx); if (checkRef != iref) { LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what @@ -75,7 +75,7 @@ bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int return true; } -IndirectRef IndirectReferenceTable::Add(uint32_t cookie, const Object* obj) { +IndirectRef IndirectReferenceTable::Add(uint32_t cookie, const mirror::Object* obj) { IRTSegmentState prevState; prevState.all = cookie; size_t topIndex = segment_state_.parts.topIndex; @@ -101,7 +101,7 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, const Object* obj) { } DCHECK_GT(newSize, alloc_entries_); - table_ = reinterpret_cast<const Object**>(realloc(table_, newSize * sizeof(const Object*))); + table_ = reinterpret_cast<const mirror::Object**>(realloc(table_, newSize * sizeof(const mirror::Object*))); slot_data_ = reinterpret_cast<IndirectRefSlot*>(realloc(slot_data_, newSize * sizeof(IndirectRefSlot))); if (table_ == NULL || slot_data_ == NULL) { @@ -126,7 +126,7 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, const Object* obj) { if (numHoles > 0) { DCHECK_GT(topIndex, 1U); // Find the first hole; likely to be near the end of the list. - const Object** pScan = &table_[topIndex - 1]; + const mirror::Object** pScan = &table_[topIndex - 1]; DCHECK(*pScan != NULL); while (*--pScan != NULL) { DCHECK_GE(pScan, table_ + prevState.parts.topIndex); @@ -194,7 +194,7 @@ bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { return true; } -static int Find(Object* direct_pointer, int bottomIndex, int topIndex, const Object** table) { +static int Find(mirror::Object* direct_pointer, int bottomIndex, int topIndex, const mirror::Object** table) { for (int i = bottomIndex; i < topIndex; ++i) { if (table[i] == direct_pointer) { return i; @@ -203,7 +203,7 @@ static int Find(Object* direct_pointer, int bottomIndex, int topIndex, const Obj return -1; } -bool IndirectReferenceTable::ContainsDirectPointer(Object* direct_pointer) const { +bool IndirectReferenceTable::ContainsDirectPointer(mirror::Object* direct_pointer) const { return Find(direct_pointer, 0, segment_state_.parts.topIndex, table_) != -1; } @@ -234,7 +234,7 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return true; } if (GetIndirectRefKind(iref) == kSirtOrInvalid && vm->work_around_app_jni_bugs) { - Object* direct_pointer = reinterpret_cast<Object*>(iref); + mirror::Object* direct_pointer = reinterpret_cast<mirror::Object*>(iref); idx = Find(direct_pointer, bottomIndex, topIndex, table_); if (idx == -1) { LOG(WARNING) << "trying to work around app JNI bugs, but didn't find " << iref << " in table!"; @@ -308,7 +308,7 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return true; } -void IndirectReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void IndirectReferenceTable::VisitRoots(RootVisitor* visitor, void* arg) { typedef IndirectReferenceTable::iterator It; // TODO: C++0x auto for (It it = begin(), end = this->end(); it != end; ++it) { visitor(**it, arg); @@ -317,7 +317,7 @@ void IndirectReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) { void IndirectReferenceTable::Dump(std::ostream& os) const { os << kind_ << " table dump:\n"; - std::vector<const Object*> entries(table_, table_ + Capacity()); + std::vector<const mirror::Object*> entries(table_, table_ + Capacity()); // Remove NULLs. for (int i = entries.size() - 1; i >= 0; --i) { if (entries[i] == NULL) { diff --git a/src/indirect_reference_table.h b/src/indirect_reference_table.h index cd358e93df..e09043dba7 100644 --- a/src/indirect_reference_table.h +++ b/src/indirect_reference_table.h @@ -23,11 +23,13 @@ #include <string> #include "base/logging.h" -#include "heap.h" +#include "offsets.h" +#include "root_visitor.h" namespace art { - +namespace mirror { class Object; +} // namespace mirror /* * Maintain a table of indirect references. Used for local/global JNI @@ -98,8 +100,8 @@ class Object; typedef void* IndirectRef; // Magic failure values; must not pass Heap::ValidateObject() or Heap::IsHeapAddress(). -static Object* const kInvalidIndirectRefObject = reinterpret_cast<Object*>(0xdead4321); -static Object* const kClearedJniWeakGlobal = reinterpret_cast<Object*>(0xdead1234); +static mirror::Object* const kInvalidIndirectRefObject = reinterpret_cast<mirror::Object*>(0xdead4321); +static mirror::Object* const kClearedJniWeakGlobal = reinterpret_cast<mirror::Object*>(0xdead1234); /* * Indirect reference kind, used as the two low bits of IndirectRef. @@ -128,7 +130,7 @@ static inline IndirectRefKind GetIndirectRefKind(IndirectRef iref) { static const size_t kIRTPrevCount = 4; struct IndirectRefSlot { uint32_t serial; - const Object* previous[kIRTPrevCount]; + const mirror::Object* previous[kIRTPrevCount]; }; /* use as initial value for "cookie", and when table has only one segment */ @@ -204,7 +206,7 @@ union IRTSegmentState { class IrtIterator { public: - explicit IrtIterator(const Object** table, size_t i, size_t capacity) + explicit IrtIterator(const mirror::Object** table, size_t i, size_t capacity) : table_(table), i_(i), capacity_(capacity) { SkipNullsAndTombstones(); } @@ -215,7 +217,7 @@ class IrtIterator { return *this; } - const Object** operator*() { + const mirror::Object** operator*() { return &table_[i_]; } @@ -231,7 +233,7 @@ class IrtIterator { } } - const Object** table_; + const mirror::Object** table_; size_t i_; size_t capacity_; }; @@ -258,7 +260,7 @@ class IndirectReferenceTable { * Returns NULL if the table is full (max entries reached, or alloc * failed during expansion). */ - IndirectRef Add(uint32_t cookie, const Object* obj) + IndirectRef Add(uint32_t cookie, const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /* @@ -266,7 +268,7 @@ class IndirectReferenceTable { * * Returns kInvalidIndirectRefObject if iref is invalid. */ - const Object* Get(IndirectRef iref) const { + const mirror::Object* Get(IndirectRef iref) const { if (!GetChecked(iref)) { return kInvalidIndirectRefObject; } @@ -274,7 +276,7 @@ class IndirectReferenceTable { } // TODO: remove when we remove work_around_app_jni_bugs support. - bool ContainsDirectPointer(Object* direct_pointer) const; + bool ContainsDirectPointer(mirror::Object* direct_pointer) const; /* * Remove an existing entry. @@ -307,7 +309,7 @@ class IndirectReferenceTable { return iterator(table_, Capacity(), Capacity()); } - void VisitRoots(Heap::RootVisitor* visitor, void* arg); + void VisitRoots(RootVisitor* visitor, void* arg); uint32_t GetSegmentState() const { return segment_state_.all; @@ -334,7 +336,7 @@ class IndirectReferenceTable { * The object pointer itself is subject to relocation in some GC * implementations, so we shouldn't really be using it here. */ - IndirectRef ToIndirectRef(const Object* /*o*/, uint32_t tableIndex) const { + IndirectRef ToIndirectRef(const mirror::Object* /*o*/, uint32_t tableIndex) const { DCHECK_LT(tableIndex, 65536U); uint32_t serialChunk = slot_data_[tableIndex].serial; uint32_t uref = serialChunk << 20 | (tableIndex << 2) | kind_; @@ -347,7 +349,7 @@ class IndirectReferenceTable { * We advance the serial number, invalidating any outstanding references to * this slot. */ - void UpdateSlotAdd(const Object* obj, int slot) { + void UpdateSlotAdd(const mirror::Object* obj, int slot) { if (slot_data_ != NULL) { IndirectRefSlot* pSlot = &slot_data_[slot]; pSlot->serial++; @@ -363,7 +365,7 @@ class IndirectReferenceTable { IRTSegmentState segment_state_; /* bottom of the stack */ - const Object** table_; + const mirror::Object** table_; /* bit mask, ORed into all irefs */ IndirectRefKind kind_; /* extended debugging info */ diff --git a/src/indirect_reference_table_test.cc b/src/indirect_reference_table_test.cc index b5a05ece2b..bd2890c497 100644 --- a/src/indirect_reference_table_test.cc +++ b/src/indirect_reference_table_test.cc @@ -47,15 +47,15 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { static const size_t kTableMax = 20; IndirectReferenceTable irt(kTableInitial, kTableMax, kGlobal); - Class* c = class_linker_->FindSystemClass("Ljava/lang/Object;"); + mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/Object;"); ASSERT_TRUE(c != NULL); - Object* obj0 = c->AllocObject(soa.Self()); + mirror::Object* obj0 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj0 != NULL); - Object* obj1 = c->AllocObject(soa.Self()); + mirror::Object* obj1 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj1 != NULL); - Object* obj2 = c->AllocObject(soa.Self()); + mirror::Object* obj2 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj2 != NULL); - Object* obj3 = c->AllocObject(soa.Self()); + mirror::Object* obj3 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj3 != NULL); const uint32_t cookie = IRT_FIRST_SEGMENT; diff --git a/src/instrumentation.cc b/src/instrumentation.cc index 065758d16e..e3d4d28d86 100644 --- a/src/instrumentation.cc +++ b/src/instrumentation.cc @@ -21,7 +21,10 @@ #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "debugger.h" -#include "dex_cache.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #if !defined(ART_USE_LLVM_COMPILER) #include "oat/runtime/oat_support_entrypoints.h" #endif @@ -34,18 +37,18 @@ namespace art { -static bool InstallStubsClassVisitor(Class* klass, void*) +static bool InstallStubsClassVisitor(mirror::Class* klass, void*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); for (size_t i = 0; i < klass->NumDirectMethods(); i++) { - AbstractMethod* method = klass->GetDirectMethod(i); + mirror::AbstractMethod* method = klass->GetDirectMethod(i); if (instrumentation->GetSavedCodeFromMap(method) == NULL) { instrumentation->SaveAndUpdateCode(method); } } for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { - AbstractMethod* method = klass->GetVirtualMethod(i); + mirror::AbstractMethod* method = klass->GetVirtualMethod(i); if (instrumentation->GetSavedCodeFromMap(method) == NULL) { instrumentation->SaveAndUpdateCode(method); } @@ -53,18 +56,18 @@ static bool InstallStubsClassVisitor(Class* klass, void*) return true; } -static bool UninstallStubsClassVisitor(Class* klass, void*) +static bool UninstallStubsClassVisitor(mirror::Class* klass, void*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); for (size_t i = 0; i < klass->NumDirectMethods(); i++) { - AbstractMethod* method = klass->GetDirectMethod(i); + mirror::AbstractMethod* method = klass->GetDirectMethod(i); if (instrumentation->GetSavedCodeFromMap(method) != NULL) { instrumentation->ResetSavedCode(method); } } for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { - AbstractMethod* method = klass->GetVirtualMethod(i); + mirror::AbstractMethod* method = klass->GetVirtualMethod(i); if (instrumentation->GetSavedCodeFromMap(method) != NULL) { instrumentation->ResetSavedCode(method); } @@ -83,7 +86,7 @@ void InstrumentationInstallStack(Thread* self, void* arg) if (GetCurrentQuickFrame() == NULL) { return true; // Ignore shadow frames. } - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m == NULL) { return true; // Ignore upcalls. } @@ -125,7 +128,7 @@ static void InstrumentationRestoreStack(Thread* self, void*) if (self_->IsInstrumentationStackEmpty()) { return false; // Stop. } - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m == NULL) { return true; // Ignore upcalls. } @@ -171,16 +174,16 @@ void Instrumentation::UninstallStubs() { Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, NULL); } -void Instrumentation::AddSavedCodeToMap(const AbstractMethod* method, const void* code) { +void Instrumentation::AddSavedCodeToMap(const mirror::AbstractMethod* method, const void* code) { saved_code_map_.Put(method, code); } -void Instrumentation::RemoveSavedCodeFromMap(const AbstractMethod* method) { +void Instrumentation::RemoveSavedCodeFromMap(const mirror::AbstractMethod* method) { saved_code_map_.erase(method); } -const void* Instrumentation::GetSavedCodeFromMap(const AbstractMethod* method) { - typedef SafeMap<const AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto +const void* Instrumentation::GetSavedCodeFromMap(const mirror::AbstractMethod* method) { + typedef SafeMap<const mirror::AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto It it = saved_code_map_.find(method); if (it == saved_code_map_.end()) { return NULL; @@ -189,7 +192,7 @@ const void* Instrumentation::GetSavedCodeFromMap(const AbstractMethod* method) { } } -void Instrumentation::SaveAndUpdateCode(AbstractMethod* method) { +void Instrumentation::SaveAndUpdateCode(mirror::AbstractMethod* method) { #if defined(ART_USE_LLVM_COMPILER) UNUSED(method); UNIMPLEMENTED(FATAL); @@ -201,7 +204,7 @@ void Instrumentation::SaveAndUpdateCode(AbstractMethod* method) { #endif } -void Instrumentation::ResetSavedCode(AbstractMethod* method) { +void Instrumentation::ResetSavedCode(mirror::AbstractMethod* method) { CHECK(GetSavedCodeFromMap(method) != NULL); method->SetCode(GetSavedCodeFromMap(method)); RemoveSavedCodeFromMap(method); @@ -223,7 +226,7 @@ void Instrumentation::RemoveTrace() { uint32_t InstrumentationMethodUnwindFromCode(Thread* self) { Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace(); InstrumentationStackFrame instrumentation_frame = self->PopInstrumentationStackFrame(); - AbstractMethod* method = instrumentation_frame.method_; + mirror::AbstractMethod* method = instrumentation_frame.method_; uint32_t lr = instrumentation_frame.return_pc_; trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind); diff --git a/src/instrumentation.h b/src/instrumentation.h index 00060ce168..fb49bf8208 100644 --- a/src/instrumentation.h +++ b/src/instrumentation.h @@ -17,29 +17,27 @@ #ifndef ART_SRC_INSTRUMENTATION_H_ #define ART_SRC_INSTRUMENTATION_H_ -#include <ostream> -#include <set> -#include <string> - #include "base/macros.h" -#include "globals.h" #include "safe_map.h" -#include "trace.h" -#include "UniquePtr.h" + +#include <stdint.h> namespace art { +namespace mirror { class AbstractMethod; +} class Thread; +class Trace; uint32_t InstrumentationMethodUnwindFromCode(Thread* self); struct InstrumentationStackFrame { InstrumentationStackFrame() : method_(NULL), return_pc_(0), frame_id_(0) {} - InstrumentationStackFrame(AbstractMethod* method, uintptr_t return_pc, size_t frame_id) + InstrumentationStackFrame(mirror::AbstractMethod* method, uintptr_t return_pc, size_t frame_id) : method_(method), return_pc_(return_pc), frame_id_(frame_id) { } - AbstractMethod* method_; + mirror::AbstractMethod* method_; uintptr_t return_pc_; size_t frame_id_; }; @@ -55,20 +53,20 @@ class Instrumentation { // Restores original code for each method and fixes the return values of each thread's stack. void UninstallStubs() LOCKS_EXCLUDED(Locks::thread_list_lock_); - const void* GetSavedCodeFromMap(const AbstractMethod* method); - void SaveAndUpdateCode(AbstractMethod* method); - void ResetSavedCode(AbstractMethod* method); + const void* GetSavedCodeFromMap(const mirror::AbstractMethod* method); + void SaveAndUpdateCode(mirror::AbstractMethod* method); + void ResetSavedCode(mirror::AbstractMethod* method); Trace* GetTrace() const; void SetTrace(Trace* trace); void RemoveTrace(); private: - void AddSavedCodeToMap(const AbstractMethod* method, const void* code); - void RemoveSavedCodeFromMap(const AbstractMethod* method); + void AddSavedCodeToMap(const mirror::AbstractMethod* method, const void* code); + void RemoveSavedCodeFromMap(const mirror::AbstractMethod* method); // Maps a method to its original code pointer. - SafeMap<const AbstractMethod*, const void*> saved_code_map_; + SafeMap<const mirror::AbstractMethod*, const void*> saved_code_map_; Trace* trace_; diff --git a/src/intern_table.cc b/src/intern_table.cc index 817ce1e5e1..fa3c0753a9 100644 --- a/src/intern_table.cc +++ b/src/intern_table.cc @@ -16,6 +16,8 @@ #include "intern_table.h" +#include "mirror/string.h" +#include "thread.h" #include "UniquePtr.h" #include "utf.h" @@ -36,7 +38,7 @@ void InternTable::DumpForSigQuit(std::ostream& os) const { << image_strong_interns_.size() << " image strong\n"; } -void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void InternTable::VisitRoots(RootVisitor* visitor, void* arg) { MutexLock mu(Thread::Current(), intern_table_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) { @@ -46,11 +48,11 @@ void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) { // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots. } -String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) { +mirror::String* InternTable::Lookup(Table& table, mirror::String* s, uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = table.find(hash_code), end = table.end(); it != end; ++it) { - String* existing_string = it->second; + mirror::String* existing_string = it->second; if (existing_string->Equals(s)) { return existing_string; } @@ -58,18 +60,18 @@ String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) { return NULL; } -String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) { +mirror::String* InternTable::Insert(Table& table, mirror::String* s, uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); table.insert(std::make_pair(hash_code, s)); return s; } -void InternTable::RegisterStrong(String* s) { +void InternTable::RegisterStrong(mirror::String* s) { MutexLock mu(Thread::Current(), intern_table_lock_); Insert(image_strong_interns_, s, s->GetHashCode()); } -void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) { +void InternTable::Remove(Table& table, const mirror::String* s, uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); typedef Table::iterator It; // TODO: C++0x auto for (It it = table.find(hash_code), end = table.end(); it != end; ++it) { @@ -80,7 +82,7 @@ void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) { } } -String* InternTable::Insert(String* s, bool is_strong) { +mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { MutexLock mu(Thread::Current(), intern_table_lock_); DCHECK(s != NULL); @@ -88,12 +90,12 @@ String* InternTable::Insert(String* s, bool is_strong) { if (is_strong) { // Check the strong table for a match. - String* strong = Lookup(strong_interns_, s, hash_code); + mirror::String* strong = Lookup(strong_interns_, s, hash_code); if (strong != NULL) { return strong; } // Check the image table for a match. - String* image = Lookup(image_strong_interns_, s, hash_code); + mirror::String* image = Lookup(image_strong_interns_, s, hash_code); if (image != NULL) { return image; } @@ -102,7 +104,7 @@ String* InternTable::Insert(String* s, bool is_strong) { Dirty(); // There is no match in the strong table, check the weak table. - String* weak = Lookup(weak_interns_, s, hash_code); + mirror::String* weak = Lookup(weak_interns_, s, hash_code); if (weak != NULL) { // A match was found in the weak table. Promote to the strong table. Remove(weak_interns_, weak, hash_code); @@ -114,17 +116,17 @@ String* InternTable::Insert(String* s, bool is_strong) { } // Check the strong table for a match. - String* strong = Lookup(strong_interns_, s, hash_code); + mirror::String* strong = Lookup(strong_interns_, s, hash_code); if (strong != NULL) { return strong; } // Check the image table for a match. - String* image = Lookup(image_strong_interns_, s, hash_code); + mirror::String* image = Lookup(image_strong_interns_, s, hash_code); if (image != NULL) { return image; } // Check the weak table for a match. - String* weak = Lookup(weak_interns_, s, hash_code); + mirror::String* weak = Lookup(weak_interns_, s, hash_code); if (weak != NULL) { return weak; } @@ -132,39 +134,39 @@ String* InternTable::Insert(String* s, bool is_strong) { return Insert(weak_interns_, s, hash_code); } -String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) { - return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf16_length, utf8_data)); +mirror::String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) { + return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf16_length, utf8_data)); } -String* InternTable::InternStrong(const char* utf8_data) { - return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf8_data)); +mirror::String* InternTable::InternStrong(const char* utf8_data) { + return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data)); } -String* InternTable::InternStrong(String* s) { +mirror::String* InternTable::InternStrong(mirror::String* s) { if (s == NULL) { return NULL; } return Insert(s, true); } -String* InternTable::InternWeak(String* s) { +mirror::String* InternTable::InternWeak(mirror::String* s) { if (s == NULL) { return NULL; } return Insert(s, false); } -bool InternTable::ContainsWeak(String* s) { +bool InternTable::ContainsWeak(mirror::String* s) { MutexLock mu(Thread::Current(), intern_table_lock_); - const String* found = Lookup(weak_interns_, s, s->GetHashCode()); + const mirror::String* found = Lookup(weak_interns_, s, s->GetHashCode()); return found == s; } -void InternTable::SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) { +void InternTable::SweepInternTableWeaks(IsMarkedTester is_marked, void* arg) { MutexLock mu(Thread::Current(), intern_table_lock_); typedef Table::iterator It; // TODO: C++0x auto for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) { - Object* object = it->second; + mirror::Object* object = it->second; if (!is_marked(object, arg)) { weak_interns_.erase(it++); } else { diff --git a/src/intern_table.h b/src/intern_table.h index 06a2b89e19..3018317e0f 100644 --- a/src/intern_table.h +++ b/src/intern_table.h @@ -17,14 +17,15 @@ #ifndef ART_SRC_INTERN_TABLE_H_ #define ART_SRC_INTERN_TABLE_H_ -#include <iosfwd> - #include "base/mutex.h" -#include "heap.h" -#include "object.h" -#include "safe_map.h" +#include "root_visitor.h" + +#include <map> namespace art { +namespace mirror { +class String; +} // namespace mirror /** * Used to intern strings. @@ -41,31 +42,31 @@ class InternTable { InternTable(); // Interns a potentially new string in the 'strong' table. (See above.) - String* InternStrong(int32_t utf16_length, const char* utf8_data) + mirror::String* InternStrong(int32_t utf16_length, const char* utf8_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Interns a potentially new string in the 'strong' table. (See above.) - String* InternStrong(const char* utf8_data) + mirror::String* InternStrong(const char* utf8_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Interns a potentially new string in the 'strong' table. (See above.) - String* InternStrong(String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::String* InternStrong(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Interns a potentially new string in the 'weak' table. (See above.) - String* InternWeak(String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::String* InternWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Register a String trusting that it is safe to intern. // Used when reinitializing InternTable from an image. - void RegisterStrong(String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void RegisterStrong(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) + void SweepInternTableWeaks(IsMarkedTester is_marked, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - bool ContainsWeak(String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool ContainsWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); size_t Size() const; - void VisitRoots(Heap::RootVisitor* visitor, void* arg); + void VisitRoots(RootVisitor* visitor, void* arg); void DumpForSigQuit(std::ostream& os) const; @@ -75,15 +76,15 @@ class InternTable { } private: - typedef std::multimap<int32_t, String*> Table; + typedef std::multimap<int32_t, mirror::String*> Table; - String* Insert(String* s, bool is_strong) + mirror::String* Insert(mirror::String* s, bool is_strong) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - String* Lookup(Table& table, String* s, uint32_t hash_code) + mirror::String* Lookup(Table& table, mirror::String* s, uint32_t hash_code) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - String* Insert(Table& table, String* s, uint32_t hash_code); - void Remove(Table& table, const String* s, uint32_t hash_code); + mirror::String* Insert(Table& table, mirror::String* s, uint32_t hash_code); + void Remove(Table& table, const mirror::String* s, uint32_t hash_code); mutable Mutex intern_table_lock_; bool is_dirty_; diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc index ee9165e69a..f6b040def2 100644 --- a/src/intern_table_test.cc +++ b/src/intern_table_test.cc @@ -17,7 +17,7 @@ #include "intern_table.h" #include "common_test.h" -#include "object.h" +#include "mirror/object.h" #include "sirt_ref.h" namespace art { @@ -27,10 +27,10 @@ class InternTableTest : public CommonTest {}; TEST_F(InternTableTest, Intern) { ScopedObjectAccess soa(Thread::Current()); InternTable intern_table; - SirtRef<String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo")); - SirtRef<String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo")); - SirtRef<String> foo_3(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); - SirtRef<String> bar(soa.Self(), intern_table.InternStrong(3, "bar")); + SirtRef<mirror::String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo")); + SirtRef<mirror::String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo")); + SirtRef<mirror::String> foo_3(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> bar(soa.Self(), intern_table.InternStrong(3, "bar")); EXPECT_TRUE(foo_1->Equals("foo")); EXPECT_TRUE(foo_2->Equals("foo")); EXPECT_TRUE(foo_3->Equals("foo")); @@ -47,7 +47,7 @@ TEST_F(InternTableTest, Size) { InternTable t; EXPECT_EQ(0U, t.Size()); t.InternStrong(3, "foo"); - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); t.InternWeak(foo.get()); EXPECT_EQ(1U, t.Size()); t.InternStrong(3, "bar"); @@ -56,9 +56,9 @@ TEST_F(InternTableTest, Size) { class TestPredicate { public: - bool IsMarked(const Object* s) const { + bool IsMarked(const mirror::Object* s) const { bool erased = false; - typedef std::vector<const String*>::iterator It; // TODO: C++0x auto + typedef std::vector<const mirror::String*>::iterator It; // TODO: C++0x auto for (It it = expected_.begin(), end = expected_.end(); it != end; ++it) { if (*it == s) { expected_.erase(it); @@ -70,7 +70,7 @@ class TestPredicate { return false; } - void Expect(const String* s) { + void Expect(const mirror::String* s) { expected_.push_back(s); } @@ -79,10 +79,10 @@ class TestPredicate { } private: - mutable std::vector<const String*> expected_; + mutable std::vector<const mirror::String*> expected_; }; -bool IsMarked(const Object* object, void* arg) { +bool IsMarked(const mirror::Object* object, void* arg) { return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object); } @@ -91,10 +91,12 @@ TEST_F(InternTableTest, SweepInternTableWeaks) { InternTable t; t.InternStrong(3, "foo"); t.InternStrong(3, "bar"); - SirtRef<String> hello(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "hello")); - SirtRef<String> world(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "world")); - SirtRef<String> s0(soa.Self(), t.InternWeak(hello.get())); - SirtRef<String> s1(soa.Self(), t.InternWeak(world.get())); + SirtRef<mirror::String> hello(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello")); + SirtRef<mirror::String> world(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "world")); + SirtRef<mirror::String> s0(soa.Self(), t.InternWeak(hello.get())); + SirtRef<mirror::String> s1(soa.Self(), t.InternWeak(world.get())); EXPECT_EQ(4U, t.Size()); @@ -110,7 +112,8 @@ TEST_F(InternTableTest, SweepInternTableWeaks) { EXPECT_EQ(2U, t.Size()); // Just check that we didn't corrupt the map. - SirtRef<String> still_here(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "still here")); + SirtRef<mirror::String> still_here(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here")); t.InternWeak(still_here.get()); EXPECT_EQ(3U, t.Size()); } @@ -120,9 +123,9 @@ TEST_F(InternTableTest, ContainsWeak) { { // Strongs are never weak. InternTable t; - SirtRef<String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo")); + SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo")); EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get())); - SirtRef<String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo")); + SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo")); EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get())); EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get()); } @@ -130,11 +133,13 @@ TEST_F(InternTableTest, ContainsWeak) { { // Weaks are always weak. InternTable t; - SirtRef<String> foo_1(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); - SirtRef<String> foo_2(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> foo_1(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> foo_2(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); EXPECT_NE(foo_1.get(), foo_2.get()); - SirtRef<String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get())); - SirtRef<String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get())); + SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get())); + SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get())); EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get())); EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get()); } @@ -142,10 +147,10 @@ TEST_F(InternTableTest, ContainsWeak) { { // A weak can be promoted to a strong. InternTable t; - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); - SirtRef<String> interned_foo_1(soa.Self(), t.InternWeak(foo.get())); + SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo.get())); EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get())); - SirtRef<String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo")); + SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo")); EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get())); EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get()); } @@ -153,10 +158,11 @@ TEST_F(InternTableTest, ContainsWeak) { { // Interning a weak after a strong gets you the strong. InternTable t; - SirtRef<String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo")); + SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo")); EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get())); - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); - SirtRef<String> interned_foo_2(soa.Self(), t.InternWeak(foo.get())); + SirtRef<mirror::String> foo(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo.get())); EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get())); EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get()); } diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index 820348e081..65729c9394 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -19,18 +19,28 @@ #include <math.h> #include "base/logging.h" +#include "class_linker-inl.h" #include "common_throws.h" #include "debugger.h" #include "dex_instruction.h" +#include "gc/card_table-inl.h" #include "invoke_arg_array_builder.h" #include "nth_caller_visitor.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "runtime_support.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" #include "thread.h" +using namespace art::mirror; + namespace art { namespace interpreter { diff --git a/src/interpreter/interpreter.h b/src/interpreter/interpreter.h index 6990458934..eee13dc1b3 100644 --- a/src/interpreter/interpreter.h +++ b/src/interpreter/interpreter.h @@ -21,18 +21,20 @@ #include "locks.h" namespace art { - +namespace mirror { class AbstractMethod; +class Object; +} // namespace mirror + union JValue; class MethodHelper; -class Object; class ShadowFrame; class Thread; namespace interpreter { -extern void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* receiver, - JValue* args, JValue* result) +extern void EnterInterpreterFromInvoke(Thread* self, mirror::AbstractMethod* method, + mirror::Object* receiver, JValue* args, JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); extern JValue EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame& shadow_frame, diff --git a/src/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h index 16eedfe54d..19c42ac9b8 100644 --- a/src/invoke_arg_array_builder.h +++ b/src/invoke_arg_array_builder.h @@ -17,7 +17,7 @@ #ifndef ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_ #define ART_SRC_INVOKE_ARG_ARRAY_BUILDER_H_ -#include "object.h" +#include "mirror/object.h" #include "scoped_thread_state_change.h" namespace art { @@ -31,7 +31,7 @@ static inline size_t NumArgArrayBytes(const char* shorty, uint32_t shorty_len) { } else if (ch == 'L') { // Argument is a reference or an array. The shorty descriptor // does not distinguish between these types. - num_bytes += sizeof(Object*); + num_bytes += sizeof(mirror::Object*); } else { num_bytes += 4; } @@ -78,7 +78,7 @@ class ArgArray { arg_array_[offset].SetF(va_arg(ap, jdouble)); break; case 'L': - arg_array_[offset].SetL(soa.Decode<Object*>(va_arg(ap, jobject))); + arg_array_[offset].SetL(soa.Decode<mirror::Object*>(va_arg(ap, jobject))); break; case 'D': arg_array_[offset].SetD(va_arg(ap, jdouble)); @@ -113,7 +113,7 @@ class ArgArray { arg_array_[offset].SetF(args[offset].f); break; case 'L': - arg_array_[offset].SetL(soa.Decode<Object*>(args[offset].l)); + arg_array_[offset].SetL(soa.Decode<mirror::Object*>(args[offset].l)); break; case 'D': arg_array_[offset].SetD(args[offset].d); diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h index 6cac0f678d..71bae087fe 100644 --- a/src/jdwp/jdwp.h +++ b/src/jdwp/jdwp.h @@ -30,8 +30,9 @@ struct iovec; namespace art { - +namespace mirror { class AbstractMethod; +} // namespace mirror class Thread; namespace JDWP { diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc index ba2d8d23af..71e91d4958 100644 --- a/src/jdwp/jdwp_event.cc +++ b/src/jdwp/jdwp_event.cc @@ -28,6 +28,7 @@ #include "jdwp/jdwp_expand_buf.h" #include "jdwp/jdwp_handler.h" #include "jdwp/jdwp_priv.h" +#include "thread.h" /* General notes: diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc index cb1369576f..aa5a8a05d7 100644 --- a/src/jdwp/jdwp_handler.cc +++ b/src/jdwp/jdwp_handler.cc @@ -42,6 +42,9 @@ #include "jdwp/jdwp_event.h" #include "jdwp/jdwp_expand_buf.h" #include "jdwp/jdwp_priv.h" +#include "runtime.h" +#include "thread.h" +#include "UniquePtr.h" namespace art { diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc index 16976d4994..4ed789817f 100644 --- a/src/jni_compiler_test.cc +++ b/src/jni_compiler_test.cc @@ -21,6 +21,11 @@ #include "indirect_reference_table.h" #include "jni_internal.h" #include "mem_map.h" +#include "mirror/class.h" +#include "mirror/class_loader.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/stack_trace_element.h" #include "runtime.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" @@ -43,8 +48,9 @@ class JniCompilerTest : public CommonTest { const char* method_name, const char* method_sig) { ScopedObjectAccess soa(Thread::Current()); // Compile the native method before starting the runtime - Class* c = class_linker_->FindClass("LMyClassNatives;", soa.Decode<ClassLoader*>(class_loader)); - AbstractMethod* method; + mirror::Class* c = class_linker_->FindClass("LMyClassNatives;", + soa.Decode<mirror::ClassLoader*>(class_loader)); + mirror::AbstractMethod* method; if (direct) { method = c->FindDirectMethod(method_name, method_sig); } else { @@ -141,7 +147,7 @@ TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) { ScopedObjectAccess soa(Thread::Current()); std::string reason; ASSERT_TRUE( - Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_), + Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_), reason)) << reason; jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24); @@ -155,7 +161,7 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) { ScopedObjectAccess soa(Thread::Current()); std::string reason; ASSERT_TRUE( - Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_), + Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_), reason)) << reason; jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42); @@ -548,15 +554,15 @@ jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) { // Build stack trace jobject internal = Thread::Current()->CreateInternalStackTrace(soa); jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal); - ObjectArray<StackTraceElement>* trace_array = - soa.Decode<ObjectArray<StackTraceElement>*>(ste_array); + mirror::ObjectArray<mirror::StackTraceElement>* trace_array = + soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array); EXPECT_TRUE(trace_array != NULL); EXPECT_EQ(11, trace_array->GetLength()); // Check stack trace entries have expected values for (int32_t i = 0; i < trace_array->GetLength(); ++i) { EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber()); - StackTraceElement* ste = trace_array->Get(i); + mirror::StackTraceElement* ste = trace_array->Get(i); EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str()); EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str()); EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str()); @@ -601,7 +607,7 @@ jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) { // Add 10 local references ScopedObjectAccess soa(env); for (int i = 0; i < 10; i++) { - soa.AddLocalReference<jobject>(soa.Decode<Object*>(thisObj)); + soa.AddLocalReference<jobject>(soa.Decode<mirror::Object*>(thisObj)); } return x+1; } diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 84b5144a3a..0ee4c21ce4 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -27,19 +27,28 @@ #include "base/stl_util.h" #include "base/stringpiece.h" #include "class_linker.h" -#include "class_loader.h" +#include "gc/card_table-inl.h" #include "invoke_arg_array_builder.h" #include "jni.h" -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/field-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/throwable.h" #include "object_utils.h" #include "runtime.h" #include "safe_map.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" #include "thread.h" +#include "utf.h" #include "UniquePtr.h" #include "well_known_classes.h" +using namespace art::mirror; + namespace art { static const size_t kMonitorsInitial = 32; // Arbitrary. @@ -2533,6 +2542,11 @@ void JNIEnvExt::PopFrame() { stacked_local_ref_cookies.pop_back(); } +Offset JNIEnvExt::SegmentStateOffset() { + return Offset(OFFSETOF_MEMBER(JNIEnvExt, locals) + + IndirectReferenceTable::SegmentStateOffset().Int32Value()); +} + // JNI Invocation interface. extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) { @@ -2860,7 +2874,7 @@ void* JavaVMExt::FindCodeForNativeMethod(AbstractMethod* m) { return native_method; } -void JavaVMExt::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void JavaVMExt::VisitRoots(RootVisitor* visitor, void* arg) { Thread* self = Thread::Current(); { MutexLock mu(self, globals_lock); diff --git a/src/jni_internal.h b/src/jni_internal.h index 6b597ec09e..9b773f3a6d 100644 --- a/src/jni_internal.h +++ b/src/jni_internal.h @@ -21,9 +21,9 @@ #include "base/macros.h" #include "base/mutex.h" -#include "heap.h" #include "indirect_reference_table.h" #include "reference_table.h" +#include "root_visitor.h" #include "runtime.h" #include <iosfwd> @@ -37,12 +37,13 @@ RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods)) namespace art { - +namespace mirror { +class AbstractMethod; class ClassLoader; class Field; +} union JValue; class Libraries; -class AbstractMethod; class ScopedObjectAccess; class Thread; @@ -54,7 +55,8 @@ void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINat JValue InvokeWithJValues(const ScopedObjectAccess&, jobject obj, jmethodID mid, jvalue* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -JValue InvokeWithJValues(const ScopedObjectAccess&, Object* receiver, AbstractMethod* m, JValue* args) +JValue InvokeWithJValues(const ScopedObjectAccess&, mirror::Object* receiver, + mirror::AbstractMethod* m, JValue* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause); @@ -69,14 +71,15 @@ struct JavaVMExt : public JavaVM { * Returns 'true' on success. On failure, sets 'detail' to a * human-readable description of the error. */ - bool LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, std::string& detail) + bool LoadNativeLibrary(const std::string& path, mirror::ClassLoader* class_loader, + std::string& detail) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /** * Returns a pointer to the code for the native method 'm', found * using dlsym(3) on every native library that's been loaded so far. */ - void* FindCodeForNativeMethod(AbstractMethod* m) + void* FindCodeForNativeMethod(mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DumpForSigQuit(std::ostream& os); @@ -86,7 +89,7 @@ struct JavaVMExt : public JavaVM { void SetCheckJniEnabled(bool enabled); - void VisitRoots(Heap::RootVisitor*, void*); + void VisitRoots(RootVisitor*, void*); Runtime* runtime; @@ -135,10 +138,7 @@ struct JNIEnvExt : public JNIEnv { void PushFrame(int capacity); void PopFrame(); - static Offset SegmentStateOffset() { - return Offset(OFFSETOF_MEMBER(JNIEnvExt, locals) + - IndirectReferenceTable::SegmentStateOffset().Int32Value()); - } + static Offset SegmentStateOffset(); static Offset LocalRefCookieOffset() { return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie)); diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc index 7201233c05..a945ba6199 100644 --- a/src/jni_internal_test.cc +++ b/src/jni_internal_test.cc @@ -20,6 +20,8 @@ #include <cmath> #include "common_test.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "ScopedLocalRef.h" #include "sirt_ref.h" @@ -70,15 +72,17 @@ class JniInternalTest : public CommonTest { CommonTest::TearDown(); } - AbstractMethod::InvokeStub* DoCompile(AbstractMethod*& method, Object*& receiver, bool is_static, - const char* method_name, const char* method_signature) + mirror::AbstractMethod::InvokeStub* DoCompile(mirror::AbstractMethod*& method, + mirror::Object*& receiver, + bool is_static, const char* method_name, + const char* method_signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods"; jobject jclass_loader(LoadDex(class_name)); Thread* self = Thread::Current(); - SirtRef<ClassLoader> + SirtRef<mirror::ClassLoader> class_loader(self, - ScopedObjectAccessUnchecked(self).Decode<ClassLoader*>(jclass_loader)); + ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader*>(jclass_loader)); if (is_static) { CompileDirectMethod(class_loader.get(), class_name, method_name, method_signature); } else { @@ -87,7 +91,7 @@ class JniInternalTest : public CommonTest { CompileVirtualMethod(class_loader.get(), class_name, method_name, method_signature); } - Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader.get()); + mirror::Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader.get()); CHECK(c != NULL); method = is_static ? c->FindDirectMethod(method_name, method_signature) @@ -96,24 +100,25 @@ class JniInternalTest : public CommonTest { receiver = (is_static ? NULL : c->AllocObject(self)); - AbstractMethod::InvokeStub* stub = method->GetInvokeStub(); + mirror::AbstractMethod::InvokeStub* stub = method->GetInvokeStub(); CHECK(stub != NULL); return stub; } void InvokeNopMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V"); (*stub)(method, receiver, Thread::Current(), NULL, NULL); } void InvokeIdentityByteMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(B)B"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "identity", "(B)B"); JValue args[1]; JValue result; @@ -141,9 +146,10 @@ class JniInternalTest : public CommonTest { void InvokeIdentityIntMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(I)I"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "identity", "(I)I"); JValue args[1]; JValue result; @@ -171,9 +177,10 @@ class JniInternalTest : public CommonTest { void InvokeIdentityDoubleMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(D)D"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "identity", "(D)D"); JValue args[1]; JValue result; @@ -201,9 +208,10 @@ class JniInternalTest : public CommonTest { void InvokeSumIntIntMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(II)I"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(II)I"); JValue result; result.SetI(-1); @@ -240,9 +248,10 @@ class JniInternalTest : public CommonTest { void InvokeSumIntIntIntMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(III)I"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(III)I"); JValue result; result.SetI(-1); @@ -284,9 +293,10 @@ class JniInternalTest : public CommonTest { void InvokeSumIntIntIntIntMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIII)I"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(IIII)I"); JValue result; result.SetI(-1); @@ -333,9 +343,10 @@ class JniInternalTest : public CommonTest { void InvokeSumIntIntIntIntIntMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIIII)I"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(IIIII)I"); JValue result; result.SetI(-1.0); @@ -387,9 +398,10 @@ class JniInternalTest : public CommonTest { void InvokeSumDoubleDoubleMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DD)D"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(DD)D"); JValue args[2]; JValue result; @@ -427,9 +439,10 @@ class JniInternalTest : public CommonTest { void InvokeSumDoubleDoubleDoubleMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDD)D"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(DDD)D"); JValue args[3]; JValue result; @@ -458,9 +471,10 @@ class JniInternalTest : public CommonTest { void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDD)D"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(DDDD)D"); JValue args[4]; JValue result; @@ -492,9 +506,10 @@ class JniInternalTest : public CommonTest { void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; - Object* receiver; - AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDDD)D"); + mirror::AbstractMethod* method; + mirror::Object* receiver; + mirror::AbstractMethod::InvokeStub* stub = + DoCompile(method, receiver, is_static, "sum", "(DDDDD)D"); JValue args[5]; JValue result; @@ -1270,7 +1285,7 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { jobject outer; jobject inner1, inner2; ScopedObjectAccess soa(env_); - Object* inner2_direct_pointer; + mirror::Object* inner2_direct_pointer; { env_->PushLocalFrame(4); outer = env_->NewLocalRef(original); @@ -1279,7 +1294,7 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { env_->PushLocalFrame(4); inner1 = env_->NewLocalRef(outer); inner2 = env_->NewStringUTF("survivor"); - inner2_direct_pointer = soa.Decode<Object*>(inner2); + inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2); env_->PopLocalFrame(inner2); } @@ -1393,16 +1408,17 @@ TEST_F(JniInternalTest, DeleteWeakGlobalRef) { TEST_F(JniInternalTest, StaticMainMethod) { ScopedObjectAccess soa(Thread::Current()); jobject jclass_loader = LoadDex("Main"); - SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader)); + SirtRef<mirror::ClassLoader> + class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader)); CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V"); - Class* klass = class_linker_->FindClass("LMain;", class_loader.get()); + mirror::Class* klass = class_linker_->FindClass("LMain;", class_loader.get()); ASSERT_TRUE(klass != NULL); - AbstractMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V"); + mirror::AbstractMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V"); ASSERT_TRUE(method != NULL); - AbstractMethod::InvokeStub* stub = method->GetInvokeStub(); + mirror::AbstractMethod::InvokeStub* stub = method->GetInvokeStub(); JValue args[1]; args[0].SetL(NULL); diff --git a/src/jobject_comparator.cc b/src/jobject_comparator.cc index edd072738a..738a186874 100644 --- a/src/jobject_comparator.cc +++ b/src/jobject_comparator.cc @@ -16,7 +16,9 @@ #include "jobject_comparator.h" -#include "object.h" +#include "mirror/array-inl.h" +#include "mirror/class.h" +#include "mirror/object-inl.h" #include "scoped_thread_state_change.h" namespace art { @@ -29,8 +31,8 @@ bool JobjectComparator::operator()(jobject jobj1, jobject jobj2) const { return false; } ScopedObjectAccess soa(Thread::Current()); - Object* obj1 = soa.Decode<Object*>(jobj1); - Object* obj2 = soa.Decode<Object*>(jobj2); + mirror::Object* obj1 = soa.Decode<mirror::Object*>(jobj1); + mirror::Object* obj2 = soa.Decode<mirror::Object*>(jobj2); if (obj1 == NULL) { return true; } else if (obj2 == NULL) { diff --git a/src/jvalue.h b/src/jvalue.h index a7a17956bf..fa85937dcd 100644 --- a/src/jvalue.h +++ b/src/jvalue.h @@ -20,8 +20,9 @@ #include "base/macros.h" namespace art { - +namespace mirror { class Object; +} // namespace mirror union PACKED(4) JValue { // We default initialize JValue instances to all-zeros. @@ -47,8 +48,8 @@ union PACKED(4) JValue { int64_t GetJ() const { return j; } void SetJ(int64_t new_j) { j = new_j; } - Object* GetL() const { return l; } - void SetL(Object* new_l) { l = new_l; } + mirror::Object* GetL() const { return l; } + void SetL(mirror::Object* new_l) { l = new_l; } int16_t GetS() const { return s; } void SetS(int16_t new_s) { @@ -67,7 +68,7 @@ union PACKED(4) JValue { int64_t j; float f; double d; - Object* l; + mirror::Object* l; }; } // namespace art diff --git a/src/mirror/abstract_method-inl.h b/src/mirror/abstract_method-inl.h new file mode 100644 index 0000000000..efb7c03300 --- /dev/null +++ b/src/mirror/abstract_method-inl.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_METHOD_INL_H_ +#define ART_SRC_MIRROR_METHOD_INL_H_ + +#include "abstract_method.h" + +#include "array.h" +#include "dex_file.h" +#include "runtime.h" + +namespace art { +namespace mirror { + +inline Class* AbstractMethod::GetDeclaringClass() const { + Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), false); + DCHECK(result != NULL) << this; + DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this; + return result; +} + +inline void AbstractMethod::SetDeclaringClass(Class *new_declaring_class) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), new_declaring_class, false); +} + +inline uint32_t AbstractMethod::GetAccessFlags() const { + DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), false); +} + +inline uint16_t AbstractMethod::GetMethodIndex() const { + DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), false); +} + +inline uint32_t AbstractMethod::GetDexMethodIndex() const { + DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), false); +} + +inline uint32_t AbstractMethod::GetCodeSize() const { + DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); + uintptr_t code = reinterpret_cast<uintptr_t>(GetCode()); + if (code == 0) { + return 0; + } + // TODO: make this Thumb2 specific + code &= ~0x1; + return reinterpret_cast<uint32_t*>(code)[-1]; +} + +inline bool AbstractMethod::CheckIncompatibleClassChange(InvokeType type) { + switch (type) { + case kStatic: + return !IsStatic(); + case kDirect: + return !IsDirect() || IsStatic(); + case kVirtual: { + Class* methods_class = GetDeclaringClass(); + return IsDirect() || (methods_class->IsInterface() && !IsMiranda()); + } + case kSuper: + return false; // TODO: appropriate checks for call to super class. + case kInterface: { + Class* methods_class = GetDeclaringClass(); + return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); + } + default: + LOG(FATAL) << "Unreachable - invocation type: " << type; + return true; + } +} + +inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const { + if (!kIsDebugBuild) { + return; + } + if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) { + return; + } + Runtime* runtime = Runtime::Current(); + if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) { + return; + } + DCHECK(IsWithinCode(pc)) + << PrettyMethod(this) + << " pc=" << std::hex << pc + << " code=" << GetCode() + << " size=" << GetCodeSize(); +} + +inline uint32_t AbstractMethod::GetOatCodeOffset() const { + DCHECK(!Runtime::Current()->IsStarted()); + return reinterpret_cast<uint32_t>(GetCode()); +} + +inline void AbstractMethod::SetOatCodeOffset(uint32_t code_offset) { + DCHECK(!Runtime::Current()->IsStarted()); + SetCode(reinterpret_cast<void*>(code_offset)); +} + +inline uint32_t AbstractMethod::GetOatMappingTableOffset() const { + DCHECK(!Runtime::Current()->IsStarted()); + return reinterpret_cast<uint32_t>(GetMappingTableRaw()); +} + +inline void AbstractMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) { + DCHECK(!Runtime::Current()->IsStarted()); + SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table_offset)); +} + +inline uint32_t AbstractMethod::GetOatVmapTableOffset() const { + DCHECK(!Runtime::Current()->IsStarted()); + return reinterpret_cast<uint32_t>(GetVmapTableRaw()); +} + +inline void AbstractMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) { + DCHECK(!Runtime::Current()->IsStarted()); + SetVmapTable(reinterpret_cast<uint16_t*>(vmap_table_offset)); +} + +inline void AbstractMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { + DCHECK(!Runtime::Current()->IsStarted()); + SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); +} + +inline uint32_t AbstractMethod::GetOatNativeGcMapOffset() const { + DCHECK(!Runtime::Current()->IsStarted()); + return reinterpret_cast<uint32_t>(GetNativeGcMap()); +} + +inline uint32_t AbstractMethod::GetOatInvokeStubOffset() const { + DCHECK(!Runtime::Current()->IsStarted()); + return reinterpret_cast<uint32_t>(GetInvokeStub()); +} + +inline void AbstractMethod::SetOatInvokeStubOffset(uint32_t invoke_stub_offset) { + DCHECK(!Runtime::Current()->IsStarted()); + SetInvokeStub(reinterpret_cast<InvokeStub*>(invoke_stub_offset)); +} + +inline bool AbstractMethod::IsRuntimeMethod() const { + return GetDexMethodIndex() == DexFile::kDexNoIndex16; +} + +inline bool AbstractMethod::IsCalleeSaveMethod() const { + if (!IsRuntimeMethod()) { + return false; + } + Runtime* runtime = Runtime::Current(); + bool result = false; + for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { + if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) { + result = true; + break; + } + } + return result; +} + +inline bool AbstractMethod::IsResolutionMethod() const { + bool result = this == Runtime::Current()->GetResolutionMethod(); + // Check that if we do think it is phony it looks like the resolution method. + DCHECK(!result || IsRuntimeMethod()); + return result; +} +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_METHOD_INL_H_ diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc new file mode 100644 index 0000000000..4641941ef9 --- /dev/null +++ b/src/mirror/abstract_method.cc @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abstract_method.h" + +#include "abstract_method-inl.h" +#include "class-inl.h" +#include "base/stringpiece.h" +#include "gc/card_table-inl.h" +#include "interpreter/interpreter.h" +#include "jni_internal.h" +#include "object-inl.h" +#include "object_array.h" +#include "object_array-inl.h" +#include "string.h" +#include "object_utils.h" + +namespace art { +namespace mirror { + +// TODO: get global references for these +Class* AbstractMethod::java_lang_reflect_Constructor_ = NULL; +Class* AbstractMethod::java_lang_reflect_Method_ = NULL; + +InvokeType AbstractMethod::GetInvokeType() const { + // TODO: kSuper? + if (GetDeclaringClass()->IsInterface()) { + return kInterface; + } else if (IsStatic()) { + return kStatic; + } else if (IsDirect()) { + return kDirect; + } else { + return kVirtual; + } +} + +void AbstractMethod::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) { + CHECK(java_lang_reflect_Constructor_ == NULL); + CHECK(java_lang_reflect_Constructor != NULL); + java_lang_reflect_Constructor_ = java_lang_reflect_Constructor; + + CHECK(java_lang_reflect_Method_ == NULL); + CHECK(java_lang_reflect_Method != NULL); + java_lang_reflect_Method_ = java_lang_reflect_Method; +} + +void AbstractMethod::ResetClasses() { + CHECK(java_lang_reflect_Constructor_ != NULL); + java_lang_reflect_Constructor_ = NULL; + + CHECK(java_lang_reflect_Method_ != NULL); + java_lang_reflect_Method_ = NULL; +} + +ObjectArray<String>* AbstractMethod::GetDexCacheStrings() const { + return GetFieldObject<ObjectArray<String>*>( + OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), false); +} + +void AbstractMethod::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), + new_dex_cache_strings, false); +} + +ObjectArray<AbstractMethod>* AbstractMethod::GetDexCacheResolvedMethods() const { + return GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), false); +} + +void AbstractMethod::SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), + new_dex_cache_methods, false); +} + +ObjectArray<Class>* AbstractMethod::GetDexCacheResolvedTypes() const { + return GetFieldObject<ObjectArray<Class>*>( + OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), false); +} + +void AbstractMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), + new_dex_cache_classes, false); +} + +ObjectArray<StaticStorageBase>* AbstractMethod::GetDexCacheInitializedStaticStorage() const { + return GetFieldObject<ObjectArray<StaticStorageBase>*>( + OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), + false); +} + +void AbstractMethod::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), + new_value, false); +} + +size_t AbstractMethod::NumArgRegisters(const StringPiece& shorty) { + CHECK_LE(1, shorty.length()); + uint32_t num_registers = 0; + for (int i = 1; i < shorty.length(); ++i) { + char ch = shorty[i]; + if (ch == 'D' || ch == 'J') { + num_registers += 2; + } else { + num_registers += 1; + } + } + return num_registers; +} + +bool AbstractMethod::IsProxyMethod() const { + return GetDeclaringClass()->IsProxyClass(); +} + +AbstractMethod* AbstractMethod::FindOverriddenMethod() const { + if (IsStatic()) { + return NULL; + } + Class* declaring_class = GetDeclaringClass(); + Class* super_class = declaring_class->GetSuperClass(); + uint16_t method_index = GetMethodIndex(); + ObjectArray<AbstractMethod>* super_class_vtable = super_class->GetVTable(); + AbstractMethod* result = NULL; + // Did this method override a super class method? If so load the result from the super class' + // vtable + if (super_class_vtable != NULL && method_index < super_class_vtable->GetLength()) { + result = super_class_vtable->Get(method_index); + } else { + // Method didn't override superclass method so search interfaces + if (IsProxyMethod()) { + result = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex()); + CHECK_EQ(result, + Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this)); + } else { + MethodHelper mh(this); + MethodHelper interface_mh; + IfTable* iftable = GetDeclaringClass()->GetIfTable(); + for (size_t i = 0; i < iftable->Count() && result == NULL; i++) { + Class* interface = iftable->GetInterface(i); + for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { + AbstractMethod* interface_method = interface->GetVirtualMethod(j); + interface_mh.ChangeMethod(interface_method); + if (mh.HasSameNameAndSignature(&interface_mh)) { + result = interface_method; + break; + } + } + } + } + } +#ifndef NDEBUG + MethodHelper result_mh(result); + DCHECK(result == NULL || MethodHelper(this).HasSameNameAndSignature(&result_mh)); +#endif + return result; +} + +static const void* GetOatCode(const AbstractMethod* m) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + Runtime* runtime = Runtime::Current(); + const void* code = m->GetCode(); + // Peel off any method tracing trampoline. + if (runtime->IsMethodTracingActive() && runtime->GetInstrumentation()->GetSavedCodeFromMap(m) != NULL) { + code = runtime->GetInstrumentation()->GetSavedCodeFromMap(m); + } + // Peel off any resolution stub. + if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) { + code = runtime->GetClassLinker()->GetOatCodeFor(m); + } + return code; +} + +uintptr_t AbstractMethod::NativePcOffset(const uintptr_t pc) const { + return pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); +} + +// Find the lowest-address native safepoint pc for a given dex pc +uintptr_t AbstractMethod::ToFirstNativeSafepointPc(const uint32_t dex_pc) const { +#if !defined(ART_USE_LLVM_COMPILER) + const uint32_t* mapping_table = GetPcToDexMappingTable(); + if (mapping_table == NULL) { + DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); + return DexFile::kDexNoIndex; // Special no mapping case + } + size_t mapping_table_length = GetPcToDexMappingTableLength(); + for (size_t i = 0; i < mapping_table_length; i += 2) { + if (mapping_table[i + 1] == dex_pc) { + return mapping_table[i] + reinterpret_cast<uintptr_t>(GetOatCode(this)); + } + } + LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc + << " in " << PrettyMethod(this); + return 0; +#else + // Compiler LLVM doesn't use the machine pc, we just use dex pc instead. + return static_cast<uint32_t>(dex_pc); +#endif +} + +uint32_t AbstractMethod::ToDexPc(const uintptr_t pc) const { +#if !defined(ART_USE_LLVM_COMPILER) + const uint32_t* mapping_table = GetPcToDexMappingTable(); + if (mapping_table == NULL) { + DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); + return DexFile::kDexNoIndex; // Special no mapping case + } + size_t mapping_table_length = GetPcToDexMappingTableLength(); + uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); + for (size_t i = 0; i < mapping_table_length; i += 2) { + if (mapping_table[i] == sought_offset) { + return mapping_table[i + 1]; + } + } + LOG(ERROR) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset) + << "(PC " << reinterpret_cast<void*>(pc) << ") in " << PrettyMethod(this); + return DexFile::kDexNoIndex; +#else + // Compiler LLVM doesn't use the machine pc, we just use dex pc instead. + return static_cast<uint32_t>(pc); +#endif +} + +uintptr_t AbstractMethod::ToNativePc(const uint32_t dex_pc) const { + const uint32_t* mapping_table = GetDexToPcMappingTable(); + if (mapping_table == NULL) { + DCHECK_EQ(dex_pc, 0U); + return 0; // Special no mapping/pc == 0 case + } + size_t mapping_table_length = GetDexToPcMappingTableLength(); + for (size_t i = 0; i < mapping_table_length; i += 2) { + uint32_t map_offset = mapping_table[i]; + uint32_t map_dex_offset = mapping_table[i + 1]; + if (map_dex_offset == dex_pc) { + return reinterpret_cast<uintptr_t>(GetOatCode(this)) + map_offset; + } + } + LOG(FATAL) << "Looking up Dex PC not contained in method, 0x" << std::hex << dex_pc + << " in " << PrettyMethod(this); + return 0; +} + +uint32_t AbstractMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const { + MethodHelper mh(this); + const DexFile::CodeItem* code_item = mh.GetCodeItem(); + // Iterate over the catch handlers associated with dex_pc + for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) { + uint16_t iter_type_idx = it.GetHandlerTypeIndex(); + // Catch all case + if (iter_type_idx == DexFile::kDexNoIndex16) { + return it.GetHandlerAddress(); + } + // Does this catch exception type apply? + Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); + if (iter_exception_type == NULL) { + // The verifier should take care of resolving all exception classes early + LOG(WARNING) << "Unresolved exception class when finding catch block: " + << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx); + } else if (iter_exception_type->IsAssignableFrom(exception_type)) { + return it.GetHandlerAddress(); + } + } + // Handler not found + return DexFile::kDexNoIndex; +} + +void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) { + if (kIsDebugBuild) { + self->AssertThreadSuspensionIsAllowable(); + CHECK_EQ(kRunnable, self->GetState()); + } + + // Push a transition back into managed code onto the linked list in thread. + ManagedStack fragment; + self->PushManagedStackFragment(&fragment); + + // Call the invoke stub associated with the method. + // Pass everything as arguments. + AbstractMethod::InvokeStub* stub = GetInvokeStub(); + + if (UNLIKELY(!Runtime::Current()->IsStarted())){ + LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started"; + if (result != NULL) { + result->SetJ(0); + } + } else { + bool interpret = self->ReadFlag(kEnterInterpreter) && !IsNative() && !IsProxyMethod(); + const bool kLogInvocationStartAndReturn = false; + if (!interpret && GetCode() != NULL && stub != NULL) { + if (kLogInvocationStartAndReturn) { + LOG(INFO) << StringPrintf("Invoking '%s' code=%p stub=%p", + PrettyMethod(this).c_str(), GetCode(), stub); + } + (*stub)(this, receiver, self, args, result); + if (kLogInvocationStartAndReturn) { + LOG(INFO) << StringPrintf("Returned '%s' code=%p stub=%p", + PrettyMethod(this).c_str(), GetCode(), stub); + } + } else { + const bool kInterpretMethodsWithNoCode = false; + if (interpret || kInterpretMethodsWithNoCode) { + if (kLogInvocationStartAndReturn) { + LOG(INFO) << "Interpreting " << PrettyMethod(this) << "'"; + } + art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args, result); + if (kLogInvocationStartAndReturn) { + LOG(INFO) << "Returned '" << PrettyMethod(this) << "'"; + } + } else { + LOG(INFO) << "Not invoking '" << PrettyMethod(this) + << "' code=" << reinterpret_cast<const void*>(GetCode()) + << " stub=" << reinterpret_cast<void*>(stub); + if (result != NULL) { + result->SetJ(0); + } + } + } + } + + // Pop transition. + self->PopManagedStackFragment(fragment); +} + +bool AbstractMethod::IsRegistered() const { + void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), false); + CHECK(native_method != NULL); + void* jni_stub = Runtime::Current()->GetJniDlsymLookupStub()->GetData(); + return native_method != jni_stub; +} + +void AbstractMethod::RegisterNative(Thread* self, const void* native_method) { + DCHECK(Thread::Current() == self); + CHECK(IsNative()) << PrettyMethod(this); + CHECK(native_method != NULL) << PrettyMethod(this); + if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) { + SetNativeMethod(native_method); + } else { + // We've been asked to associate this method with the given native method but are working + // around JNI bugs, that include not giving Object** SIRT references to native methods. Direct + // the native method to runtime support and store the target somewhere runtime support will + // find it. +#if defined(__arm__) && !defined(ART_USE_LLVM_COMPILER) + SetNativeMethod(native_method); +#else + UNIMPLEMENTED(FATAL); +#endif + SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), + reinterpret_cast<const uint8_t*>(native_method), false); + } +} + +void AbstractMethod::UnregisterNative(Thread* self) { + CHECK(IsNative()) << PrettyMethod(this); + // restore stub to lookup native pointer via dlsym + RegisterNative(self, Runtime::Current()->GetJniDlsymLookupStub()->GetData()); +} + +void AbstractMethod::SetNativeMethod(const void* native_method) { + SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), + native_method, false); +} + +} // namespace mirror +} // namespace art diff --git a/src/mirror/abstract_method.h b/src/mirror/abstract_method.h new file mode 100644 index 0000000000..1d57abb1d2 --- /dev/null +++ b/src/mirror/abstract_method.h @@ -0,0 +1,524 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_METHOD_H_ +#define ART_SRC_MIRROR_METHOD_H_ + +#include "class.h" +#include "invoke_type.h" +#include "locks.h" +#include "modifiers.h" +#include "object.h" + +namespace art { + +struct AbstractMethodOffsets; +struct ConstructorMethodOffsets; +union JValue; +struct MethodClassOffsets; +struct MethodOffsets; +class StringPiece; + +namespace mirror { + +class StaticStorageBase; + +// C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor +class MANAGED AbstractMethod : public Object { + public: + // A function that invokes a method with an array of its arguments. + typedef void InvokeStub(const AbstractMethod* method, + Object* obj, + Thread* thread, + JValue* args, + JValue* result); + + Class* GetDeclaringClass() const; + + void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static MemberOffset DeclaringClassOffset() { + return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_)); + } + + uint32_t GetAccessFlags() const; + + void SetAccessFlags(uint32_t new_access_flags) { + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), new_access_flags, false); + } + + // Approximate what kind of method call would be used for this method. + InvokeType GetInvokeType() const; + + // Returns true if the method is declared public. + bool IsPublic() const { + return (GetAccessFlags() & kAccPublic) != 0; + } + + // Returns true if the method is declared private. + bool IsPrivate() const { + return (GetAccessFlags() & kAccPrivate) != 0; + } + + // Returns true if the method is declared static. + bool IsStatic() const { + return (GetAccessFlags() & kAccStatic) != 0; + } + + // Returns true if the method is a constructor. + bool IsConstructor() const { + return (GetAccessFlags() & kAccConstructor) != 0; + } + + // Returns true if the method is static, private, or a constructor. + bool IsDirect() const { + return IsDirect(GetAccessFlags()); + } + + static bool IsDirect(uint32_t access_flags) { + return (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0; + } + + // Returns true if the method is declared synchronized. + bool IsSynchronized() const { + uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized; + return (GetAccessFlags() & synchonized) != 0; + } + + bool IsFinal() const { + return (GetAccessFlags() & kAccFinal) != 0; + } + + bool IsMiranda() const { + return (GetAccessFlags() & kAccMiranda) != 0; + } + + bool IsNative() const { + return (GetAccessFlags() & kAccNative) != 0; + } + + bool IsAbstract() const { + return (GetAccessFlags() & kAccAbstract) != 0; + } + + bool IsSynthetic() const { + return (GetAccessFlags() & kAccSynthetic) != 0; + } + + bool IsProxyMethod() const; + + bool CheckIncompatibleClassChange(InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + uint16_t GetMethodIndex() const; + + size_t GetVtableIndex() const { + return GetMethodIndex(); + } + + void SetMethodIndex(uint16_t new_method_index) { + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), new_method_index, false); + } + + static MemberOffset MethodIndexOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_); + } + + uint32_t GetCodeItemOffset() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), false); + } + + void SetCodeItemOffset(uint32_t new_code_off) { + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), new_code_off, false); + } + + // Number of 32bit registers that would be required to hold all the arguments + static size_t NumArgRegisters(const StringPiece& shorty); + + uint32_t GetDexMethodIndex() const; + + void SetDexMethodIndex(uint32_t new_idx) { + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), new_idx, false); + } + + ObjectArray<String>* GetDexCacheStrings() const; + void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static MemberOffset DexCacheStringsOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_); + } + + static MemberOffset DexCacheResolvedMethodsOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_); + } + + static MemberOffset DexCacheResolvedTypesOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_); + } + + static MemberOffset DexCacheInitializedStaticStorageOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, + dex_cache_initialized_static_storage_); + } + + ObjectArray<AbstractMethod>* GetDexCacheResolvedMethods() const; + void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<Class>* GetDexCacheResolvedTypes() const; + void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const; + void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Find the method that this method overrides + AbstractMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + const void* GetCode() const { + return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), false); + } + + void SetCode(const void* code) { + SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), code, false); + } + + uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsWithinCode(uintptr_t pc) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uintptr_t code = reinterpret_cast<uintptr_t>(GetCode()); + if (code == 0) { + return pc == 0; + } + /* + * During a stack walk, a return PC may point to the end of the code + 1 + * (in the case that the last instruction is a call that isn't expected to + * return. Thus, we check <= code + GetCodeSize(). + */ + return (code <= pc && pc <= code + GetCodeSize()); + } + + void AssertPcIsWithinCode(uintptr_t pc) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + uint32_t GetOatCodeOffset() const; + + void SetOatCodeOffset(uint32_t code_offset); + + static MemberOffset GetCodeOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_); + } + + const uint32_t* GetMappingTable() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return map; + } + return map + 1; + } + + uint32_t GetPcToDexMappingTableLength() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return 0; + } + return map[2]; + } + + const uint32_t* GetPcToDexMappingTable() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return map; + } + return map + 3; + } + + + uint32_t GetDexToPcMappingTableLength() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return 0; + } + return map[1] - map[2]; + } + + const uint32_t* GetDexToPcMappingTable() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return map; + } + return map + 3 + map[2]; + } + + + const uint32_t* GetMappingTableRaw() const { + return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), false); + } + + void SetMappingTable(const uint32_t* mapping_table) { + SetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), + mapping_table, false); + } + + uint32_t GetOatMappingTableOffset() const; + + void SetOatMappingTableOffset(uint32_t mapping_table_offset); + + // Callers should wrap the uint16_t* in a VmapTable instance for convenient access. + const uint16_t* GetVmapTableRaw() const { + return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), false); + } + + void SetVmapTable(const uint16_t* vmap_table) { + SetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), vmap_table, false); + } + + uint32_t GetOatVmapTableOffset() const; + + void SetOatVmapTableOffset(uint32_t vmap_table_offset); + + const uint8_t* GetNativeGcMap() const { + return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), false); + } + void SetNativeGcMap(const uint8_t* data) { + SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), data, + false); + } + + // When building the oat need a convenient place to stuff the offset of the native GC map. + void SetOatNativeGcMapOffset(uint32_t gc_map_offset); + uint32_t GetOatNativeGcMapOffset() const; + + size_t GetFrameSizeInBytes() const { + DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); + size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), false); + DCHECK_LE(static_cast<size_t>(kStackAlignment), result); + return result; + } + + void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) { + DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), + new_frame_size_in_bytes, false); + } + + size_t GetReturnPcOffsetInBytes() const { + return GetFrameSizeInBytes() - kPointerSize; + } + + bool IsRegistered() const; + + void RegisterNative(Thread* self, const void* native_method) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static MemberOffset NativeMethodOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_); + } + + const void* GetNativeMethod() const { + return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false)); + } + + void SetNativeMethod(const void*); + + // Native to managed invocation stub entry point + InvokeStub* GetInvokeStub() const { + InvokeStub* result = GetFieldPtr<InvokeStub*>( + OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), false); + // TODO: DCHECK(result != NULL); should be ahead of time compiled + return result; + } + + void SetInvokeStub(InvokeStub* invoke_stub) { + SetFieldPtr<InvokeStub*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), + invoke_stub, false); + } + + uint32_t GetInvokeStubSize() const { + uintptr_t invoke_stub = reinterpret_cast<uintptr_t>(GetInvokeStub()); + if (invoke_stub == 0) { + return 0; + } + // TODO: make this Thumb2 specific + invoke_stub &= ~0x1; + return reinterpret_cast<const uint32_t*>(invoke_stub)[-1]; + } + + uint32_t GetOatInvokeStubOffset() const; + void SetOatInvokeStubOffset(uint32_t invoke_stub_offset); + + static MemberOffset GetInvokeStubOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_); + } + + static MemberOffset GetMethodIndexOffset() { + return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_); + } + + uint32_t GetCoreSpillMask() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), false); + } + + void SetCoreSpillMask(uint32_t core_spill_mask) { + // Computed during compilation + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), core_spill_mask, false); + } + + uint32_t GetFpSpillMask() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), false); + } + + void SetFpSpillMask(uint32_t fp_spill_mask) { + // Computed during compilation + SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), fp_spill_mask, false); + } + + // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal + // conventions for a method of managed code. Returns false for Proxy methods. + bool IsRuntimeMethod() const; + + // Is this a hand crafted method used for something like describing callee saves? + bool IsCalleeSaveMethod() const; + + bool IsResolutionMethod() const; + + uintptr_t NativePcOffset(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Converts a native PC to a dex PC. + uint32_t ToDexPc(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Converts a dex PC to a native PC. + uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Converts a dex PC to the first corresponding safepoint PC. + uintptr_t ToFirstNativeSafepointPc(const uint32_t dex_pc) + const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Find the catch block for the given exception type and dex_pc + uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static void SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method); + + static Class* GetConstructorClass() { + return java_lang_reflect_Constructor_; + } + + static Class* GetMethodClass() { + return java_lang_reflect_Method_; + } + + static void ResetClasses(); + + protected: + // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". + // The class we are a part of + Class* declaring_class_; + + // short cuts to declaring_class_->dex_cache_ member for fast compiled code access + ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_; + + // short cuts to declaring_class_->dex_cache_ member for fast compiled code access + ObjectArray<AbstractMethod>* dex_cache_resolved_methods_; + + // short cuts to declaring_class_->dex_cache_ member for fast compiled code access + ObjectArray<Class>* dex_cache_resolved_types_; + + // short cuts to declaring_class_->dex_cache_ member for fast compiled code access + ObjectArray<String>* dex_cache_strings_; + + // Access flags; low 16 bits are defined by spec. + uint32_t access_flags_; + + // Compiled code associated with this method for callers from managed code. + // May be compiled managed code or a bridge for invoking a native method. + const void* code_; + + // Offset to the CodeItem. + uint32_t code_item_offset_; + + // Architecture-dependent register spill mask + uint32_t core_spill_mask_; + + // Architecture-dependent register spill mask + uint32_t fp_spill_mask_; + + // Total size in bytes of the frame + size_t frame_size_in_bytes_; + + // Garbage collection map of native PC offsets to reference bitmaps. + const uint8_t* native_gc_map_; + + // Native invocation stub entry point for calling from native to managed code. + InvokeStub* invoke_stub_; + + // Mapping from native pc to dex pc + const uint32_t* mapping_table_; + + // Index into method_ids of the dex file associated with this method + uint32_t method_dex_index_; + + // For concrete virtual methods, this is the offset of the method in Class::vtable_. + // + // For abstract methods in an interface class, this is the offset of the method in + // "iftable_->Get(n)->GetMethodArray()". + // + // For static and direct methods this is the index in the direct methods table. + uint32_t method_index_; + + // The target native method registered with this method + const void* native_method_; + + // When a register is promoted into a register, the spill mask holds which registers hold dex + // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth + // is vmap_table_[N]. vmap_table_[0] holds the length of the table. + const uint16_t* vmap_table_; + + static Class* java_lang_reflect_Constructor_; + static Class* java_lang_reflect_Method_; + + friend struct art::AbstractMethodOffsets; // for verifying offset information + friend struct art::ConstructorMethodOffsets; // for verifying offset information + friend struct art::MethodOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod); +}; + +class MANAGED Method : public AbstractMethod { + +}; + +class MANAGED Constructor : public AbstractMethod { + +}; + +class MANAGED AbstractMethodClass : public Class { + private: + Object* ORDER_BY_SIGNATURE_; + friend struct art::MethodClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethodClass); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_METHOD_H_ diff --git a/src/mirror/array-inl.h b/src/mirror/array-inl.h new file mode 100644 index 0000000000..b7f212f50f --- /dev/null +++ b/src/mirror/array-inl.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_ARRAY_INL_H_ +#define ART_SRC_MIRROR_ARRAY_INL_H_ + +#include "array.h" + +#include "class.h" + +namespace art { +namespace mirror { + +inline size_t Array::SizeOf() const { + // This is safe from overflow because the array was already allocated, so we know it's sane. + size_t component_size = GetClass()->GetComponentSize(); + int32_t component_count = GetLength(); + size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); + size_t data_size = component_count * component_size; + return header_size + data_size; +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_ARRAY_INL_H_ diff --git a/src/mirror/array.cc b/src/mirror/array.cc new file mode 100644 index 0000000000..103efa36b5 --- /dev/null +++ b/src/mirror/array.cc @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "array.h" + +#include "class.h" +#include "class-inl.h" +#include "gc/card_table-inl.h" +#include "object-inl.h" +#include "object_array.h" +#include "object_array-inl.h" +#include "object_utils.h" +#include "sirt_ref.h" +#include "thread.h" +#include "utils.h" + +namespace art { +namespace mirror { + +Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) { + DCHECK(array_class != NULL); + DCHECK_GE(component_count, 0); + DCHECK(array_class->IsArrayClass()); + + size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); + size_t data_size = component_count * component_size; + size_t size = header_size + data_size; + + // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. + size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size); + if (data_size >> component_shift != size_t(component_count) || size < data_size) { + self->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;", + "%s of length %d would overflow", + PrettyDescriptor(array_class).c_str(), component_count); + return NULL; + } + + Heap* heap = Runtime::Current()->GetHeap(); + Array* array = down_cast<Array*>(heap->AllocObject(self, array_class, size)); + if (array != NULL) { + DCHECK(array->IsArrayInstance()); + array->SetLength(component_count); + } + return array; +} + +Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) { + DCHECK(array_class->IsArrayClass()); + return Alloc(self, array_class, component_count, array_class->GetComponentSize()); +} + +// Create a multi-dimensional array of Objects or primitive types. +// +// We have to generate the names for X[], X[][], X[][][], and so on. The +// easiest way to deal with that is to create the full name once and then +// subtract pieces off. Besides, we want to start with the outermost +// piece and work our way in. +// Recursively create an array with multiple dimensions. Elements may be +// Objects or primitive types. +static Array* RecursiveCreateMultiArray(Thread* self, Class* array_class, int current_dimension, + IntArray* dimensions) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + int32_t array_length = dimensions->Get(current_dimension); + SirtRef<Array> new_array(self, Array::Alloc(self, array_class, array_length)); + if (UNLIKELY(new_array.get() == NULL)) { + CHECK(self->IsExceptionPending()); + return NULL; + } + if ((current_dimension + 1) < dimensions->GetLength()) { + // Create a new sub-array in every element of the array. + for (int32_t i = 0; i < array_length; i++) { + Array* sub_array = RecursiveCreateMultiArray(self, array_class->GetComponentType(), + current_dimension + 1, dimensions); + if (UNLIKELY(sub_array == NULL)) { + CHECK(self->IsExceptionPending()); + return NULL; + } + new_array->AsObjectArray<Array>()->Set(i, sub_array); + } + } + return new_array.get(); +} + +Array* Array::CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) { + // Verify dimensions. + // + // The caller is responsible for verifying that "dimArray" is non-null + // and has a length > 0 and <= 255. + int num_dimensions = dimensions->GetLength(); + DCHECK_GT(num_dimensions, 0); + DCHECK_LE(num_dimensions, 255); + + for (int i = 0; i < num_dimensions; i++) { + int dimension = dimensions->Get(i); + if (UNLIKELY(dimension < 0)) { + self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", + "Dimension %d: %d", i, dimension); + return NULL; + } + } + + // Generate the full name of the array class. + std::string descriptor(num_dimensions, '['); + descriptor += ClassHelper(element_class).GetDescriptor(); + + // Find/generate the array class. + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader()); + if (UNLIKELY(array_class == NULL)) { + CHECK(self->IsExceptionPending()); + return NULL; + } + // create the array + Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions); + if (UNLIKELY(new_array == NULL)) { + CHECK(self->IsExceptionPending()); + return NULL; + } + return new_array; +} + +bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const { + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", + "length=%i; index=%i", length_, index); + return false; +} + +bool Array::ThrowArrayStoreException(Object* object) const { + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", + "%s cannot be stored in an array of type %s", + PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str()); + return false; +} + +template<typename T> +PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { + DCHECK(array_class_ != NULL); + Array* raw_array = Array::Alloc(self, array_class_, length, sizeof(T)); + return down_cast<PrimitiveArray<T>*>(raw_array); +} + +template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL; + +// Explicitly instantiate all the primitive array types. +template class PrimitiveArray<uint8_t>; // BooleanArray +template class PrimitiveArray<int8_t>; // ByteArray +template class PrimitiveArray<uint16_t>; // CharArray +template class PrimitiveArray<double>; // DoubleArray +template class PrimitiveArray<float>; // FloatArray +template class PrimitiveArray<int32_t>; // IntArray +template class PrimitiveArray<int64_t>; // LongArray +template class PrimitiveArray<int16_t>; // ShortArray + +} // namespace mirror +} // namespace art diff --git a/src/mirror/array.h b/src/mirror/array.h new file mode 100644 index 0000000000..8da906faf9 --- /dev/null +++ b/src/mirror/array.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_ARRAY_H_ +#define ART_SRC_MIRROR_ARRAY_H_ + +#include "object.h" + +namespace art { +namespace mirror { + +class MANAGED Array : public Object { + public: + // A convenience for code that doesn't know the component size, + // and doesn't want to have to work it out itself. + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + size_t SizeOf() const; + + int32_t GetLength() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false); + } + + void SetLength(int32_t length) { + CHECK_GE(length, 0); + SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false); + } + + static MemberOffset LengthOffset() { + return OFFSET_OF_OBJECT_MEMBER(Array, length_); + } + + static MemberOffset DataOffset(size_t component_size) { + if (component_size != sizeof(int64_t)) { + return OFFSET_OF_OBJECT_MEMBER(Array, first_element_); + } else { + // Align longs and doubles. + return MemberOffset(OFFSETOF_MEMBER(Array, first_element_) + 4); + } + } + + void* GetRawData(size_t component_size) { + intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); + return reinterpret_cast<void*>(data); + } + + const void* GetRawData(size_t component_size) const { + intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); + return reinterpret_cast<const void*>(data); + } + + protected: + bool IsValidIndex(int32_t index) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (UNLIKELY(index < 0 || index >= GetLength())) { + return ThrowArrayIndexOutOfBoundsException(index); + } + return true; + } + + protected: + bool ThrowArrayIndexOutOfBoundsException(int32_t index) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool ThrowArrayStoreException(Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + private: + // The number of array elements. + int32_t length_; + // Marker for the data (used by generated code) + uint32_t first_element_[0]; + + DISALLOW_IMPLICIT_CONSTRUCTORS(Array); +}; + +template<class T> +class MANAGED PrimitiveArray : public Array { + public: + typedef T ElementType; + + static PrimitiveArray<T>* Alloc(Thread* self, size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + const T* GetData() const { + intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); + return reinterpret_cast<T*>(data); + } + + T* GetData() { + intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); + return reinterpret_cast<T*>(data); + } + + T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (!IsValidIndex(i)) { + return T(0); + } + return GetData()[i]; + } + + void Set(int32_t i, T value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (IsValidIndex(i)) { + GetData()[i] = value; + } + } + + static void SetArrayClass(Class* array_class) { + CHECK(array_class_ == NULL); + CHECK(array_class != NULL); + array_class_ = array_class; + } + + static void ResetArrayClass() { + CHECK(array_class_ != NULL); + array_class_ = NULL; + } + + private: + static Class* array_class_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_ARRAY_H_ diff --git a/src/mirror/class-inl.h b/src/mirror/class-inl.h new file mode 100644 index 0000000000..7eb8601cd6 --- /dev/null +++ b/src/mirror/class-inl.h @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_CLASS_INL_H_ +#define ART_SRC_MIRROR_CLASS_INL_H_ + +#include "class.h" + +#include "abstract_method.h" +#include "field.h" +#include "iftable.h" +#include "object_array.h" +#include "runtime.h" +#include "string.h" + +namespace art { +namespace mirror { + +inline size_t Class::GetObjectSize() const { + CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false); + CHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this); + return result; +} + +inline Class* Class::GetSuperClass() const { + // Can only get super class for loaded classes (hack for when runtime is + // initializing) + DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded(); + return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false); +} + +inline ObjectArray<AbstractMethod>* Class::GetDirectMethods() const { + DCHECK(IsLoaded() || IsErroneous()); + return GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false); +} + +inline void Class::SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false)); + DCHECK_NE(0, new_direct_methods->GetLength()); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), + new_direct_methods, false); +} + +inline AbstractMethod* Class::GetDirectMethod(int32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetDirectMethods()->Get(i); +} + +inline void Class::SetDirectMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ + ObjectArray<AbstractMethod>* direct_methods = + GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false); + direct_methods->Set(i, f); +} + +// Returns the number of static, private, and constructor methods. +inline size_t Class::NumDirectMethods() const { + return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0; +} + +inline ObjectArray<AbstractMethod>* Class::GetVirtualMethods() const { + DCHECK(IsLoaded() || IsErroneous()); + return GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false); +} + +inline void Class::SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) { + // TODO: we reassign virtual methods to grow the table for miranda + // methods.. they should really just be assigned once + DCHECK_NE(0, new_virtual_methods->GetLength()); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), + new_virtual_methods, false); +} + +inline size_t Class::NumVirtualMethods() const { + return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0; +} + +inline AbstractMethod* Class::GetVirtualMethod(uint32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(IsResolved() || IsErroneous()); + return GetVirtualMethods()->Get(i); +} + +inline AbstractMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(IsLoaded() || IsErroneous()); + return GetVirtualMethods()->Get(i); +} + +inline void Class::SetVirtualMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ObjectArray<AbstractMethod>* virtual_methods = + GetFieldObject<ObjectArray<AbstractMethod>*>( + OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false); + virtual_methods->Set(i, f); +} + +inline ObjectArray<AbstractMethod>* Class::GetVTable() const { + DCHECK(IsResolved() || IsErroneous()); + return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false); +} + +inline ObjectArray<AbstractMethod>* Class::GetVTableDuringLinking() const { + DCHECK(IsLoaded() || IsErroneous()); + return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false); +} + +inline void Class::SetVTable(ObjectArray<AbstractMethod>* new_vtable) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false); +} + +inline AbstractMethod* Class::FindVirtualMethodForVirtual(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(!method->GetDeclaringClass()->IsInterface()); + // The argument method may from a super class. + // Use the index to a potentially overridden one for this instance's class. + return GetVTable()->Get(method->GetMethodIndex()); +} + +inline AbstractMethod* Class::FindVirtualMethodForSuper(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(!method->GetDeclaringClass()->IsInterface()); + return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex()); +} + +inline AbstractMethod* Class::FindVirtualMethodForVirtualOrInterface(AbstractMethod* method) const { + if (method->IsDirect()) { + return method; + } + if (method->GetDeclaringClass()->IsInterface()) { + return FindVirtualMethodForInterface(method); + } + return FindVirtualMethodForVirtual(method); +} + +inline IfTable* Class::GetIfTable() const { + return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false); +} + +inline int32_t Class::GetIfTableCount() const { + IfTable* iftable = GetIfTable(); + if (iftable == NULL) { + return 0; + } + return iftable->Count(); +} + +inline void Class::SetIfTable(IfTable* new_iftable) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false); +} + +inline ObjectArray<Field>* Class::GetIFields() const { + DCHECK(IsLoaded() || IsErroneous()); + return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false); +} + +inline void Class::SetIFields(ObjectArray<Field>* new_ifields) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>( + OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false)); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false); +} + +inline ObjectArray<Field>* Class::GetSFields() const { + DCHECK(IsLoaded() || IsErroneous()); + return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false); +} + +inline void Class::SetSFields(ObjectArray<Field>* new_sfields) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>( + OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false)); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false); +} + +inline size_t Class::NumStaticFields() const { + return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0; +} + +inline Field* Class::GetStaticField(uint32_t i) const // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetSFields()->Get(i); +} + +inline void Class::SetStaticField(uint32_t i, Field* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ObjectArray<Field>* sfields= GetFieldObject<ObjectArray<Field>*>( + OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false); + sfields->Set(i, f); +} + +inline size_t Class::NumInstanceFields() const { + return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0; +} + +inline Field* Class::GetInstanceField(uint32_t i) const // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ + DCHECK_NE(NumInstanceFields(), 0U); + return GetIFields()->Get(i); +} + +inline void Class::SetInstanceField(uint32_t i, Field* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ + ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>( + OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false); + ifields->Set(i, f); +} + +inline void Class::SetVerifyErrorClass(Class* klass) { + CHECK(klass != NULL) << PrettyClass(this); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false); +} + +inline uint32_t Class::GetAccessFlags() const { + // Check class is loaded or this is java.lang.String that has a + // circularity issue during loading the names of its members + DCHECK(IsLoaded() || IsErroneous() || + this == String::GetJavaLangString() || + this == Field::GetJavaLangReflectField() || + this == AbstractMethod::GetConstructorClass() || + this == AbstractMethod::GetMethodClass()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); +} + +inline String* Class::GetName() const { + return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false); +} +inline void Class::SetName(String* name) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false); +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_CLASS_INL_H_ diff --git a/src/mirror/class.cc b/src/mirror/class.cc new file mode 100644 index 0000000000..7f52d17616 --- /dev/null +++ b/src/mirror/class.cc @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "class.h" + +#include "abstract_method-inl.h" +#include "class-inl.h" +#include "class_linker.h" +#include "class_loader.h" +#include "dex_cache.h" +#include "field-inl.h" +#include "gc/card_table-inl.h" +#include "object-inl.h" +#include "object_array-inl.h" +#include "object_utils.h" +#include "runtime.h" +#include "sirt_ref.h" +#include "thread.h" +#include "throwable.h" +#include "utils.h" +#include "well_known_classes.h" + +namespace art { +namespace mirror { + +Class* Class::java_lang_Class_ = NULL; + +void Class::SetClassClass(Class* java_lang_Class) { + CHECK(java_lang_Class_ == NULL) << java_lang_Class_ << " " << java_lang_Class; + CHECK(java_lang_Class != NULL); + java_lang_Class_ = java_lang_Class; +} + +void Class::ResetClass() { + CHECK(java_lang_Class_ != NULL); + java_lang_Class_ = NULL; +} + +void Class::SetStatus(Status new_status) { + CHECK(new_status > GetStatus() || new_status == kStatusError || !Runtime::Current()->IsStarted()) + << PrettyClass(this) << " " << GetStatus() << " -> " << new_status; + CHECK(sizeof(Status) == sizeof(uint32_t)) << PrettyClass(this); + if (new_status > kStatusResolved) { + CHECK_EQ(GetThinLockId(), Thread::Current()->GetThinLockId()) << PrettyClass(this); + } + if (new_status == kStatusError) { + CHECK_NE(GetStatus(), kStatusError) << PrettyClass(this); + + // stash current exception + Thread* self = Thread::Current(); + SirtRef<Throwable> exception(self, self->GetException()); + CHECK(exception.get() != NULL); + + // clear exception to call FindSystemClass + self->ClearException(); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Class* eiie_class = class_linker->FindSystemClass("Ljava/lang/ExceptionInInitializerError;"); + CHECK(!self->IsExceptionPending()); + + // only verification errors, not initialization problems, should set a verify error. + // this is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case. + Class* exception_class = exception->GetClass(); + if (!eiie_class->IsAssignableFrom(exception_class)) { + SetVerifyErrorClass(exception_class); + } + + // restore exception + self->SetException(exception.get()); + } + return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status, false); +} + +DexCache* Class::GetDexCache() const { + return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false); +} + +void Class::SetDexCache(DexCache* new_dex_cache) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false); +} + +Object* Class::AllocObject(Thread* self) { + DCHECK(!IsArrayClass()) << PrettyClass(this); + DCHECK(IsInstantiable()) << PrettyClass(this); + // TODO: decide whether we want this check. It currently fails during bootstrap. + // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); + DCHECK_GE(this->object_size_, sizeof(Object)); + return Runtime::Current()->GetHeap()->AllocObject(self, this, this->object_size_); +} + +void Class::SetClassSize(size_t new_class_size) { + DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this); + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false); +} + +// Return the class' name. The exact format is bizarre, but it's the specified behavior for +// Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int" +// but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than +// slashes (so "java.lang.String" but "[Ljava.lang.String;"). Madness. +String* Class::ComputeName() { + String* name = GetName(); + if (name != NULL) { + return name; + } + std::string descriptor(ClassHelper(this).GetDescriptor()); + if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { + // The descriptor indicates that this is the class for + // a primitive type; special-case the return value. + const char* c_name = NULL; + switch (descriptor[0]) { + case 'Z': c_name = "boolean"; break; + case 'B': c_name = "byte"; break; + case 'C': c_name = "char"; break; + case 'S': c_name = "short"; break; + case 'I': c_name = "int"; break; + case 'J': c_name = "long"; break; + case 'F': c_name = "float"; break; + case 'D': c_name = "double"; break; + case 'V': c_name = "void"; break; + default: + LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]); + } + name = String::AllocFromModifiedUtf8(Thread::Current(), c_name); + } else { + // Convert the UTF-8 name to a java.lang.String. The name must use '.' to separate package + // components. + if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') { + descriptor.erase(0, 1); + descriptor.erase(descriptor.size() - 1); + } + std::replace(descriptor.begin(), descriptor.end(), '/', '.'); + name = String::AllocFromModifiedUtf8(Thread::Current(), descriptor.c_str()); + } + SetName(name); + return name; +} + +void Class::DumpClass(std::ostream& os, int flags) const { + if ((flags & kDumpClassFullDetail) == 0) { + os << PrettyClass(this); + if ((flags & kDumpClassClassLoader) != 0) { + os << ' ' << GetClassLoader(); + } + if ((flags & kDumpClassInitialized) != 0) { + os << ' ' << GetStatus(); + } + os << "\n"; + return; + } + + Class* super = GetSuperClass(); + ClassHelper kh(this); + os << "----- " << (IsInterface() ? "interface" : "class") << " " + << "'" << kh.GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n", + os << " objectSize=" << SizeOf() << " " + << "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n", + os << StringPrintf(" access=0x%04x.%04x\n", + GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask); + if (super != NULL) { + os << " super='" << PrettyClass(super) << "' (cl=" << super->GetClassLoader() << ")\n"; + } + if (IsArrayClass()) { + os << " componentType=" << PrettyClass(GetComponentType()) << "\n"; + } + if (kh.NumDirectInterfaces() > 0) { + os << " interfaces (" << kh.NumDirectInterfaces() << "):\n"; + for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) { + Class* interface = kh.GetDirectInterface(i); + const ClassLoader* cl = interface->GetClassLoader(); + os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl); + } + } + os << " vtable (" << NumVirtualMethods() << " entries, " + << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n"; + for (size_t i = 0; i < NumVirtualMethods(); ++i) { + os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str()); + } + os << " direct methods (" << NumDirectMethods() << " entries):\n"; + for (size_t i = 0; i < NumDirectMethods(); ++i) { + os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetDirectMethod(i)).c_str()); + } + if (NumStaticFields() > 0) { + os << " static fields (" << NumStaticFields() << " entries):\n"; + if (IsResolved() || IsErroneous()) { + for (size_t i = 0; i < NumStaticFields(); ++i) { + os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetStaticField(i)).c_str()); + } + } else { + os << " <not yet available>"; + } + } + if (NumInstanceFields() > 0) { + os << " instance fields (" << NumInstanceFields() << " entries):\n"; + if (IsResolved() || IsErroneous()) { + for (size_t i = 0; i < NumInstanceFields(); ++i) { + os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetInstanceField(i)).c_str()); + } + } else { + os << " <not yet available>"; + } + } +} + +void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) { + if (new_reference_offsets != CLASS_WALK_SUPER) { + // Sanity check that the number of bits set in the reference offset bitmap + // agrees with the number of references + size_t count = 0; + for (Class* c = this; c != NULL; c = c->GetSuperClass()) { + count += c->NumReferenceInstanceFieldsDuringLinking(); + } + CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), count); + } + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), + new_reference_offsets, false); +} + +void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) { + if (new_reference_offsets != CLASS_WALK_SUPER) { + // Sanity check that the number of bits set in the reference offset bitmap + // agrees with the number of references + CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), + NumReferenceStaticFieldsDuringLinking()); + } + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), + new_reference_offsets, false); +} + +bool Class::Implements(const Class* klass) const { + DCHECK(klass != NULL); + DCHECK(klass->IsInterface()) << PrettyClass(this); + // All interfaces implemented directly and by our superclass, and + // recursively all super-interfaces of those interfaces, are listed + // in iftable_, so we can just do a linear scan through that. + int32_t iftable_count = GetIfTableCount(); + IfTable* iftable = GetIfTable(); + for (int32_t i = 0; i < iftable_count; i++) { + if (iftable->GetInterface(i) == klass) { + return true; + } + } + return false; +} + +// Determine whether "this" is assignable from "src", where both of these +// are array classes. +// +// Consider an array class, e.g. Y[][], where Y is a subclass of X. +// Y[][] = Y[][] --> true (identity) +// X[][] = Y[][] --> true (element superclass) +// Y = Y[][] --> false +// Y[] = Y[][] --> false +// Object = Y[][] --> true (everything is an object) +// Object[] = Y[][] --> true +// Object[][] = Y[][] --> true +// Object[][][] = Y[][] --> false (too many []s) +// Serializable = Y[][] --> true (all arrays are Serializable) +// Serializable[] = Y[][] --> true +// Serializable[][] = Y[][] --> false (unless Y is Serializable) +// +// Don't forget about primitive types. +// Object[] = int[] --> false +// +bool Class::IsArrayAssignableFromArray(const Class* src) const { + DCHECK(IsArrayClass()) << PrettyClass(this); + DCHECK(src->IsArrayClass()) << PrettyClass(src); + return GetComponentType()->IsAssignableFrom(src->GetComponentType()); +} + +bool Class::IsAssignableFromArray(const Class* src) const { + DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom + DCHECK(src->IsArrayClass()) << PrettyClass(src); + if (!IsArrayClass()) { + // If "this" is not also an array, it must be Object. + // src's super should be java_lang_Object, since it is an array. + Class* java_lang_Object = src->GetSuperClass(); + DCHECK(java_lang_Object != NULL) << PrettyClass(src); + DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src); + return this == java_lang_Object; + } + return IsArrayAssignableFromArray(src); +} + +bool Class::IsSubClass(const Class* klass) const { + DCHECK(!IsInterface()) << PrettyClass(this); + DCHECK(!IsArrayClass()) << PrettyClass(this); + const Class* current = this; + do { + if (current == klass) { + return true; + } + current = current->GetSuperClass(); + } while (current != NULL); + return false; +} + +bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) { + size_t i = 0; + while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) { + ++i; + } + if (descriptor1.find('/', i) != StringPiece::npos || + descriptor2.find('/', i) != StringPiece::npos) { + return false; + } else { + return true; + } +} + +bool Class::IsInSamePackage(const Class* that) const { + const Class* klass1 = this; + const Class* klass2 = that; + if (klass1 == klass2) { + return true; + } + // Class loaders must match. + if (klass1->GetClassLoader() != klass2->GetClassLoader()) { + return false; + } + // Arrays are in the same package when their element classes are. + while (klass1->IsArrayClass()) { + klass1 = klass1->GetComponentType(); + } + while (klass2->IsArrayClass()) { + klass2 = klass2->GetComponentType(); + } + // Compare the package part of the descriptor string. + ClassHelper kh(klass1); + std::string descriptor1(kh.GetDescriptor()); + kh.ChangeClass(klass2); + std::string descriptor2(kh.GetDescriptor()); + return IsInSamePackage(descriptor1, descriptor2); +} + +bool Class::IsClassClass() const { + Class* java_lang_Class = GetClass()->GetClass(); + return this == java_lang_Class; +} + +bool Class::IsStringClass() const { + return this == String::GetJavaLangString(); +} + +bool Class::IsThrowableClass() const { + return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this); +} + +bool Class::IsFieldClass() const { + Class* java_lang_Class = GetClass(); + Class* java_lang_reflect_Field = java_lang_Class->GetInstanceField(0)->GetClass(); + return this == java_lang_reflect_Field; + +} + +bool Class::IsMethodClass() const { + return (this == AbstractMethod::GetMethodClass()) || + (this == AbstractMethod::GetConstructorClass()); + +} + +ClassLoader* Class::GetClassLoader() const { + return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false); +} + +void Class::SetClassLoader(ClassLoader* new_class_loader) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false); +} + +AbstractMethod* Class::FindVirtualMethodForInterface(AbstractMethod* method) const { + Class* declaring_class = method->GetDeclaringClass(); + DCHECK(declaring_class != NULL) << PrettyClass(this); + DCHECK(declaring_class->IsInterface()) << PrettyMethod(method); + // TODO cache to improve lookup speed + int32_t iftable_count = GetIfTableCount(); + IfTable* iftable = GetIfTable(); + for (int32_t i = 0; i < iftable_count; i++) { + if (iftable->GetInterface(i) == declaring_class) { + return iftable->GetMethodArray(i)->Get(method->GetMethodIndex()); + } + } + return NULL; +} + +AbstractMethod* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature) const { + // Check the current class before checking the interfaces. + AbstractMethod* method = FindDeclaredVirtualMethod(name, signature); + if (method != NULL) { + return method; + } + + int32_t iftable_count = GetIfTableCount(); + IfTable* iftable = GetIfTable(); + for (int32_t i = 0; i < iftable_count; i++) { + method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature); + if (method != NULL) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { + // Check the current class before checking the interfaces. + AbstractMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx); + if (method != NULL) { + return method; + } + + int32_t iftable_count = GetIfTableCount(); + IfTable* iftable = GetIfTable(); + for (int32_t i = 0; i < iftable_count; i++) { + method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(dex_cache, dex_method_idx); + if (method != NULL) { + return method; + } + } + return NULL; +} + + +AbstractMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const { + MethodHelper mh; + for (size_t i = 0; i < NumDirectMethods(); ++i) { + AbstractMethod* method = GetDirectMethod(i); + mh.ChangeMethod(method); + if (name == mh.GetName() && signature == mh.GetSignature()) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { + if (GetDexCache() == dex_cache) { + for (size_t i = 0; i < NumDirectMethods(); ++i) { + AbstractMethod* method = GetDirectMethod(i); + if (method->GetDexMethodIndex() == dex_method_idx) { + return method; + } + } + } + return NULL; +} + +AbstractMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + AbstractMethod* method = klass->FindDeclaredDirectMethod(name, signature); + if (method != NULL) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + AbstractMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx); + if (method != NULL) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, + const StringPiece& signature) const { + MethodHelper mh; + for (size_t i = 0; i < NumVirtualMethods(); ++i) { + AbstractMethod* method = GetVirtualMethod(i); + mh.ChangeMethod(method); + if (name == mh.GetName() && signature == mh.GetSignature()) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { + if (GetDexCache() == dex_cache) { + for (size_t i = 0; i < NumVirtualMethods(); ++i) { + AbstractMethod* method = GetVirtualMethod(i); + if (method->GetDexMethodIndex() == dex_method_idx) { + return method; + } + } + } + return NULL; +} + +AbstractMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + AbstractMethod* method = klass->FindDeclaredVirtualMethod(name, signature); + if (method != NULL) { + return method; + } + } + return NULL; +} + +AbstractMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { + for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { + AbstractMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx); + if (method != NULL) { + return method; + } + } + return NULL; +} + +Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) { + // Is the field in this class? + // Interfaces are not relevant because they can't contain instance fields. + FieldHelper fh; + for (size_t i = 0; i < NumInstanceFields(); ++i) { + Field* f = GetInstanceField(i); + fh.ChangeField(f); + if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { + return f; + } + } + return NULL; +} + +Field* Class::FindDeclaredInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) { + if (GetDexCache() == dex_cache) { + for (size_t i = 0; i < NumInstanceFields(); ++i) { + Field* f = GetInstanceField(i); + if (f->GetDexFieldIndex() == dex_field_idx) { + return f; + } + } + } + return NULL; +} + +Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& type) { + // Is the field in this class, or any of its superclasses? + // Interfaces are not relevant because they can't contain instance fields. + for (Class* c = this; c != NULL; c = c->GetSuperClass()) { + Field* f = c->FindDeclaredInstanceField(name, type); + if (f != NULL) { + return f; + } + } + return NULL; +} + +Field* Class::FindInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) { + // Is the field in this class, or any of its superclasses? + // Interfaces are not relevant because they can't contain instance fields. + for (Class* c = this; c != NULL; c = c->GetSuperClass()) { + Field* f = c->FindDeclaredInstanceField(dex_cache, dex_field_idx); + if (f != NULL) { + return f; + } + } + return NULL; +} + +Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) { + DCHECK(type != NULL); + FieldHelper fh; + for (size_t i = 0; i < NumStaticFields(); ++i) { + Field* f = GetStaticField(i); + fh.ChangeField(f); + if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { + return f; + } + } + return NULL; +} + +Field* Class::FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) { + if (dex_cache == GetDexCache()) { + for (size_t i = 0; i < NumStaticFields(); ++i) { + Field* f = GetStaticField(i); + if (f->GetDexFieldIndex() == dex_field_idx) { + return f; + } + } + } + return NULL; +} + +Field* Class::FindStaticField(const StringPiece& name, const StringPiece& type) { + // Is the field in this class (or its interfaces), or any of its + // superclasses (or their interfaces)? + ClassHelper kh; + for (Class* k = this; k != NULL; k = k->GetSuperClass()) { + // Is the field in this class? + Field* f = k->FindDeclaredStaticField(name, type); + if (f != NULL) { + return f; + } + // Is this field in any of this class' interfaces? + kh.ChangeClass(k); + for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { + Class* interface = kh.GetDirectInterface(i); + f = interface->FindStaticField(name, type); + if (f != NULL) { + return f; + } + } + } + return NULL; +} + +Field* Class::FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) { + ClassHelper kh; + for (Class* k = this; k != NULL; k = k->GetSuperClass()) { + // Is the field in this class? + Field* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx); + if (f != NULL) { + return f; + } + // Is this field in any of this class' interfaces? + kh.ChangeClass(k); + for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { + Class* interface = kh.GetDirectInterface(i); + f = interface->FindStaticField(dex_cache, dex_field_idx); + if (f != NULL) { + return f; + } + } + } + return NULL; +} + +Field* Class::FindField(const StringPiece& name, const StringPiece& type) { + // Find a field using the JLS field resolution order + ClassHelper kh; + for (Class* k = this; k != NULL; k = k->GetSuperClass()) { + // Is the field in this class? + Field* f = k->FindDeclaredInstanceField(name, type); + if (f != NULL) { + return f; + } + f = k->FindDeclaredStaticField(name, type); + if (f != NULL) { + return f; + } + // Is this field in any of this class' interfaces? + kh.ChangeClass(k); + for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { + Class* interface = kh.GetDirectInterface(i); + f = interface->FindStaticField(name, type); + if (f != NULL) { + return f; + } + } + } + return NULL; +} + +} // namespace mirror +} // namespace art diff --git a/src/mirror/class.h b/src/mirror/class.h new file mode 100644 index 0000000000..843e07cb37 --- /dev/null +++ b/src/mirror/class.h @@ -0,0 +1,866 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_CLASS_H_ +#define ART_SRC_MIRROR_CLASS_H_ + +#include "modifiers.h" +#include "object.h" +#include "primitive.h" + +/* + * A magic value for refOffsets. Ignore the bits and walk the super + * chain when this is the value. + * [This is an unlikely "natural" value, since it would be 30 non-ref instance + * fields followed by 2 ref instance fields.] + */ +#define CLASS_WALK_SUPER ((unsigned int)(3)) +#define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8) +#define CLASS_OFFSET_ALIGNMENT 4 +#define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1)) +/* + * Given an offset, return the bit number which would encode that offset. + * Local use only. + */ +#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \ + ((unsigned int)(byteOffset) / \ + CLASS_OFFSET_ALIGNMENT) +/* + * Is the given offset too large to be encoded? + */ +#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \ + (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD) +/* + * Return a single bit, encoding the offset. + * Undefined if the offset is too large, as defined above. + */ +#define CLASS_BIT_FROM_OFFSET(byteOffset) \ + (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset)) +/* + * Return an offset, given a bit number as returned from CLZ. + */ +#define CLASS_OFFSET_FROM_CLZ(rshift) \ + MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT)) + +namespace art { + +struct ClassClassOffsets; +struct ClassOffsets; +class StringPiece; + +namespace mirror { + +class ClassLoader; +class DexCache; +class Field; +class IfTable; + +// Type for the InitializedStaticStorage table. Currently the Class +// provides the static storage. However, this might change to an Array +// to improve image sharing, so we use this type to avoid assumptions +// on the current storage. +class MANAGED StaticStorageBase : public Object { +}; + +// C++ mirror of java.lang.Class +class MANAGED Class : public StaticStorageBase { + public: + // Class Status + // + // kStatusNotReady: If a Class cannot be found in the class table by + // FindClass, it allocates an new one with AllocClass in the + // kStatusNotReady and calls LoadClass. Note if it does find a + // class, it may not be kStatusResolved and it will try to push it + // forward toward kStatusResolved. + // + // kStatusIdx: LoadClass populates with Class with information from + // the DexFile, moving the status to kStatusIdx, indicating that the + // Class value in super_class_ has not been populated. The new Class + // can then be inserted into the classes table. + // + // kStatusLoaded: After taking a lock on Class, the ClassLinker will + // attempt to move a kStatusIdx class forward to kStatusLoaded by + // using ResolveClass to initialize the super_class_ and ensuring the + // interfaces are resolved. + // + // kStatusResolved: Still holding the lock on Class, the ClassLinker + // shows linking is complete and fields of the Class populated by making + // it kStatusResolved. Java allows circularities of the form where a super + // class has a field that is of the type of the sub class. We need to be able + // to fully resolve super classes while resolving types for fields. + // + // kStatusRetryVerificationAtRuntime: The verifier sets a class to + // this state if it encounters a soft failure at compile time. This + // often happens when there are unresolved classes in other dex + // files, and this status marks a class as needing to be verified + // again at runtime. + // + // TODO: Explain the other states + enum Status { + kStatusError = -1, + kStatusNotReady = 0, + kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_. + kStatusLoaded = 2, // DEX idx values resolved. + kStatusResolved = 3, // Part of linking. + kStatusVerifying = 4, // In the process of being verified. + kStatusRetryVerificationAtRuntime = 5, // Compile time verification failed, retry at runtime. + kStatusVerifyingAtRuntime = 6, // Retrying verification at runtime. + kStatusVerified = 7, // Logically part of linking; done pre-init. + kStatusInitializing = 8, // Class init in progress. + kStatusInitialized = 9, // Ready to go. + }; + + Status GetStatus() const { + DCHECK_EQ(sizeof(Status), sizeof(uint32_t)); + return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false)); + } + + void SetStatus(Status new_status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Returns true if the class has failed to link. + bool IsErroneous() const { + return GetStatus() == kStatusError; + } + + // Returns true if the class has been loaded. + bool IsIdxLoaded() const { + return GetStatus() >= kStatusIdx; + } + + // Returns true if the class has been loaded. + bool IsLoaded() const { + return GetStatus() >= kStatusLoaded; + } + + // Returns true if the class has been linked. + bool IsResolved() const { + return GetStatus() >= kStatusResolved; + } + + // Returns true if the class was compile-time verified. + bool IsCompileTimeVerified() const { + return GetStatus() >= kStatusRetryVerificationAtRuntime; + } + + // Returns true if the class has been verified. + bool IsVerified() const { + return GetStatus() >= kStatusVerified; + } + + // Returns true if the class is initializing. + bool IsInitializing() const { + return GetStatus() >= kStatusInitializing; + } + + // Returns true if the class is initialized. + bool IsInitialized() const { + return GetStatus() == kStatusInitialized; + } + + uint32_t GetAccessFlags() const; + + void SetAccessFlags(uint32_t new_access_flags) { + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags, false); + } + + // Returns true if the class is an interface. + bool IsInterface() const { + return (GetAccessFlags() & kAccInterface) != 0; + } + + // Returns true if the class is declared public. + bool IsPublic() const { + return (GetAccessFlags() & kAccPublic) != 0; + } + + // Returns true if the class is declared final. + bool IsFinal() const { + return (GetAccessFlags() & kAccFinal) != 0; + } + + bool IsFinalizable() const { + return (GetAccessFlags() & kAccClassIsFinalizable) != 0; + } + + void SetFinalizable() { + uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); + SetAccessFlags(flags | kAccClassIsFinalizable); + } + + // Returns true if the class is abstract. + bool IsAbstract() const { + return (GetAccessFlags() & kAccAbstract) != 0; + } + + // Returns true if the class is an annotation. + bool IsAnnotation() const { + return (GetAccessFlags() & kAccAnnotation) != 0; + } + + // Returns true if the class is synthetic. + bool IsSynthetic() const { + return (GetAccessFlags() & kAccSynthetic) != 0; + } + + bool IsReferenceClass() const { + return (GetAccessFlags() & kAccClassIsReference) != 0; + } + + bool IsWeakReferenceClass() const { + return (GetAccessFlags() & kAccClassIsWeakReference) != 0; + } + + bool IsSoftReferenceClass() const { + return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference; + } + + bool IsFinalizerReferenceClass() const { + return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0; + } + + bool IsPhantomReferenceClass() const { + return (GetAccessFlags() & kAccClassIsPhantomReference) != 0; + } + + + String* GetName() const; // Returns the cached name. + void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name. + // Computes the name, then sets the cached value. + String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsProxyClass() const { + // Read access flags without using getter as whether something is a proxy can be check in + // any loaded state + // TODO: switch to a check if the super class is java.lang.reflect.Proxy? + uint32_t access_flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); + return (access_flags & kAccClassIsProxy) != 0; + } + + Primitive::Type GetPrimitiveType() const { + DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t)); + return static_cast<Primitive::Type>( + GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false)); + } + + void SetPrimitiveType(Primitive::Type new_type) { + DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t)); + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false); + } + + // Returns true if the class is a primitive type. + bool IsPrimitive() const { + return GetPrimitiveType() != Primitive::kPrimNot; + } + + bool IsPrimitiveBoolean() const { + return GetPrimitiveType() == Primitive::kPrimBoolean; + } + + bool IsPrimitiveByte() const { + return GetPrimitiveType() == Primitive::kPrimByte; + } + + bool IsPrimitiveChar() const { + return GetPrimitiveType() == Primitive::kPrimChar; + } + + bool IsPrimitiveShort() const { + return GetPrimitiveType() == Primitive::kPrimShort; + } + + bool IsPrimitiveInt() const { + return GetPrimitiveType() == Primitive::kPrimInt; + } + + bool IsPrimitiveLong() const { + return GetPrimitiveType() == Primitive::kPrimLong; + } + + bool IsPrimitiveFloat() const { + return GetPrimitiveType() == Primitive::kPrimFloat; + } + + bool IsPrimitiveDouble() const { + return GetPrimitiveType() == Primitive::kPrimDouble; + } + + bool IsPrimitiveVoid() const { + return GetPrimitiveType() == Primitive::kPrimVoid; + } + + bool IsPrimitiveArray() const { + return IsArrayClass() && GetComponentType()->IsPrimitive(); + } + + // Depth of class from java.lang.Object + size_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + size_t depth = 0; + for (Class* klass = this; klass->GetSuperClass() != NULL; klass = klass->GetSuperClass()) { + depth++; + } + return depth; + } + + bool IsArrayClass() const { + return GetComponentType() != NULL; + } + + bool IsClassClass() const; + + bool IsStringClass() const; + + bool IsThrowableClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsMethodClass() const; + + Class* GetComponentType() const { + return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false); + } + + void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(GetComponentType() == NULL); + DCHECK(new_component_type != NULL); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), new_component_type, false); + } + + size_t GetComponentSize() const { + return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType()); + } + + bool IsObjectClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return !IsPrimitive() && GetSuperClass() == NULL; + } + bool IsInstantiable() const { + return !IsPrimitive() && !IsInterface() && !IsAbstract(); + } + + bool IsObjectArrayClass() const { + return GetComponentType() != NULL && !GetComponentType()->IsPrimitive(); + } + + // Creates a raw object instance but does not invoke the default constructor. + Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsVariableSize() const { + // Classes and arrays vary in size, and so the object_size_ field cannot + // be used to get their instance size + return IsClassClass() || IsArrayClass(); + } + + size_t SizeOf() const { + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false); + } + + size_t GetClassSize() const { + DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false); + } + + void SetClassSize(size_t new_class_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + size_t GetObjectSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetObjectSize(size_t new_object_size) { + DCHECK(!IsVariableSize()); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size, false); + } + + // Returns true if this class is in the same packages as that class. + bool IsInSamePackage(const Class* that) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2); + + // Returns true if this class can access that class. + bool CanAccess(Class* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return that->IsPublic() || this->IsInSamePackage(that); + } + + // Can this class access a member in the provided class with the provided member access flags? + // Note that access to the class isn't checked in case the declaring class is protected and the + // method has been exposed by a public sub-class + bool CanAccessMember(Class* access_to, uint32_t member_flags) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // Classes can access all of their own members + if (this == access_to) { + return true; + } + // Public members are trivially accessible + if (member_flags & kAccPublic) { + return true; + } + // Private members are trivially not accessible + if (member_flags & kAccPrivate) { + return false; + } + // Check for protected access from a sub-class, which may or may not be in the same package. + if (member_flags & kAccProtected) { + if (this->IsSubClass(access_to)) { + return true; + } + } + // Allow protected access from other classes in the same package. + return this->IsInSamePackage(access_to); + } + + bool IsSubClass(const Class* klass) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Can src be assigned to this class? For example, String can be assigned to Object (by an + // upcast), however, an Object cannot be assigned to a String as a potentially exception throwing + // downcast would be necessary. Similarly for interfaces, a class that implements (or an interface + // that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign + // to themselves. Classes for primitive types may not assign to each other. + bool IsAssignableFrom(const Class* src) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(src != NULL); + if (this == src) { + // Can always assign to things of the same type. + return true; + } else if (IsObjectClass()) { + // Can assign any reference to java.lang.Object. + return !src->IsPrimitive(); + } else if (IsInterface()) { + return src->Implements(this); + } else if (src->IsArrayClass()) { + return IsAssignableFromArray(src); + } else { + return !src->IsInterface() && src->IsSubClass(this); + } + } + + Class* GetSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // super class is assigned once, except during class linker initialization + Class* old_super_class = GetFieldObject<Class*>( + OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false); + DCHECK(old_super_class == NULL || old_super_class == new_super_class); + DCHECK(new_super_class != NULL); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class, false); + } + + bool HasSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetSuperClass() != NULL; + } + + static MemberOffset SuperClassOffset() { + return MemberOffset(OFFSETOF_MEMBER(Class, super_class_)); + } + + ClassLoader* GetClassLoader() const; + + void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static MemberOffset DexCacheOffset() { + return MemberOffset(OFFSETOF_MEMBER(Class, dex_cache_)); + } + + enum { + kDumpClassFullDetail = 1, + kDumpClassClassLoader = (1 << 1), + kDumpClassInitialized = (1 << 2), + }; + + void DumpClass(std::ostream& os, int flags) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + DexCache* GetDexCache() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<AbstractMethod>* GetDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* GetDirectMethod(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetDirectMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Returns the number of static, private, and constructor methods. + size_t NumDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<AbstractMethod>* GetVirtualMethods() const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Returns the number of non-inherited virtual methods. + size_t NumVirtualMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* GetVirtualMethod(uint32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* GetVirtualMethodDuringLinking(uint32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetVirtualMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<AbstractMethod>* GetVTable() const; + + ObjectArray<AbstractMethod>* GetVTableDuringLinking() const; + + void SetVTable(ObjectArray<AbstractMethod>* new_vtable) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static MemberOffset VTableOffset() { + return OFFSET_OF_OBJECT_MEMBER(Class, vtable_); + } + + // Given a method implemented by this class but potentially from a super class, return the + // specific implementation method for this class. + AbstractMethod* FindVirtualMethodForVirtual(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Given a method implemented by this class' super class, return the specific implementation + // method for this class. + AbstractMethod* FindVirtualMethodForSuper(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Given a method implemented by this class, but potentially from a + // super class or interface, return the specific implementation + // method for this class. + AbstractMethod* FindVirtualMethodForInterface(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindVirtualMethodForVirtualOrInterface(AbstractMethod* method) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + AbstractMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int32_t GetIfTableCount() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + IfTable* GetIfTable() const; + + void SetIfTable(IfTable* new_iftable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Get instance fields of the class (See also GetSFields). + ObjectArray<Field>* GetIFields() const; + + void SetIFields(ObjectArray<Field>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + size_t NumInstanceFields() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* GetInstanceField(uint32_t i) const // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetInstanceField(uint32_t i, Field* f) // TODO: uint16_t + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Returns the number of instance fields containing reference types. + size_t NumReferenceInstanceFields() const { + DCHECK(IsResolved() || IsErroneous()); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false); + } + + size_t NumReferenceInstanceFieldsDuringLinking() const { + DCHECK(IsLoaded() || IsErroneous()); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false); + } + + void SetNumReferenceInstanceFields(size_t new_num) { + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num, false); + } + + uint32_t GetReferenceInstanceOffsets() const { + DCHECK(IsResolved() || IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false); + } + + void SetReferenceInstanceOffsets(uint32_t new_reference_offsets) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Beginning of static field data + static MemberOffset FieldsOffset() { + return OFFSET_OF_OBJECT_MEMBER(Class, fields_); + } + + // Returns the number of static fields containing reference types. + size_t NumReferenceStaticFields() const { + DCHECK(IsResolved() || IsErroneous()); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false); + } + + size_t NumReferenceStaticFieldsDuringLinking() const { + DCHECK(IsLoaded() || IsErroneous()); + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false); + } + + void SetNumReferenceStaticFields(size_t new_num) { + DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num, false); + } + + // Gets the static fields of the class. + ObjectArray<Field>* GetSFields() const; + + void SetSFields(ObjectArray<Field>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + size_t NumStaticFields() const; + + Field* GetStaticField(uint32_t i) const; // TODO: uint16_t + + void SetStaticField(uint32_t i, Field* f); // TODO: uint16_t + + uint32_t GetReferenceStaticOffsets() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false); + } + + void SetReferenceStaticOffsets(uint32_t new_reference_offsets); + + // Find a static or instance field using the JLS resolution order + Field* FindField(const StringPiece& name, const StringPiece& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Finds the given instance field in this class or a superclass. + Field* FindInstanceField(const StringPiece& name, const StringPiece& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Finds the given instance field in this class or a superclass, only searches classes that + // have the same dex cache. + Field* FindInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* FindDeclaredInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Finds the given static field in this class or a superclass. + Field* FindStaticField(const StringPiece& name, const StringPiece& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Finds the given static field in this class or superclass, only searches classes that + // have the same dex cache. + Field* FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + pid_t GetClinitThreadId() const { + DCHECK(IsIdxLoaded() || IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false); + } + + void SetClinitThreadId(pid_t new_clinit_thread_id) { + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id, false); + } + + Class* GetVerifyErrorClass() const { + // DCHECK(IsErroneous()); + return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false); + } + + uint16_t GetDexTypeIndex() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false); + } + + void SetDexTypeIndex(uint16_t type_idx) { + SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false); + } + + static Class* GetJavaLangClass() { + DCHECK(java_lang_Class_ != NULL); + return java_lang_Class_; + } + + // Can't call this SetClass or else gets called instead of Object::SetClass in places. + static void SetClassClass(Class* java_lang_Class); + static void ResetClass(); + + private: + void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool Implements(const Class* klass) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsArrayAssignableFromArray(const Class* klass) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsAssignableFromArray(const Class* klass) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // defining class loader, or NULL for the "bootstrap" system loader + ClassLoader* class_loader_; + + // For array classes, the component class object for instanceof/checkcast + // (for String[][][], this will be String[][]). NULL for non-array classes. + Class* component_type_; + + // DexCache of resolved constant pool entries (will be NULL for classes generated by the + // runtime such as arrays and primitive classes). + DexCache* dex_cache_; + + // static, private, and <init> methods + ObjectArray<AbstractMethod>* direct_methods_; + + // instance fields + // + // These describe the layout of the contents of an Object. + // Note that only the fields directly declared by this class are + // listed in ifields; fields declared by a superclass are listed in + // the superclass's Class.ifields. + // + // All instance fields that refer to objects are guaranteed to be at + // the beginning of the field list. num_reference_instance_fields_ + // specifies the number of reference fields. + ObjectArray<Field>* ifields_; + + // The interface table (iftable_) contains pairs of a interface class and an array of the + // interface methods. There is one pair per interface supported by this class. That means one + // pair for each interface we support directly, indirectly via superclass, or indirectly via a + // superinterface. This will be null if neither we nor our superclass implement any interfaces. + // + // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()". + // Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a + // single vtable. + // + // For every interface a concrete class implements, we create an array of the concrete vtable_ + // methods for the methods in the interface. + IfTable* iftable_; + + // descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName + String* name_; + + // Static fields + ObjectArray<Field>* sfields_; + + // The superclass, or NULL if this is java.lang.Object, an interface or primitive type. + Class* super_class_; + + // If class verify fails, we must return same error on subsequent tries. + Class* verify_error_class_; + + // virtual methods defined in this class; invoked through vtable + ObjectArray<AbstractMethod>* virtual_methods_; + + // Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is + // copied in, and virtual methods from our class either replace those from the super or are + // appended. For abstract classes, methods may be created in the vtable that aren't in + // virtual_ methods_ for miranda methods. + ObjectArray<AbstractMethod>* vtable_; + + // access flags; low 16 bits are defined by VM spec + uint32_t access_flags_; + + // Total size of the Class instance; used when allocating storage on gc heap. + // See also object_size_. + size_t class_size_; + + // tid used to check for recursive <clinit> invocation + pid_t clinit_thread_id_; + + // type index from dex file + // TODO: really 16bits + uint32_t dex_type_idx_; + + // number of instance fields that are object refs + size_t num_reference_instance_fields_; + + // number of static fields that are object refs + size_t num_reference_static_fields_; + + // Total object size; used when allocating storage on gc heap. + // (For interfaces and abstract classes this will be zero.) + // See also class_size_. + size_t object_size_; + + // primitive type value, or Primitive::kPrimNot (0); set for generated prim classes + Primitive::Type primitive_type_; + + // Bitmap of offsets of ifields. + uint32_t reference_instance_offsets_; + + // Bitmap of offsets of sfields. + uint32_t reference_static_offsets_; + + // state of class initialization + Status status_; + + // TODO: ? + // initiating class loader list + // NOTE: for classes with low serialNumber, these are unused, and the + // values are kept in a table in gDvm. + // InitiatingLoaderList initiating_loader_list_; + + // Location of first static field. + uint32_t fields_[0]; + + // java.lang.Class + static Class* java_lang_Class_; + + friend struct art::ClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(Class); +}; + +std::ostream& operator<<(std::ostream& os, const Class::Status& rhs); + +class MANAGED ClassClass : public Class { + private: + int32_t padding_; + int64_t serialVersionUID_; + friend struct art::ClassClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(ClassClass); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_CLASS_H_ diff --git a/src/class_loader.h b/src/mirror/class_loader.h index 029c4a20ca..0d635f1d21 100644 --- a/src/class_loader.h +++ b/src/mirror/class_loader.h @@ -20,10 +20,14 @@ #include <vector> #include "dex_file.h" -#include "object.h" +#include "mirror/object.h" namespace art { +struct ClassLoaderOffsets; + +namespace mirror { + // C++ mirror of java.lang.ClassLoader class MANAGED ClassLoader : public Object { private: @@ -32,10 +36,11 @@ class MANAGED ClassLoader : public Object { ClassLoader* parent_; Object* proxyCache_; - friend struct ClassLoaderOffsets; // for verifying offset information + friend struct art::ClassLoaderOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader); }; +} // namespace mirror } // namespace art #endif // ART_SRC_CLASS_LOADER_H_ diff --git a/src/dex_cache.cc b/src/mirror/dex_cache.cc index 98fc93254a..3009786baa 100644 --- a/src/dex_cache.cc +++ b/src/mirror/dex_cache.cc @@ -14,14 +14,22 @@ * limitations under the License. */ +#include "dex_cache.h" + +#include "abstract_method-inl.h" #include "base/logging.h" #include "class_linker.h" -#include "dex_cache.h" #include "heap.h" +#include "gc/card_table-inl.h" #include "globals.h" #include "object.h" +#include "object-inl.h" +#include "object_array-inl.h" +#include "runtime.h" +#include "string.h" namespace art { +namespace mirror { void DexCache::Init(const DexFile* dex_file, String* location, @@ -70,4 +78,17 @@ void DexCache::Fixup(AbstractMethod* trampoline) { } } +AbstractMethod* DexCache::GetResolvedMethod(uint32_t method_idx) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + AbstractMethod* method = GetResolvedMethods()->Get(method_idx); + // Hide resolution trampoline methods from the caller + if (method != NULL && method->IsRuntimeMethod()) { + DCHECK(method == Runtime::Current()->GetResolutionMethod()); + return NULL; + } else { + return method; + } +} + +} // namespace mirror } // namespace art diff --git a/src/dex_cache.h b/src/mirror/dex_cache.h index ee44856a4d..307588b581 100644 --- a/src/dex_cache.h +++ b/src/mirror/dex_cache.h @@ -14,23 +14,27 @@ * limitations under the License. */ -#ifndef ART_SRC_DEX_CACHE_H_ -#define ART_SRC_DEX_CACHE_H_ +#ifndef ART_SRC_MIRROR_DEX_CACHE_H_ +#define ART_SRC_MIRROR_DEX_CACHE_H_ -#include "base/macros.h" -#include "dex_file.h" -#include "globals.h" +#include "abstract_method.h" +#include "class.h" #include "object.h" +#include "object_array.h" +#include "string.h" namespace art { -class Class; -class Field; +struct DexCacheOffsets; +class DexFile; class ImageWriter; -class AbstractMethod; -class String; union JValue; +namespace mirror { + +class Class; +class Field; + class MANAGED DexCacheClass : public Class { private: DISALLOW_IMPLICIT_CONSTRUCTORS(DexCacheClass); @@ -107,16 +111,7 @@ class MANAGED DexCache : public Object { } AbstractMethod* GetResolvedMethod(uint32_t method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method = GetResolvedMethods()->Get(method_idx); - // Hide resolution trampoline methods from the caller - if (method != NULL && method->GetDexMethodIndex() == DexFile::kDexNoIndex16) { - DCHECK(method == Runtime::Current()->GetResolutionMethod()); - return NULL; - } else { - return method; - } - } + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void SetResolvedMethod(uint32_t method_idx, AbstractMethod* resolved) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -177,10 +172,11 @@ class MANAGED DexCache : public Object { ObjectArray<String>* strings_; uint32_t dex_file_; - friend struct DexCacheOffsets; // for verifying offset information + friend struct art::DexCacheOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache); }; +} // namespace mirror } // namespace art -#endif // ART_SRC_DEX_CACHE_H_ +#endif // ART_SRC_MIRROR_DEX_CACHE_H_ diff --git a/src/dex_cache_test.cc b/src/mirror/dex_cache_test.cc index b131e4c248..98176602a1 100644 --- a/src/dex_cache_test.cc +++ b/src/mirror/dex_cache_test.cc @@ -18,12 +18,13 @@ #include "common_test.h" #include "dex_cache.h" #include "heap.h" -#include "object.h" +#include "mirror/object_array-inl.h" #include "sirt_ref.h" #include <stdio.h> namespace art { +namespace mirror { class DexCacheTest : public CommonTest {}; @@ -57,4 +58,5 @@ TEST_F(DexCacheTest, Open) { static_cast<uint32_t>(dex_cache->GetInitializedStaticStorage()->GetLength())); } +} // namespace mirror } // namespace art diff --git a/src/mirror/field-inl.h b/src/mirror/field-inl.h new file mode 100644 index 0000000000..b73cf19214 --- /dev/null +++ b/src/mirror/field-inl.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_FIELD_INL_H_ +#define ART_SRC_MIRROR_FIELD_INL_H_ + +#include "field.h" + +namespace art { +namespace mirror { + +inline Class* Field::GetDeclaringClass() const { + Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false); + DCHECK(result != NULL); + DCHECK(result->IsLoaded() || result->IsErroneous()); + return result; +} + +inline void Field::SetDeclaringClass(Class *new_declaring_class) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), new_declaring_class, false); +} + +inline uint32_t Field::GetAccessFlags() const { + DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); + return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false); +} + +inline MemberOffset Field::GetOffset() const { + DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); + return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false)); +} + +inline MemberOffset Field::GetOffsetDuringLinking() const { + DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); + return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false)); +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_FIELD_INL_H_ diff --git a/src/mirror/field.cc b/src/mirror/field.cc new file mode 100644 index 0000000000..dab7868ae6 --- /dev/null +++ b/src/mirror/field.cc @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "field.h" + +#include "field-inl.h" +#include "gc/card_table-inl.h" +#include "object-inl.h" +#include "object_utils.h" +#include "runtime.h" +#include "utils.h" + +namespace art { +namespace mirror { + +// TODO: get global references for these +Class* Field::java_lang_reflect_Field_ = NULL; + +void Field::SetClass(Class* java_lang_reflect_Field) { + CHECK(java_lang_reflect_Field_ == NULL); + CHECK(java_lang_reflect_Field != NULL); + java_lang_reflect_Field_ = java_lang_reflect_Field; +} + +void Field::ResetClass() { + CHECK(java_lang_reflect_Field_ != NULL); + java_lang_reflect_Field_ = NULL; +} + +void Field::SetOffset(MemberOffset num_bytes) { + DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); +#if 0 // TODO enable later in boot and under !NDEBUG + FieldHelper fh(this); + Primitive::Type type = fh.GetTypeAsPrimitiveType(); + if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) { + DCHECK_ALIGNED(num_bytes.Uint32Value(), 8); + } +#endif + SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false); +} + +uint32_t Field::Get32(const Object* object) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + return object->GetField32(GetOffset(), IsVolatile()); +} + +void Field::Set32(Object* object, uint32_t new_value) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + object->SetField32(GetOffset(), new_value, IsVolatile()); +} + +uint64_t Field::Get64(const Object* object) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + return object->GetField64(GetOffset(), IsVolatile()); +} + +void Field::Set64(Object* object, uint64_t new_value) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + object->SetField64(GetOffset(), new_value, IsVolatile()); +} + +Object* Field::GetObj(const Object* object) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + return object->GetFieldObject<Object*>(GetOffset(), IsVolatile()); +} + +void Field::SetObj(Object* object, const Object* new_value) const { + DCHECK(object != NULL) << PrettyField(this); + DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); + object->SetFieldObject(GetOffset(), new_value, IsVolatile()); +} + +bool Field::GetBoolean(const Object* object) const { + DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + return Get32(object); +} + +void Field::SetBoolean(Object* object, bool z) const { + DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Set32(object, z); +} + +int8_t Field::GetByte(const Object* object) const { + DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + return Get32(object); +} + +void Field::SetByte(Object* object, int8_t b) const { + DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Set32(object, b); +} + +uint16_t Field::GetChar(const Object* object) const { + DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + return Get32(object); +} + +void Field::SetChar(Object* object, uint16_t c) const { + DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Set32(object, c); +} + +int16_t Field::GetShort(const Object* object) const { + DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + return Get32(object); +} + +void Field::SetShort(Object* object, int16_t s) const { + DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Set32(object, s); +} + +int32_t Field::GetInt(const Object* object) const { +#ifndef NDEBUG + Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); + CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); +#endif + return Get32(object); +} + +void Field::SetInt(Object* object, int32_t i) const { +#ifndef NDEBUG + Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); + CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); +#endif + Set32(object, i); +} + +int64_t Field::GetLong(const Object* object) const { +#ifndef NDEBUG + Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); + CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); +#endif + return Get64(object); +} + +void Field::SetLong(Object* object, int64_t j) const { +#ifndef NDEBUG + Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); + CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); +#endif + Set64(object, j); +} + +union Bits { + jdouble d; + jfloat f; + jint i; + jlong j; +}; + +float Field::GetFloat(const Object* object) const { + DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Bits bits; + bits.i = Get32(object); + return bits.f; +} + +void Field::SetFloat(Object* object, float f) const { + DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Bits bits; + bits.f = f; + Set32(object, bits.i); +} + +double Field::GetDouble(const Object* object) const { + DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Bits bits; + bits.j = Get64(object); + return bits.d; +} + +void Field::SetDouble(Object* object, double d) const { + DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + Bits bits; + bits.d = d; + Set64(object, bits.j); +} + +Object* Field::GetObject(const Object* object) const { + DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + return GetObj(object); +} + +void Field::SetObject(Object* object, const Object* l) const { + DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType()) + << PrettyField(this); + SetObj(object, l); +} + +} // namespace mirror +} // namespace art diff --git a/src/mirror/field.h b/src/mirror/field.h new file mode 100644 index 0000000000..4e7abe8550 --- /dev/null +++ b/src/mirror/field.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_FIELD_H_ +#define ART_SRC_MIRROR_FIELD_H_ + +#include "class.h" +#include "modifiers.h" +#include "object.h" + +namespace art { + +struct FieldClassOffsets; +struct FieldOffsets; + +namespace mirror { + +// C++ mirror of java.lang.reflect.Field +class MANAGED Field : public Object { + public: + Class* GetDeclaringClass() const; + + void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + uint32_t GetAccessFlags() const; + + void SetAccessFlags(uint32_t new_access_flags) { + SetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), new_access_flags, false); + } + + bool IsPublic() const { + return (GetAccessFlags() & kAccPublic) != 0; + } + + bool IsStatic() const { + return (GetAccessFlags() & kAccStatic) != 0; + } + + bool IsFinal() const { + return (GetAccessFlags() & kAccFinal) != 0; + } + + uint32_t GetDexFieldIndex() const { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), false); + } + + void SetDexFieldIndex(uint32_t new_idx) { + SetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), new_idx, false); + } + + // Offset to field within an Object + MemberOffset GetOffset() const; + + static MemberOffset OffsetOffset() { + return MemberOffset(OFFSETOF_MEMBER(Field, offset_)); + } + + MemberOffset GetOffsetDuringLinking() const; + + void SetOffset(MemberOffset num_bytes); + + // field access, null object for static fields + bool GetBoolean(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetBoolean(Object* object, bool z) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int8_t GetByte(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetByte(Object* object, int8_t b) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint16_t GetChar(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetChar(Object* object, uint16_t c) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int16_t GetShort(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetShort(Object* object, int16_t s) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int32_t GetInt(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetInt(Object* object, int32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int64_t GetLong(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetLong(Object* object, int64_t j) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + float GetFloat(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetFloat(Object* object, float f) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + double GetDouble(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetDouble(Object* object, double d) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* GetObject(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetObject(Object* object, const Object* l) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // raw field accesses + uint32_t Get32(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Set32(Object* object, uint32_t new_value) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint64_t Get64(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Set64(Object* object, uint64_t new_value) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* GetObj(const Object* object) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetObj(Object* object, const Object* new_value) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static Class* GetJavaLangReflectField() { + DCHECK(java_lang_reflect_Field_ != NULL); + return java_lang_reflect_Field_; + } + + static void SetClass(Class* java_lang_reflect_Field); + static void ResetClass(); + + bool IsVolatile() const { + return (GetAccessFlags() & kAccVolatile) != 0; + } + + private: + // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". + // The class we are a part of + Class* declaring_class_; + + uint32_t access_flags_; + + // Dex cache index of field id + uint32_t field_dex_idx_; + + // Offset of field within an instance or in the Class' static fields + uint32_t offset_; + + static Class* java_lang_reflect_Field_; + + friend struct art::FieldOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(Field); +}; + +class MANAGED FieldClass : public Class { + private: + Object* ORDER_BY_NAME_AND_DECLARING_CLASS_; + friend struct art::FieldClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(FieldClass); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_FIELD_H_ diff --git a/src/mirror/iftable-inl.h b/src/mirror/iftable-inl.h new file mode 100644 index 0000000000..72803b8002 --- /dev/null +++ b/src/mirror/iftable-inl.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_IFTABLE_INL_H_ +#define ART_SRC_MIRROR_IFTABLE_INL_H_ + +#include "iftable.h" + +namespace art { +namespace mirror { + +inline void IfTable::SetInterface(int32_t i, Class* interface) { + DCHECK(interface != NULL); + DCHECK(interface->IsInterface()); + DCHECK(Get((i * kMax) + kInterface) == NULL); + Set((i * kMax) + kInterface, interface); +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_IFTABLE_INL_H_ diff --git a/src/mirror/iftable.h b/src/mirror/iftable.h new file mode 100644 index 0000000000..ffb2e51582 --- /dev/null +++ b/src/mirror/iftable.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_IFTABLE_H_ +#define ART_SRC_MIRROR_IFTABLE_H_ + +#include "object_array.h" + +namespace art { +namespace mirror { + +class MANAGED IfTable : public ObjectArray<Object> { + public: + Class* GetInterface(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + Class* interface = Get((i * kMax) + kInterface)->AsClass(); + DCHECK(interface != NULL); + return interface; + } + + void SetInterface(int32_t i, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<AbstractMethod>* GetMethodArray(int32_t i) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ObjectArray<AbstractMethod>* method_array = + down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray)); + DCHECK(method_array != NULL); + return method_array; + } + + size_t GetMethodArrayCount(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ObjectArray<AbstractMethod>* method_array = + down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray)); + if (method_array == NULL) { + return 0; + } + return method_array->GetLength(); + } + + void SetMethodArray(int32_t i, ObjectArray<AbstractMethod>* new_ma) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(new_ma != NULL); + DCHECK(Get((i * kMax) + kMethodArray) == NULL); + Set((i * kMax) + kMethodArray, new_ma); + } + + size_t Count() const { + return GetLength() / kMax; + } + + enum { + // Points to the interface class. + kInterface = 0, + // Method pointers into the vtable, allow fast map from interface method index to concrete + // instance method. + kMethodArray = 1, + kMax = 2, + }; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(IfTable); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_IFTABLE_H_ diff --git a/src/mirror/object-inl.h b/src/mirror/object-inl.h new file mode 100644 index 0000000000..723192dc8a --- /dev/null +++ b/src/mirror/object-inl.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_OBJECT_INL_H_ +#define ART_SRC_MIRROR_OBJECT_INL_H_ + +#include "object.h" + +#include "abstract_method.h" +#include "atomic.h" +#include "array.h" +#include "field.h" +#include "class.h" +#include "runtime.h" + +namespace art { +namespace mirror { + +inline Class* Object::GetClass() const { + return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false); +} + +inline void Object::SetClass(Class* new_klass) { + // new_klass may be NULL prior to class linker initialization + // We don't mark the card since the class is guaranteed to be referenced from another location. + // Proxy classes are held live by the class loader, and other classes are roots of the class + // linker. + SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false); +} + +inline bool Object::InstanceOf(const Class* klass) const { + DCHECK(klass != NULL); + DCHECK(GetClass() != NULL); + return klass->IsAssignableFrom(GetClass()); +} + +inline bool Object::IsClass() const { + Class* java_lang_Class = GetClass()->GetClass(); + return GetClass() == java_lang_Class; +} + +inline Class* Object::AsClass() { + DCHECK(IsClass()); + return down_cast<Class*>(this); +} + +inline const Class* Object::AsClass() const { + DCHECK(IsClass()); + return down_cast<const Class*>(this); +} + +inline bool Object::IsObjectArray() const { + return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive(); +} + +template<class T> +inline ObjectArray<T>* Object::AsObjectArray() { + DCHECK(IsObjectArray()); + return down_cast<ObjectArray<T>*>(this); +} + +template<class T> +inline const ObjectArray<T>* Object::AsObjectArray() const { + DCHECK(IsObjectArray()); + return down_cast<const ObjectArray<T>*>(this); +} + +inline bool Object::IsArrayInstance() const { + return GetClass()->IsArrayClass(); +} + +inline bool Object::IsField() const { + return GetClass()->IsFieldClass(); +} + +inline Field* Object::AsField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(IsField()); + return down_cast<Field*>(this); +} + +inline const Field* Object::AsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(IsField()); + return down_cast<const Field*>(this); +} + +inline bool Object::IsMethod() const { + return GetClass()->IsMethodClass(); +} + +inline AbstractMethod* Object::AsMethod() { + DCHECK(IsMethod()); + return down_cast<AbstractMethod*>(this); +} + +inline const AbstractMethod* Object::AsMethod() const { + DCHECK(IsMethod()); + return down_cast<const AbstractMethod*>(this); +} + +inline bool Object::IsReferenceInstance() const { + return GetClass()->IsReferenceClass(); +} + +inline bool Object::IsWeakReferenceInstance() const { + return GetClass()->IsWeakReferenceClass(); +} + +inline bool Object::IsSoftReferenceInstance() const { + return GetClass()->IsSoftReferenceClass(); +} + +inline bool Object::IsFinalizerReferenceInstance() const { + return GetClass()->IsFinalizerReferenceClass(); +} + +inline bool Object::IsPhantomReferenceInstance() const { + return GetClass()->IsPhantomReferenceClass(); +} + +inline size_t Object::SizeOf() const { + size_t result; + if (IsArrayInstance()) { + result = AsArray()->SizeOf(); + } else if (IsClass()) { + result = AsClass()->SizeOf(); + } else { + result = GetClass()->GetObjectSize(); + } + DCHECK(!IsField() || result == sizeof(Field)); + DCHECK(!IsMethod() || result == sizeof(AbstractMethod)); + return result; +} + +inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const { + VerifyObject(this); + const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); + const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); + if (UNLIKELY(is_volatile)) { + uint64_t result = QuasiAtomic::Read64(addr); + ANDROID_MEMBAR_FULL(); + return result; + } else { + return *addr; + } +} + +inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) { + VerifyObject(this); + byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); + int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); + if (UNLIKELY(is_volatile)) { + ANDROID_MEMBAR_STORE(); + QuasiAtomic::Write64(addr, new_value); + // Post-store barrier not required due to use of atomic op or mutex. + } else { + *addr = new_value; + } +} + +inline void Object::WriteBarrierField(const Object* dst, MemberOffset field_offset, + const Object* new_value) { + Runtime::Current()->GetHeap()->WriteBarrierField(dst, field_offset, new_value); +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_OBJECT_INL_H_ diff --git a/src/mirror/object.cc b/src/mirror/object.cc new file mode 100644 index 0000000000..27a42d3334 --- /dev/null +++ b/src/mirror/object.cc @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "object.h" + +#include "array-inl.h" +#include "class.h" +#include "class-inl.h" +#include "field.h" +#include "field-inl.h" +#include "gc/card_table-inl.h" +#include "heap.h" +#include "monitor.h" +#include "object-inl.h" +#include "object_array.h" +#include "object_utils.h" +#include "runtime.h" +#include "sirt_ref.h" +#include "throwable.h" +#include "well_known_classes.h" + +namespace art { +namespace mirror { + +Array* Object::AsArray() { + DCHECK(IsArrayInstance()); + return down_cast<Array*>(this); +} + +const Array* Object::AsArray() const { + DCHECK(IsArrayInstance()); + return down_cast<const Array*>(this); +} + +BooleanArray* Object::AsBooleanArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean()); + return down_cast<BooleanArray*>(this); +} + +ByteArray* Object::AsByteArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte()); + return down_cast<ByteArray*>(this); +} + +CharArray* Object::AsCharArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar()); + return down_cast<CharArray*>(this); +} + +ShortArray* Object::AsShortArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort()); + return down_cast<ShortArray*>(this); +} + +IntArray* Object::AsIntArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() || + GetClass()->GetComponentType()->IsPrimitiveFloat()); + return down_cast<IntArray*>(this); +} + +LongArray* Object::AsLongArray() { + DCHECK(GetClass()->IsArrayClass()); + DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() || + GetClass()->GetComponentType()->IsPrimitiveDouble()); + return down_cast<LongArray*>(this); +} + +String* Object::AsString() { + DCHECK(GetClass()->IsStringClass()); + return down_cast<String*>(this); +} + +Throwable* Object::AsThrowable() { + DCHECK(GetClass()->IsThrowableClass()); + return down_cast<Throwable*>(this); +} + +Object* Object::Clone(Thread* self) { + Class* c = GetClass(); + DCHECK(!c->IsClassClass()); + + // Object::SizeOf gets the right size even if we're an array. + // Using c->AllocObject() here would be wrong. + size_t num_bytes = SizeOf(); + Heap* heap = Runtime::Current()->GetHeap(); + SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes)); + if (copy.get() == NULL) { + return NULL; + } + + // Copy instance data. We assume memcpy copies by words. + // TODO: expose and use move32. + byte* src_bytes = reinterpret_cast<byte*>(this); + byte* dst_bytes = reinterpret_cast<byte*>(copy.get()); + size_t offset = sizeof(Object); + memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset); + + // Perform write barriers on copied object references. + if (c->IsArrayClass()) { + if (!c->GetComponentType()->IsPrimitive()) { + const ObjectArray<Object>* array = copy->AsObjectArray<Object>(); + heap->WriteBarrierArray(copy.get(), 0, array->GetLength()); + } + } else { + for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) { + size_t num_reference_fields = klass->NumReferenceInstanceFields(); + for (size_t i = 0; i < num_reference_fields; ++i) { + Field* field = klass->GetInstanceField(i); + MemberOffset field_offset = field->GetOffset(); + const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false); + heap->WriteBarrierField(copy.get(), field_offset, ref); + } + } + } + + if (c->IsFinalizable()) { + heap->AddFinalizerReference(Thread::Current(), copy.get()); + } + + return copy.get(); +} + +uint32_t Object::GetThinLockId() { + return Monitor::GetThinLockId(monitor_); +} + +void Object::MonitorEnter(Thread* thread) { + Monitor::MonitorEnter(thread, this); +} + +bool Object::MonitorExit(Thread* thread) { + return Monitor::MonitorExit(thread, this); +} + +void Object::Notify() { + Monitor::Notify(Thread::Current(), this); +} + +void Object::NotifyAll() { + Monitor::NotifyAll(Thread::Current(), this); +} + +void Object::Wait() { + Monitor::Wait(Thread::Current(), this, 0, 0, true, kWaiting); +} + +void Object::Wait(int64_t ms, int32_t ns) { + Monitor::Wait(Thread::Current(), this, ms, ns, true, kTimedWaiting); +} + +#if VERIFY_OBJECT_ENABLED +void Object::CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) { + const Class* c = GetClass(); + if (Runtime::Current()->GetClassLinker() == NULL || + !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() || + !c->IsResolved()) { + return; + } + for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) { + ObjectArray<Field>* fields = cur->GetIFields(); + if (fields != NULL) { + size_t num_ref_ifields = cur->NumReferenceInstanceFields(); + for (size_t i = 0; i < num_ref_ifields; ++i) { + Field* field = fields->Get(i); + if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { + FieldHelper fh(field); + CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); + return; + } + } + } + } + if (c->IsArrayClass()) { + // Bounds and assign-ability done in the array setter. + return; + } + if (IsClass()) { + ObjectArray<Field>* fields = AsClass()->GetSFields(); + if (fields != NULL) { + size_t num_ref_sfields = AsClass()->NumReferenceStaticFields(); + for (size_t i = 0; i < num_ref_sfields; ++i) { + Field* field = fields->Get(i); + if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { + FieldHelper fh(field); + CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); + return; + } + } + } + } + LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this) + << " of type " << PrettyDescriptor(c) << " at offset " << field_offset; +} +#endif + +} // namespace mirror +} // namespace art diff --git a/src/mirror/object.h b/src/mirror/object.h new file mode 100644 index 0000000000..e2cedd860b --- /dev/null +++ b/src/mirror/object.h @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_OBJECT_H_ +#define ART_SRC_MIRROR_OBJECT_H_ + +#include "base/casts.h" +#include "base/logging.h" +#include "base/macros.h" +#include "cutils/atomic-inline.h" +#include "offsets.h" + +namespace art { + +class ImageWriter; +struct ObjectOffsets; +class Thread; + +namespace mirror { + +class AbstractMethod; +class Array; +class Class; +class Field; +template<class T> class ObjectArray; +template<class T> class PrimitiveArray; +typedef PrimitiveArray<uint8_t> BooleanArray; +typedef PrimitiveArray<int8_t> ByteArray; +typedef PrimitiveArray<uint16_t> CharArray; +typedef PrimitiveArray<double> DoubleArray; +typedef PrimitiveArray<float> FloatArray; +typedef PrimitiveArray<int32_t> IntArray; +typedef PrimitiveArray<int64_t> LongArray; +typedef PrimitiveArray<int16_t> ShortArray; +class String; +class Throwable; + +// Classes shared with the managed side of the world need to be packed so that they don't have +// extra platform specific padding. +#define MANAGED PACKED(4) + +// Fields within mirror objects aren't accessed directly so that the appropriate amount of +// handshaking is done with GC (for example, read and write barriers). This macro is used to +// compute an offset for the Set/Get methods defined in Object that can safely access fields. +#define OFFSET_OF_OBJECT_MEMBER(type, field) \ + MemberOffset(OFFSETOF_MEMBER(type, field)) + +// C++ mirror of java.lang.Object +class MANAGED Object { + public: + static MemberOffset ClassOffset() { + return OFFSET_OF_OBJECT_MEMBER(Object, klass_); + } + + Class* GetClass() const; + + void SetClass(Class* new_klass); + + bool InstanceOf(const Class* klass) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int32_t IdentityHashCode() const { + #ifdef MOVING_GARBAGE_COLLECTOR + // TODO: we'll need to use the Object's internal concept of identity + UNIMPLEMENTED(FATAL); + #endif + return reinterpret_cast<int32_t>(this); + } + + static MemberOffset MonitorOffset() { + return OFFSET_OF_OBJECT_MEMBER(Object, monitor_); + } + + volatile int32_t* GetRawLockWordAddress() { + byte* raw_addr = reinterpret_cast<byte*>(this) + + OFFSET_OF_OBJECT_MEMBER(Object, monitor_).Int32Value(); + int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); + return const_cast<volatile int32_t*>(word_addr); + } + + uint32_t GetThinLockId(); + + void MonitorEnter(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + EXCLUSIVE_LOCK_FUNCTION(monitor_lock_); + + bool MonitorExit(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + UNLOCK_FUNCTION(monitor_lock_); + + void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Wait(int64_t timeout) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Wait(int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsClass() const; + + Class* AsClass(); + + const Class* AsClass() const; + + bool IsObjectArray() const; + + template<class T> + ObjectArray<T>* AsObjectArray(); + + template<class T> + const ObjectArray<T>* AsObjectArray() const; + + bool IsArrayInstance() const; + + Array* AsArray(); + + const Array* AsArray() const; + + BooleanArray* AsBooleanArray(); + ByteArray* AsByteArray(); + CharArray* AsCharArray(); + ShortArray* AsShortArray(); + IntArray* AsIntArray(); + LongArray* AsLongArray(); + + String* AsString(); + + Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsMethod() const; + + AbstractMethod* AsMethod(); + + const AbstractMethod* AsMethod() const; + + bool IsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + Field* AsField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + const Field* AsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool IsReferenceInstance() const; + + bool IsWeakReferenceInstance() const; + + bool IsSoftReferenceInstance() const; + + bool IsFinalizerReferenceInstance() const; + + bool IsPhantomReferenceInstance() const; + + // Accessors for Java type fields + template<class T> + T GetFieldObject(MemberOffset field_offset, bool is_volatile) const { + T result = reinterpret_cast<T>(GetField32(field_offset, is_volatile)); + VerifyObject(result); + return result; + } + + void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile, + bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + VerifyObject(new_value); + SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid); + if (new_value != NULL) { + CheckFieldAssignment(field_offset, new_value); + WriteBarrierField(this, field_offset, new_value); + } + } + + uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const { + VerifyObject(this); + const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); + const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); + if (UNLIKELY(is_volatile)) { + return android_atomic_acquire_load(word_addr); + } else { + return *word_addr; + } + } + + void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile, + bool this_is_valid = true) { + if (this_is_valid) { + VerifyObject(this); + } + byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); + uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr); + if (UNLIKELY(is_volatile)) { + /* + * TODO: add an android_atomic_synchronization_store() function and + * use it in the 32-bit volatile set handlers. On some platforms we + * can use a fast atomic instruction and avoid the barriers. + */ + ANDROID_MEMBAR_STORE(); + *word_addr = new_value; + ANDROID_MEMBAR_FULL(); + } else { + *word_addr = new_value; + } + } + + uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const; + + void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile); + + protected: + // Accessors for non-Java type fields + template<class T> + T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const { + return reinterpret_cast<T>(GetField32(field_offset, is_volatile)); + } + + template<typename T> + void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) { + SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid); + } + + private: +#if VERIFY_OBJECT_ENABLED + static void VerifyObject(const Object* obj); + void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); +#else + static void VerifyObject(const Object*) {} + void CheckFieldAssignment(MemberOffset, const Object*) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {} +#endif + + // Write barrier called post update to a reference bearing field. + static void WriteBarrierField(const Object* dst, MemberOffset offset, const Object* new_value); + + Class* klass_; + + uint32_t monitor_; + + friend class art::ImageWriter; + friend struct art::ObjectOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(Object); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_OBJECT_H_ diff --git a/src/mirror/object_array-inl.h b/src/mirror/object_array-inl.h new file mode 100644 index 0000000000..d98142829a --- /dev/null +++ b/src/mirror/object_array-inl.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_OBJECT_ARRAY_INL_H_ +#define ART_SRC_MIRROR_OBJECT_ARRAY_INL_H_ + +#include "object_array.h" + +#include "heap.h" +#include "mirror/class.h" +#include "mirror/field.h" +#include "runtime.h" + +namespace art { +namespace mirror { + +template<class T> +inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) { + Array* array = Array::Alloc(self, object_array_class, length, sizeof(Object*)); + if (UNLIKELY(array == NULL)) { + return NULL; + } else { + return array->AsObjectArray<T>(); + } +} + +template<class T> +inline T* ObjectArray<T>::Get(int32_t i) const { + if (UNLIKELY(!IsValidIndex(i))) { + return NULL; + } + MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); + return GetFieldObject<T*>(data_offset, false); +} + +template<class T> +inline void ObjectArray<T>::Set(int32_t i, T* object) { + if (LIKELY(IsValidIndex(i))) { + if (object != NULL) { + Class* element_class = GetClass()->GetComponentType(); + if (UNLIKELY(!object->InstanceOf(element_class))) { + ThrowArrayStoreException(object); + return; + } + } + MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); + SetFieldObject(data_offset, object, false); + } +} + +template<class T> +inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) { + DCHECK(IsValidIndex(i)); + MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); + SetFieldObject(data_offset, object, false); +} + +template<class T> +inline void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) { + DCHECK(IsValidIndex(i)); + MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); + SetFieldPtr(data_offset, object, false); +} + +template<class T> +inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) const { + DCHECK(IsValidIndex(i)); + MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); + return GetFieldObject<T*>(data_offset, false); +} + +template<class T> +inline void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos, + ObjectArray<T>* dst, int dst_pos, + size_t length) { + if (src->IsValidIndex(src_pos) && + src->IsValidIndex(src_pos+length-1) && + dst->IsValidIndex(dst_pos) && + dst->IsValidIndex(dst_pos+length-1)) { + MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*)); + MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*)); + Class* array_class = dst->GetClass(); + Heap* heap = Runtime::Current()->GetHeap(); + if (array_class == src->GetClass()) { + // No need for array store checks if arrays are of the same type + for (size_t i = 0; i < length; i++) { + Object* object = src->GetFieldObject<Object*>(src_offset, false); + heap->VerifyObject(object); + // directly set field, we do a bulk write barrier at the end + dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); + src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); + dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); + } + } else { + Class* element_class = array_class->GetComponentType(); + CHECK(!element_class->IsPrimitive()); + for (size_t i = 0; i < length; i++) { + Object* object = src->GetFieldObject<Object*>(src_offset, false); + if (object != NULL && !object->InstanceOf(element_class)) { + dst->ThrowArrayStoreException(object); + return; + } + heap->VerifyObject(object); + // directly set field, we do a bulk write barrier at the end + dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); + src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); + dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); + } + } + heap->WriteBarrierArray(dst, dst_pos, length); + } +} + +template<class T> +inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) { + ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length); + Copy(this, 0, new_array, 0, std::min(GetLength(), new_length)); + return new_array; +} + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_OBJET_ARRAY_INL_H_ diff --git a/src/mirror/object_array.h b/src/mirror/object_array.h new file mode 100644 index 0000000000..3d04b396da --- /dev/null +++ b/src/mirror/object_array.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_OBJECT_ARRAY_H_ +#define ART_SRC_MIRROR_OBJECT_ARRAY_H_ + +#include "array.h" + +namespace art { +namespace mirror { + +template<class T> +class MANAGED ObjectArray : public Array { + public: + static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Set(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Set element without bound and element type checks, to be used in limited + // circumstances, such as during boot image writing + void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Set element without bound and element type checks, to be used in limited circumstances, such + // as during boot image writing. Does not do write barrier. + void SetPtrWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static void Copy(const ObjectArray<T>* src, int src_pos, + ObjectArray<T>* dst, int dst_pos, + size_t length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + ObjectArray<T>* CopyOf(Thread* self, int32_t new_length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_OBJECT_ARRAY_H_ diff --git a/src/object_test.cc b/src/mirror/object_test.cc index f3b6a19739..29cf2f10a1 100644 --- a/src/object_test.cc +++ b/src/mirror/object_test.cc @@ -19,16 +19,26 @@ #include <stdint.h> #include <stdio.h> +#include "array-inl.h" #include "asm_support.h" +#include "class-inl.h" #include "class_linker.h" +#include "class_linker-inl.h" #include "common_test.h" #include "dex_file.h" +#include "field-inl.h" +#include "gc/card_table-inl.h" #include "heap.h" +#include "iftable-inl.h" +#include "abstract_method-inl.h" +#include "object-inl.h" +#include "object_array-inl.h" #include "runtime_support.h" #include "sirt_ref.h" #include "UniquePtr.h" namespace art { +namespace mirror { class ObjectTest : public CommonTest { protected: @@ -626,4 +636,5 @@ TEST_F(ObjectTest, FindStaticField) { // TODO: test that interfaces trump superclasses. } +} // namespace mirror } // namespace art diff --git a/src/mirror/proxy.h b/src/mirror/proxy.h new file mode 100644 index 0000000000..cac028a731 --- /dev/null +++ b/src/mirror/proxy.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_PROXY_H_ +#define ART_SRC_MIRROR_PROXY_H_ + +#include "mirror/object.h" + +namespace art { + +struct ProxyOffsets; + +namespace mirror { + +class MANAGED SynthesizedProxyClass : public Class { + public: + ObjectArray<Class>* GetInterfaces() { + return interfaces_; + } + + ObjectArray<ObjectArray<Class> >* GetThrows() { + return throws_; + } + + private: + ObjectArray<Class>* interfaces_; + ObjectArray<ObjectArray<Class> >* throws_; + DISALLOW_IMPLICIT_CONSTRUCTORS(SynthesizedProxyClass); +}; + +class MANAGED Proxy : public Object { + private: + Object* h_; + + friend struct art::ProxyOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_PROXY_H_ diff --git a/src/mirror/stack_trace_element.cc b/src/mirror/stack_trace_element.cc new file mode 100644 index 0000000000..9d557ec9e8 --- /dev/null +++ b/src/mirror/stack_trace_element.cc @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stack_trace_element.h" + +#include "class.h" +#include "gc/card_table-inl.h" +#include "object-inl.h" +#include "string.h" + +namespace art { +namespace mirror { + +Class* StackTraceElement::java_lang_StackTraceElement_ = NULL; + +void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) { + CHECK(java_lang_StackTraceElement_ == NULL); + CHECK(java_lang_StackTraceElement != NULL); + java_lang_StackTraceElement_ = java_lang_StackTraceElement; +} + +void StackTraceElement::ResetClass() { + CHECK(java_lang_StackTraceElement_ != NULL); + java_lang_StackTraceElement_ = NULL; +} + +StackTraceElement* StackTraceElement::Alloc(Thread* self, + String* declaring_class, + String* method_name, + String* file_name, + int32_t line_number) { + StackTraceElement* trace = + down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject(self)); + trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), + const_cast<String*>(declaring_class), false); + trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), + const_cast<String*>(method_name), false); + trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), + const_cast<String*>(file_name), false); + trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), + line_number, false); + return trace; +} + +} // namespace mirror +} // namespace art diff --git a/src/mirror/stack_trace_element.h b/src/mirror/stack_trace_element.h new file mode 100644 index 0000000000..d53c8602dc --- /dev/null +++ b/src/mirror/stack_trace_element.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_STACK_TRACE_ELEMENT_H_ +#define ART_SRC_MIRROR_STACK_TRACE_ELEMENT_H_ + +#include "object.h" + +namespace art { + +struct StackTraceElementOffsets; + +namespace mirror { + +// C++ mirror of java.lang.StackTraceElement +class MANAGED StackTraceElement : public Object { + public: + const String* GetDeclaringClass() const { + return GetFieldObject<const String*>( + OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false); + } + + const String* GetMethodName() const { + return GetFieldObject<const String*>( + OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false); + } + + const String* GetFileName() const { + return GetFieldObject<const String*>( + OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false); + } + + int32_t GetLineNumber() const { + return GetField32( + OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false); + } + + static StackTraceElement* Alloc(Thread* self, + String* declaring_class, + String* method_name, + String* file_name, + int32_t line_number) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static void SetClass(Class* java_lang_StackTraceElement); + + static void ResetClass(); + + private: + // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". + String* declaring_class_; + String* file_name_; + String* method_name_; + int32_t line_number_; + + static Class* GetStackTraceElement() { + DCHECK(java_lang_StackTraceElement_ != NULL); + return java_lang_StackTraceElement_; + } + + static Class* java_lang_StackTraceElement_; + + friend struct art::StackTraceElementOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_STACK_TRACE_ELEMENT_H_ diff --git a/src/mirror/string.cc b/src/mirror/string.cc new file mode 100644 index 0000000000..f571fb828a --- /dev/null +++ b/src/mirror/string.cc @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string.h" + +#include "array.h" +#include "gc/card_table-inl.h" +#include "intern_table.h" +#include "object-inl.h" +#include "runtime.h" +#include "sirt_ref.h" +#include "thread.h" +#include "utf.h" + +namespace art { +namespace mirror { + +const CharArray* String::GetCharArray() const { + return GetFieldObject<const CharArray*>(ValueOffset(), false); +} + +void String::ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength())); +} + +int32_t String::GetUtfLength() const { + return CountUtf8Bytes(GetCharArray()->GetData() + GetOffset(), GetLength()); +} + +int32_t String::FastIndexOf(int32_t ch, int32_t start) const { + int32_t count = GetLength(); + if (start < 0) { + start = 0; + } else if (start > count) { + start = count; + } + const uint16_t* chars = GetCharArray()->GetData() + GetOffset(); + const uint16_t* p = chars + start; + const uint16_t* end = chars + count; + while (p < end) { + if (*p++ == ch) { + return (p - 1) - chars; + } + } + return -1; +} + +void String::SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(new_array != NULL); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array, false); +} + +// TODO: get global references for these +Class* String::java_lang_String_ = NULL; + +void String::SetClass(Class* java_lang_String) { + CHECK(java_lang_String_ == NULL); + CHECK(java_lang_String != NULL); + java_lang_String_ = java_lang_String; +} + +void String::ResetClass() { + CHECK(java_lang_String_ != NULL); + java_lang_String_ = NULL; +} + +String* String::Intern() { + return Runtime::Current()->GetInternTable()->InternWeak(this); +} + +int32_t String::GetHashCode() { + int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false); + if (result == 0) { + ComputeHashCode(); + } + result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false); + DCHECK(result != 0 || ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0) + << ToModifiedUtf8() << " " << result; + return result; +} + +int32_t String::GetLength() const { + int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false); + DCHECK(result >= 0 && result <= GetCharArray()->GetLength()); + return result; +} + +uint16_t String::CharAt(int32_t index) const { + // TODO: do we need this? Equals is the only caller, and could + // bounds check itself. + if (index < 0 || index >= count_) { + Thread* self = Thread::Current(); + self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;", + "length=%i; index=%i", count_, index); + return 0; + } + return GetCharArray()->Get(index + GetOffset()); +} + +String* String::AllocFromUtf16(Thread* self, + int32_t utf16_length, + const uint16_t* utf16_data_in, + int32_t hash_code) { + CHECK(utf16_data_in != NULL || utf16_length == 0); + String* string = Alloc(self, GetJavaLangString(), utf16_length); + if (string == NULL) { + return NULL; + } + // TODO: use 16-bit wide memset variant + CharArray* array = const_cast<CharArray*>(string->GetCharArray()); + if (array == NULL) { + return NULL; + } + for (int i = 0; i < utf16_length; i++) { + array->Set(i, utf16_data_in[i]); + } + if (hash_code != 0) { + string->SetHashCode(hash_code); + } else { + string->ComputeHashCode(); + } + return string; +} + + String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) { + if (utf == NULL) { + return NULL; + } + size_t char_count = CountModifiedUtf8Chars(utf); + return AllocFromModifiedUtf8(self, char_count, utf); +} + +String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, + const char* utf8_data_in) { + String* string = Alloc(self, GetJavaLangString(), utf16_length); + if (string == NULL) { + return NULL; + } + uint16_t* utf16_data_out = + const_cast<uint16_t*>(string->GetCharArray()->GetData()); + ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in); + string->ComputeHashCode(); + return string; +} + +String* String::Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) { + SirtRef<CharArray> array(self, CharArray::Alloc(self, utf16_length)); + if (array.get() == NULL) { + return NULL; + } + return Alloc(self, java_lang_String, array.get()); +} + +String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) { + // Hold reference in case AllocObject causes GC. + SirtRef<CharArray> array_ref(self, array); + String* string = down_cast<String*>(java_lang_String->AllocObject(self)); + if (string == NULL) { + return NULL; + } + string->SetArray(array); + string->SetCount(array->GetLength()); + return string; +} + +bool String::Equals(const String* that) const { + if (this == that) { + // Quick reference equality test + return true; + } else if (that == NULL) { + // Null isn't an instanceof anything + return false; + } else if (this->GetLength() != that->GetLength()) { + // Quick length inequality test + return false; + } else { + // Note: don't short circuit on hash code as we're presumably here as the + // hash code was already equal + for (int32_t i = 0; i < that->GetLength(); ++i) { + if (this->CharAt(i) != that->CharAt(i)) { + return false; + } + } + return true; + } +} + +bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) const { + if (this->GetLength() != that_length) { + return false; + } else { + for (int32_t i = 0; i < that_length; ++i) { + if (this->CharAt(i) != that_chars[that_offset + i]) { + return false; + } + } + return true; + } +} + +bool String::Equals(const char* modified_utf8) const { + for (int32_t i = 0; i < GetLength(); ++i) { + uint16_t ch = GetUtf16FromUtf8(&modified_utf8); + if (ch == '\0' || ch != CharAt(i)) { + return false; + } + } + return *modified_utf8 == '\0'; +} + +bool String::Equals(const StringPiece& modified_utf8) const { + if (modified_utf8.size() != GetLength()) { + return false; + } + const char* p = modified_utf8.data(); + for (int32_t i = 0; i < GetLength(); ++i) { + uint16_t ch = GetUtf16FromUtf8(&p); + if (ch != CharAt(i)) { + return false; + } + } + return true; +} + +// Create a modified UTF-8 encoded std::string from a java/lang/String object. +std::string String::ToModifiedUtf8() const { + const uint16_t* chars = GetCharArray()->GetData() + GetOffset(); + size_t byte_count = GetUtfLength(); + std::string result(byte_count, static_cast<char>(0)); + ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength()); + return result; +} + +#ifdef HAVE__MEMCMP16 +// "count" is in 16-bit units. +extern "C" uint32_t __memcmp16(const uint16_t* s0, const uint16_t* s1, size_t count); +#define MemCmp16 __memcmp16 +#else +static uint32_t MemCmp16(const uint16_t* s0, const uint16_t* s1, size_t count) { + for (size_t i = 0; i < count; i++) { + if (s0[i] != s1[i]) { + return static_cast<int32_t>(s0[i]) - static_cast<int32_t>(s1[i]); + } + } + return 0; +} +#endif + +int32_t String::CompareTo(String* rhs) const { + // Quick test for comparison of a string with itself. + const String* lhs = this; + if (lhs == rhs) { + return 0; + } + // TODO: is this still true? + // The annoying part here is that 0x00e9 - 0xffff != 0x00ea, + // because the interpreter converts the characters to 32-bit integers + // *without* sign extension before it subtracts them (which makes some + // sense since "char" is unsigned). So what we get is the result of + // 0x000000e9 - 0x0000ffff, which is 0xffff00ea. + int lhsCount = lhs->GetLength(); + int rhsCount = rhs->GetLength(); + int countDiff = lhsCount - rhsCount; + int minCount = (countDiff < 0) ? lhsCount : rhsCount; + const uint16_t* lhsChars = lhs->GetCharArray()->GetData() + lhs->GetOffset(); + const uint16_t* rhsChars = rhs->GetCharArray()->GetData() + rhs->GetOffset(); + int otherRes = MemCmp16(lhsChars, rhsChars, minCount); + if (otherRes != 0) { + return otherRes; + } + return countDiff; +} + +} // namespace mirror +} // namespace art + diff --git a/src/mirror/string.h b/src/mirror/string.h new file mode 100644 index 0000000000..ef74fed93c --- /dev/null +++ b/src/mirror/string.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_STRING_H_ +#define ART_SRC_MIRROR_STRING_H_ + +#include "class.h" +#include "gtest/gtest.h" + +namespace art { + +struct StringClassOffsets; +struct StringOffsets; +class StringPiece; + +namespace mirror { + +// C++ mirror of java.lang.String +class MANAGED String : public Object { + public: + static MemberOffset CountOffset() { + return OFFSET_OF_OBJECT_MEMBER(String, count_); + } + + static MemberOffset ValueOffset() { + return OFFSET_OF_OBJECT_MEMBER(String, array_); + } + + static MemberOffset OffsetOffset() { + return OFFSET_OF_OBJECT_MEMBER(String, offset_); + } + + const CharArray* GetCharArray() const; + + int32_t GetOffset() const { + int32_t result = GetField32(OffsetOffset(), false); + DCHECK_LE(0, result); + return result; + } + + int32_t GetLength() const; + + int32_t GetHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int32_t GetUtfLength() const; + + uint16_t CharAt(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static String* AllocFromUtf16(Thread* self, + int32_t utf16_length, + const uint16_t* utf16_data_in, + int32_t hash_code = 0) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static String* AllocFromModifiedUtf8(Thread* self, const char* utf) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, + const char* utf8_data_in) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool Equals(const char* modified_utf8) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // TODO: do we need this overload? give it a more intention-revealing name. + bool Equals(const StringPiece& modified_utf8) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + bool Equals(const String* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Compare UTF-16 code point values not in a locale-sensitive manner + int Compare(int32_t utf16_length, const char* utf8_data_in); + + // TODO: do we need this overload? give it a more intention-revealing name. + bool Equals(const uint16_t* that_chars, int32_t that_offset, + int32_t that_length) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Create a modified UTF-8 encoded std::string from a java/lang/String object. + std::string ToModifiedUtf8() const; + + int32_t FastIndexOf(int32_t ch, int32_t start) const; + + int32_t CompareTo(String* other) const; + + static Class* GetJavaLangString() { + DCHECK(java_lang_String_ != NULL); + return java_lang_String_; + } + + static void SetClass(Class* java_lang_String); + static void ResetClass(); + + private: + void SetHashCode(int32_t new_hash_code) { + DCHECK_EQ(0u, + GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false)); + SetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), + new_hash_code, false); + } + + void SetCount(int32_t new_count) { + DCHECK_LE(0, new_count); + SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false); + } + + void SetOffset(int32_t new_offset) { + DCHECK_LE(0, new_offset); + DCHECK_GE(GetLength(), new_offset); + SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false); + } + + void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". + CharArray* array_; + + int32_t count_; + + uint32_t hash_code_; + + int32_t offset_; + + static Class* java_lang_String_; + + friend struct art::StringOffsets; // for verifying offset information + FRIEND_TEST(ObjectTest, StringLength); // for SetOffset and SetCount + DISALLOW_IMPLICIT_CONSTRUCTORS(String); +}; + +// TODO: remove? only used in a unit test of itself. +struct StringHashCode { + int32_t operator()(String* string) const { + return string->GetHashCode(); + } +}; + +class MANAGED StringClass : public Class { + private: + CharArray* ASCII_; + Object* CASE_INSENSITIVE_ORDER_; + uint32_t REPLACEMENT_CHAR_; + int64_t serialVersionUID_; + friend struct art::StringClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(StringClass); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_STRING_H_ diff --git a/src/mirror/throwable.cc b/src/mirror/throwable.cc new file mode 100644 index 0000000000..bbab1dd60d --- /dev/null +++ b/src/mirror/throwable.cc @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "throwable.h" + +#include "abstract_method-inl.h" +#include "class-inl.h" +#include "gc/card_table-inl.h" +#include "object-inl.h" +#include "object_array.h" +#include "object_array-inl.h" +#include "object_utils.h" +#include "utils.h" +#include "well_known_classes.h" + +namespace art { +namespace mirror { + +Class* Throwable::java_lang_Throwable_ = NULL; + +void Throwable::SetCause(Throwable* cause) { + CHECK(cause != NULL); + CHECK(cause != this); + CHECK(GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false) == NULL); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false); +} + +bool Throwable::IsCheckedException() const { + if (InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_Error))) { + return false; + } + return !InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_RuntimeException)); +} + +std::string Throwable::Dump() const { + std::string result(PrettyTypeOf(this)); + result += ": "; + String* msg = GetDetailMessage(); + if (msg != NULL) { + result += msg->ToModifiedUtf8(); + } + result += "\n"; + Object* stack_state = GetStackState(); + // check stack state isn't missing or corrupt + if (stack_state != NULL && stack_state->IsObjectArray()) { + // Decode the internal stack trace into the depth and method trace + ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state); + int32_t depth = method_trace->GetLength() - 1; + IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); + MethodHelper mh; + for (int32_t i = 0; i < depth; ++i) { + AbstractMethod* method = down_cast<AbstractMethod*>(method_trace->Get(i)); + mh.ChangeMethod(method); + uint32_t dex_pc = pc_trace->Get(i); + int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); + const char* source_file = mh.GetDeclaringClassSourceFile(); + result += StringPrintf(" at %s (%s:%d)\n", PrettyMethod(method, true).c_str(), + source_file, line_number); + } + } + Throwable* cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false); + if (cause != NULL && cause != this) { // Constructor makes cause == this by default. + result += "Caused by: "; + result += cause->Dump(); + } + return result; +} + +void Throwable::SetClass(Class* java_lang_Throwable) { + CHECK(java_lang_Throwable_ == NULL); + CHECK(java_lang_Throwable != NULL); + java_lang_Throwable_ = java_lang_Throwable; +} + +void Throwable::ResetClass() { + CHECK(java_lang_Throwable_ != NULL); + java_lang_Throwable_ = NULL; +} + +} // namespace mirror +} // namespace art diff --git a/src/mirror/throwable.h b/src/mirror/throwable.h new file mode 100644 index 0000000000..aafcc07d86 --- /dev/null +++ b/src/mirror/throwable.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_MIRROR_THROWABLE_H_ +#define ART_SRC_MIRROR_THROWABLE_H_ + +#include "object.h" +#include "string.h" + +namespace art { + +struct ThrowableOffsets; + +namespace mirror { + +// C++ mirror of java.lang.Throwable +class MANAGED Throwable : public Object { + public: + void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false); + } + String* GetDetailMessage() const { + return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false); + } + std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // This is a runtime version of initCause, you shouldn't use it if initCause may have been + // overridden. Also it asserts rather than throwing exceptions. Currently this is only used + // in cases like the verifier where the checks cannot fail and initCause isn't overridden. + void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static Class* GetJavaLangThrowable() { + DCHECK(java_lang_Throwable_ != NULL); + return java_lang_Throwable_; + } + + static void SetClass(Class* java_lang_Throwable); + static void ResetClass(); + + private: + Object* GetStackState() const { + return GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true); + } + + // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". + Throwable* cause_; + String* detail_message_; + Object* stack_state_; // Note this is Java volatile: + Object* stack_trace_; + Object* suppressed_exceptions_; + + static Class* java_lang_Throwable_; + + friend struct art::ThrowableOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable); +}; + +} // namespace mirror +} // namespace art + +#endif // ART_SRC_MIRROR_THROWABLE_H_ diff --git a/src/modifiers.h b/src/modifiers.h index ee2d4ff597..78ba1404ef 100644 --- a/src/modifiers.h +++ b/src/modifiers.h @@ -17,6 +17,8 @@ #ifndef ART_SRC_MODIFIERS_H_ #define ART_SRC_MODIFIERS_H_ +#include <stdint.h> + static const uint32_t kAccPublic = 0x0001; // class, field, method, ic static const uint32_t kAccPrivate = 0x0002; // field, method, ic static const uint32_t kAccProtected = 0x0004; // field, method, ic diff --git a/src/monitor.cc b/src/monitor.cc index 47c87cb259..aa4e5acefe 100644 --- a/src/monitor.cc +++ b/src/monitor.cc @@ -22,7 +22,9 @@ #include "base/stl_util.h" #include "class_linker.h" #include "dex_instruction.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "thread.h" @@ -111,7 +113,7 @@ void Monitor::Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread is_sensitive_thread_hook_ = is_sensitive_thread_hook; } -Monitor::Monitor(Thread* owner, Object* obj) +Monitor::Monitor(Thread* owner, mirror::Object* obj) : monitor_lock_("a monitor lock", kMonitorLock), owner_(owner), lock_count_(0), @@ -186,7 +188,7 @@ void Monitor::RemoveFromWaitSet(Thread *thread) { } } -Object* Monitor::GetObject() { +mirror::Object* Monitor::GetObject() { return obj_; } @@ -200,7 +202,7 @@ void Monitor::Lock(Thread* self) { uint64_t waitStart = 0; uint64_t waitEnd = 0; uint32_t wait_threshold = lock_profiling_threshold_; - const AbstractMethod* current_locking_method = NULL; + const mirror::AbstractMethod* current_locking_method = NULL; uint32_t current_locking_dex_pc = 0; { ScopedThreadStateChange tsc(self, kBlocked); @@ -270,7 +272,7 @@ static std::string ThreadToString(Thread* thread) { return oss.str(); } -void Monitor::FailedUnlock(Object* o, Thread* expected_owner, Thread* found_owner, +void Monitor::FailedUnlock(mirror::Object* o, Thread* expected_owner, Thread* found_owner, Monitor* monitor) { Thread* current_owner = NULL; std::string current_owner_string; @@ -426,7 +428,7 @@ void Monitor::WaitWithLock(Thread* self, int64_t ms, int32_t ns, int prev_lock_count = lock_count_; lock_count_ = 0; owner_ = NULL; - const AbstractMethod* saved_method = locking_method_; + const mirror::AbstractMethod* saved_method = locking_method_; locking_method_ = NULL; uintptr_t saved_dex_pc = locking_dex_pc_; locking_dex_pc_ = 0; @@ -570,7 +572,7 @@ void Monitor::NotifyAllWithLock() { * Changes the shape of a monitor from thin to fat, preserving the * internal lock state. The calling thread must own the lock. */ -void Monitor::Inflate(Thread* self, Object* obj) { +void Monitor::Inflate(Thread* self, mirror::Object* obj) { DCHECK(self != NULL); DCHECK(obj != NULL); DCHECK_EQ(LW_SHAPE(*obj->GetRawLockWordAddress()), LW_SHAPE_THIN); @@ -583,7 +585,7 @@ void Monitor::Inflate(Thread* self, Object* obj) { Runtime::Current()->GetMonitorList()->Add(m); } -void Monitor::MonitorEnter(Thread* self, Object* obj) { +void Monitor::MonitorEnter(Thread* self, mirror::Object* obj) { volatile int32_t* thinp = obj->GetRawLockWordAddress(); uint32_t sleepDelayNs; uint32_t minSleepDelayNs = 1000000; /* 1 millisecond */ @@ -686,7 +688,7 @@ void Monitor::MonitorEnter(Thread* self, Object* obj) { } } -bool Monitor::MonitorExit(Thread* self, Object* obj) { +bool Monitor::MonitorExit(Thread* self, mirror::Object* obj) { volatile int32_t* thinp = obj->GetRawLockWordAddress(); DCHECK(self != NULL); @@ -748,7 +750,7 @@ bool Monitor::MonitorExit(Thread* self, Object* obj) { /* * Object.wait(). Also called for class init. */ -void Monitor::Wait(Thread* self, Object *obj, int64_t ms, int32_t ns, +void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why) { volatile int32_t* thinp = obj->GetRawLockWordAddress(); @@ -772,7 +774,7 @@ void Monitor::Wait(Thread* self, Object *obj, int64_t ms, int32_t ns, LW_MONITOR(*thinp)->Wait(self, ms, ns, interruptShouldThrow, why); } -void Monitor::Notify(Thread* self, Object *obj) { +void Monitor::Notify(Thread* self, mirror::Object *obj) { uint32_t thin = *obj->GetRawLockWordAddress(); // If the lock is still thin, there aren't any waiters; @@ -791,7 +793,7 @@ void Monitor::Notify(Thread* self, Object *obj) { } } -void Monitor::NotifyAll(Thread* self, Object *obj) { +void Monitor::NotifyAll(Thread* self, mirror::Object *obj) { uint32_t thin = *obj->GetRawLockWordAddress(); // If the lock is still thin, there aren't any waiters; @@ -822,7 +824,7 @@ uint32_t Monitor::GetThinLockId(uint32_t raw_lock_word) { void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { ThreadState state = thread->GetState(); - Object* object = NULL; + mirror::Object* object = NULL; uint32_t lock_owner = ThreadList::kInvalidId; if (state == kWaiting || state == kTimedWaiting || state == kSleeping) { if (state == kSleeping) { @@ -860,10 +862,10 @@ void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { os << "\n"; } -Object* Monitor::GetContendedMonitor(Thread* thread) { +mirror::Object* Monitor::GetContendedMonitor(Thread* thread) { // This is used to implement JDWP's ThreadReference.CurrentContendedMonitor, and has a bizarre // definition of contended that includes a monitor a thread is trying to enter... - Object* result = thread->monitor_enter_object_; + mirror::Object* result = thread->monitor_enter_object_; if (result != NULL) { return result; } @@ -878,15 +880,16 @@ Object* Monitor::GetContendedMonitor(Thread* thread) { return NULL; } -void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(Object*, void*), void* callback_context) { - AbstractMethod* m = stack_visitor->GetMethod(); +void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), + void* callback_context) { + mirror::AbstractMethod* m = stack_visitor->GetMethod(); CHECK(m != NULL); // Native methods are an easy special case. // TODO: use the JNI implementation's table of explicit MonitorEnter calls and dump those too. if (m->IsNative()) { if (m->IsSynchronized()) { - Object* jni_this = stack_visitor->GetCurrentSirt()->GetReference(0); + mirror::Object* jni_this = stack_visitor->GetCurrentSirt()->GetReference(0); callback(jni_this, callback_context); } return; @@ -933,13 +936,13 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(Object*, } uint16_t monitor_register = ((monitor_enter_instruction >> 8) & 0xff); - Object* o = reinterpret_cast<Object*>(stack_visitor->GetVReg(m, monitor_register, - kReferenceVReg)); + mirror::Object* o = reinterpret_cast<mirror::Object*>(stack_visitor->GetVReg(m, monitor_register, + kReferenceVReg)); callback(o, callback_context); } } -void Monitor::TranslateLocation(const AbstractMethod* method, uint32_t dex_pc, +void Monitor::TranslateLocation(const mirror::AbstractMethod* method, uint32_t dex_pc, const char*& source_file, uint32_t& line_number) const { // If method is null, location is unknown if (method == NULL) { @@ -968,7 +971,7 @@ void MonitorList::Add(Monitor* m) { list_.push_front(m); } -void MonitorList::SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg) { +void MonitorList::SweepMonitorList(IsMarkedTester is_marked, void* arg) { MutexLock mu(Thread::Current(), monitor_list_lock_); typedef std::list<Monitor*>::iterator It; // TODO: C++0x auto It it = list_.begin(); @@ -984,7 +987,7 @@ void MonitorList::SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg) { } } -MonitorInfo::MonitorInfo(Object* o) : owner(NULL), entry_count(0) { +MonitorInfo::MonitorInfo(mirror::Object* o) : owner(NULL), entry_count(0) { uint32_t lock_word = *o->GetRawLockWordAddress(); if (LW_SHAPE(lock_word) == LW_SHAPE_THIN) { uint32_t owner_thin_lock_id = LW_LOCK_OWNER(lock_word); diff --git a/src/monitor.h b/src/monitor.h index 1b5ab763e2..9194c08ab4 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -25,8 +25,8 @@ #include <vector> #include "base/mutex.h" -#include "heap.h" -#include "thread.h" +#include "root_visitor.h" +#include "thread_state.h" namespace art { @@ -55,8 +55,10 @@ namespace art { #define LW_LOCK_OWNER_SHIFT 3 #define LW_LOCK_OWNER(x) (((x) >> LW_LOCK_OWNER_SHIFT) & LW_LOCK_OWNER_MASK) +namespace mirror { class AbstractMethod; class Object; +} // namespace mirror class Thread; class StackVisitor; @@ -70,18 +72,19 @@ class Monitor { static uint32_t GetThinLockId(uint32_t raw_lock_word) NO_THREAD_SAFETY_ANALYSIS; // Reading lock owner without holding lock is racy. - static void MonitorEnter(Thread* thread, Object* obj) + static void MonitorEnter(Thread* thread, mirror::Object* obj) EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static bool MonitorExit(Thread* thread, Object* obj) + static bool MonitorExit(Thread* thread, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) UNLOCK_FUNCTION(monitor_lock_); - static void Notify(Thread* self, Object* obj) + static void Notify(Thread* self, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void NotifyAll(Thread* self, Object* obj) + static void NotifyAll(Thread* self, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void Wait(Thread* self, Object* obj, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why) + static void Wait(Thread* self, mirror::Object* obj, int64_t ms, int32_t ns, + bool interruptShouldThrow, ThreadState why) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void DescribeWait(std::ostream& os, const Thread* thread) @@ -89,30 +92,31 @@ class Monitor { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Used to implement JDWP's ThreadReference.CurrentContendedMonitor. - static Object* GetContendedMonitor(Thread* thread); + static mirror::Object* GetContendedMonitor(Thread* thread); // Calls 'callback' once for each lock held in the single stack frame represented by // the current state of 'stack_visitor'. - static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(Object*, void*), void* callback_context) + static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), + void* callback_context) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetObject(); + mirror::Object* GetObject(); private: - explicit Monitor(Thread* owner, Object* obj) + explicit Monitor(Thread* owner, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void AppendToWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_); void RemoveFromWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_); - static void Inflate(Thread* self, Object* obj) + static void Inflate(Thread* self, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, const char* owner_filename, uint32_t owner_line_number) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void FailedUnlock(Object* obj, Thread* expected_owner, Thread* found_owner, Monitor* mon) + static void FailedUnlock(mirror::Object* obj, Thread* expected_owner, Thread* found_owner, Monitor* mon) LOCKS_EXCLUDED(Locks::thread_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -137,7 +141,7 @@ class Monitor { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Translates the provided method and pc into its declaring class' source file and line number. - void TranslateLocation(const AbstractMethod* method, uint32_t pc, + void TranslateLocation(const mirror::AbstractMethod* method, uint32_t pc, const char*& source_file, uint32_t& line_number) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -153,7 +157,7 @@ class Monitor { int lock_count_ GUARDED_BY(monitor_lock_); // What object are we part of (for debugging). - Object* const obj_; + mirror::Object* const obj_; // Threads currently waiting on this monitor. Thread* wait_set_ GUARDED_BY(monitor_lock_); @@ -161,12 +165,12 @@ class Monitor { // Method and dex pc where the lock owner acquired the lock, used when lock // sampling is enabled. locking_method_ may be null if the lock is currently // unlocked, or if the lock is acquired by the system when the stack is empty. - const AbstractMethod* locking_method_ GUARDED_BY(monitor_lock_); + const mirror::AbstractMethod* locking_method_ GUARDED_BY(monitor_lock_); uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_); friend class MonitorInfo; friend class MonitorList; - friend class Object; + friend class mirror::Object; DISALLOW_COPY_AND_ASSIGN(Monitor); }; @@ -177,7 +181,7 @@ class MonitorList { void Add(Monitor* m); - void SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg) + void SweepMonitorList(IsMarkedTester is_marked, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); private: @@ -192,7 +196,7 @@ class MonitorList { // For use only by the JDWP implementation. class MonitorInfo { public: - MonitorInfo(Object* o) EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); + MonitorInfo(mirror::Object* o) EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); Thread* owner; size_t entry_count; diff --git a/src/monitor_android.cc b/src/monitor_android.cc index 6e22237afb..d3ac14355a 100644 --- a/src/monitor_android.cc +++ b/src/monitor_android.cc @@ -15,7 +15,6 @@ */ #include "monitor.h" -#include "object.h" #include "thread.h" #include <fcntl.h> @@ -79,7 +78,7 @@ void Monitor::LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample // Emit the source code file name, <= 37 bytes. uintptr_t pc; - AbstractMethod* m = self->GetCurrentMethod(&pc); + mirror::AbstractMethod* m = self->GetCurrentMethod(&pc); const char* filename; uint32_t line_number; TranslateLocation(m, pc, filename, line_number); diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc index 7485600fe4..e549a8bf74 100644 --- a/src/native/dalvik_system_DexFile.cc +++ b/src/native/dalvik_system_DexFile.cc @@ -18,11 +18,12 @@ #include "base/logging.h" #include "class_linker.h" -#include "class_loader.h" #include "dex_file.h" #include "gc/space.h" #include "image.h" #include "jni_internal.h" +#include "mirror/class_loader.h" +#include "mirror/string.h" #include "oat.h" #include "os.h" #include "runtime.h" @@ -150,9 +151,8 @@ static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, j } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); class_linker->RegisterDexFile(*dex_file); - Object* class_loader_object = soa.Decode<Object*>(javaLoader); - ClassLoader* class_loader = down_cast<ClassLoader*>(class_loader_object); - Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader); + mirror::Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def); return soa.AddLocalReference<jclass>(result); } diff --git a/src/native/dalvik_system_VMDebug.cc b/src/native/dalvik_system_VMDebug.cc index e5a398ab4b..dc07a31ee3 100644 --- a/src/native/dalvik_system_VMDebug.cc +++ b/src/native/dalvik_system_VMDebug.cc @@ -21,6 +21,7 @@ #include "debugger.h" #include "hprof/hprof.h" #include "jni_internal.h" +#include "mirror/class.h" #include "ScopedUtfChars.h" #include "scoped_thread_state_change.h" #include "toStringArray.h" @@ -220,11 +221,11 @@ static void VMDebug_infopoint(JNIEnv*, jclass, jint id) { static jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass, jboolean countAssignable) { ScopedObjectAccess soa(env); - Class* c = soa.Decode<Class*>(javaClass); + mirror::Class* c = soa.Decode<mirror::Class*>(javaClass); if (c == NULL) { return 0; } - std::vector<Class*> classes; + std::vector<mirror::Class*> classes; classes.push_back(c); uint64_t count = 0; Runtime::Current()->GetHeap()->CountInstances(classes, countAssignable, &count); diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc index bf518dcefb..5ce27fbcc0 100644 --- a/src/native/dalvik_system_VMRuntime.cc +++ b/src/native/dalvik_system_VMRuntime.cc @@ -19,7 +19,8 @@ #include "class_linker.h" #include "debugger.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/object.h" +#include "mirror/object-inl.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "gc/space.h" @@ -52,7 +53,7 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle UNIMPLEMENTED(FATAL); #endif - Class* element_class = soa.Decode<Class*>(javaElementClass); + mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); if (element_class == NULL) { soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "element class == null"); return NULL; @@ -66,8 +67,8 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle std::string descriptor; descriptor += "["; descriptor += ClassHelper(element_class).GetDescriptor(); - Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL); - Array* result = Array::Alloc(soa.Self(), array_class, length); + mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL); + mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length); if (result == NULL) { return NULL; } @@ -79,7 +80,7 @@ static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) { return 0; } ScopedObjectAccess soa(env); - Array* array = soa.Decode<Array*>(javaArray); + mirror::Array* array = soa.Decode<mirror::Array*>(javaArray); if (!array->IsArrayInstance()) { soa.Self()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array"); return 0; diff --git a/src/native/dalvik_system_VMStack.cc b/src/native/dalvik_system_VMStack.cc index 494f38d38a..bb2ed8889d 100644 --- a/src/native/dalvik_system_VMStack.cc +++ b/src/native/dalvik_system_VMStack.cc @@ -14,10 +14,11 @@ * limitations under the License. */ -#include "class_loader.h" #include "jni_internal.h" #include "nth_caller_visitor.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class.h" +#include "mirror/class_loader.h" #include "scoped_thread_state_change.h" #include "thread_list.h" @@ -26,7 +27,7 @@ namespace art { static jobject GetThreadStack(JNIEnv* env, jobject peer) { { ScopedObjectAccess soa(env); - if (soa.Decode<Object*>(peer) == soa.Self()->GetPeer()) { + if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) { return soa.Self()->CreateInternalStackTrace(soa); } } @@ -73,13 +74,13 @@ static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) { static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap, jobject javaSystem) { struct ClosestUserClassLoaderVisitor : public StackVisitor { - ClosestUserClassLoaderVisitor(Thread* thread, Object* bootstrap, Object* system) + ClosestUserClassLoaderVisitor(Thread* thread, mirror::Object* bootstrap, mirror::Object* system) : StackVisitor(thread, NULL), bootstrap(bootstrap), system(system), class_loader(NULL) {} bool VisitFrame() { DCHECK(class_loader == NULL); - Class* c = GetMethod()->GetDeclaringClass(); - Object* cl = c->GetClassLoader(); + mirror::Class* c = GetMethod()->GetDeclaringClass(); + mirror::Object* cl = c->GetClassLoader(); if (cl != NULL && cl != bootstrap && cl != system) { class_loader = cl; return false; @@ -87,13 +88,13 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject ja return true; } - Object* bootstrap; - Object* system; - Object* class_loader; + mirror::Object* bootstrap; + mirror::Object* system; + mirror::Object* class_loader; }; ScopedObjectAccess soa(env); - Object* bootstrap = soa.Decode<Object*>(javaBootstrap); - Object* system = soa.Decode<Object*>(javaSystem); + mirror::Object* bootstrap = soa.Decode<mirror::Object*>(javaBootstrap); + mirror::Object* system = soa.Decode<mirror::Object*>(javaSystem); ClosestUserClassLoaderVisitor visitor(soa.Self(), bootstrap, system); visitor.WalkStack(); return soa.AddLocalReference<jobject>(visitor.class_loader); diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc index 59c9bef0f1..dded787214 100644 --- a/src/native/java_lang_Class.cc +++ b/src/native/java_lang_Class.cc @@ -15,10 +15,12 @@ */ #include "class_linker.h" -#include "class_loader.h" #include "jni_internal.h" #include "nth_caller_visitor.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/class_loader.h" +#include "mirror/object-inl.h" +#include "mirror/proxy.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" @@ -27,9 +29,9 @@ namespace art { -static Class* DecodeClass(const ScopedObjectAccess& soa, jobject java_class) +static mirror::Class* DecodeClass(const ScopedObjectAccess& soa, jobject java_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* c = soa.Decode<Class*>(java_class); + mirror::Class* c = soa.Decode<mirror::Class*>(java_class); DCHECK(c != NULL); DCHECK(c->IsClass()); // TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke . @@ -56,9 +58,9 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean } std::string descriptor(DotToDescriptor(name.c_str())); - ClassLoader* class_loader = soa.Decode<ClassLoader*>(javaLoader); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* c = class_linker->FindClass(descriptor.c_str(), class_loader); + mirror::Class* c = class_linker->FindClass(descriptor.c_str(), class_loader); if (c == NULL) { ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred()); env->ExceptionClear(); @@ -76,7 +78,7 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean static jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) { ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); + mirror::Class* c = DecodeClass(soa, javaClass); if (c->IsPrimitive() || c->IsArrayClass() || c->IsProxyClass()) { return 0; // primitive, array and proxy classes don't have class definitions } @@ -90,9 +92,9 @@ static jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) { static jobject Class_getDex(JNIEnv* env, jobject javaClass) { ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); + mirror::Class* c = DecodeClass(soa, javaClass); - DexCache* dex_cache = c->GetDexCache(); + mirror::DexCache* dex_cache = c->GetDexCache(); if (dex_cache == NULL) { return NULL; } @@ -105,13 +107,14 @@ static jobject Class_getDex(JNIEnv* env, jobject javaClass) { static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaThis); + mirror::Class* c = DecodeClass(soa, javaThis); return soa.AddLocalReference<jstring>(c->ComputeName()); } static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { ScopedObjectAccess soa(env); - SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(soa, javaThis)); + mirror::SynthesizedProxyClass* c = + down_cast<mirror::SynthesizedProxyClass*>(DecodeClass(soa, javaThis)); return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self())); } diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc index f3c295e6dc..75d5f70bef 100644 --- a/src/native/java_lang_Object.cc +++ b/src/native/java_lang_Object.cc @@ -15,7 +15,7 @@ */ #include "jni_internal.h" -#include "object.h" +#include "mirror/object.h" #include "scoped_thread_state_change.h" // TODO: better support for overloading. @@ -27,31 +27,31 @@ namespace art { static jobject Object_internalClone(JNIEnv* env, jobject java_this) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(java_this); + mirror::Object* o = soa.Decode<mirror::Object*>(java_this); return soa.AddLocalReference<jobject>(o->Clone(soa.Self())); } static void Object_notify(JNIEnv* env, jobject java_this) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(java_this); + mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Notify(); } static void Object_notifyAll(JNIEnv* env, jobject java_this) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(java_this); + mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->NotifyAll(); } static void Object_wait(JNIEnv* env, jobject java_this) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(java_this); + mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Wait(); } static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(java_this); + mirror::Object* o = soa.Decode<mirror::Object*>(java_this); o->Wait(ms, ns); } diff --git a/src/native/java_lang_Runtime.cc b/src/native/java_lang_Runtime.cc index d197b7340f..54ccddc9f0 100644 --- a/src/native/java_lang_Runtime.cc +++ b/src/native/java_lang_Runtime.cc @@ -18,10 +18,9 @@ #include <limits.h> #include <unistd.h> -#include "class_loader.h" #include "heap.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/class_loader.h" #include "runtime.h" #include "scoped_thread_state_change.h" #include "ScopedUtfChars.h" @@ -59,7 +58,7 @@ static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, job } } - ClassLoader* classLoader = soa.Decode<ClassLoader*>(javaLoader); + mirror::ClassLoader* classLoader = soa.Decode<mirror::ClassLoader*>(javaLoader); std::string detail; JavaVMExt* vm = Runtime::Current()->GetJavaVM(); bool success = vm->LoadNativeLibrary(filename.c_str(), classLoader, detail); diff --git a/src/native/java_lang_String.cc b/src/native/java_lang_String.cc index 8b7a69162d..44ab1ca8be 100644 --- a/src/native/java_lang_String.cc +++ b/src/native/java_lang_String.cc @@ -15,7 +15,7 @@ */ #include "jni_internal.h" -#include "object.h" +#include "mirror/string.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" @@ -28,7 +28,7 @@ static jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) { return -1; } else { ScopedObjectAccess soa(env); - return soa.Decode<String*>(javaThis)->CompareTo(soa.Decode<String*>(javaRhs)); + return soa.Decode<mirror::String*>(javaThis)->CompareTo(soa.Decode<mirror::String*>(javaRhs)); } } @@ -37,14 +37,14 @@ static jint String_fastIndexOf(JNIEnv* env, jobject java_this, jint ch, jint sta // This method does not handle supplementary characters. They're dealt with in managed code. DCHECK_LE(ch, 0xffff); - String* s = soa.Decode<String*>(java_this); + mirror::String* s = soa.Decode<mirror::String*>(java_this); return s->FastIndexOf(ch, start); } static jstring String_intern(JNIEnv* env, jobject javaThis) { ScopedObjectAccess soa(env); - String* s = soa.Decode<String*>(javaThis); - String* result = s->Intern(); + mirror::String* s = soa.Decode<mirror::String*>(javaThis); + mirror::String* result = s->Intern(); return soa.AddLocalReference<jstring>(result); } diff --git a/src/native/java_lang_System.cc b/src/native/java_lang_System.cc index d74c9dbc7f..54ee2e914e 100644 --- a/src/native/java_lang_System.cc +++ b/src/native/java_lang_System.cc @@ -14,8 +14,12 @@ * limitations under the License. */ +#include "gc/card_table-inl.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/array.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" #include "scoped_thread_state_change.h" /* @@ -101,7 +105,7 @@ static void move32(void* dst, const void* src, size_t n) { namespace art { -static void ThrowArrayStoreException_NotAnArray(const char* identifier, Object* array) +static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string actualType(PrettyTypeOf(array)); Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", @@ -122,8 +126,8 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, } // Make sure source and destination are both arrays. - Object* srcObject = soa.Decode<Object*>(javaSrc); - Object* dstObject = soa.Decode<Object*>(javaDst); + mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc); + mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst); if (!srcObject->IsArrayInstance()) { ThrowArrayStoreException_NotAnArray("source", srcObject); return; @@ -132,10 +136,10 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, ThrowArrayStoreException_NotAnArray("destination", dstObject); return; } - Array* srcArray = srcObject->AsArray(); - Array* dstArray = dstObject->AsArray(); - Class* srcComponentType = srcArray->GetClass()->GetComponentType(); - Class* dstComponentType = dstArray->GetClass()->GetComponentType(); + mirror::Array* srcArray = srcObject->AsArray(); + mirror::Array* dstArray = dstObject->AsArray(); + mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType(); + mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType(); // Bounds checking. if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) { @@ -182,7 +186,7 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, } // Neither class is primitive. Are the types trivially compatible? - const size_t width = sizeof(Object*); + const size_t width = sizeof(mirror::Object*); uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width)); const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width)); if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) { @@ -202,20 +206,21 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, // We already dealt with overlapping copies, so we don't need to cope with that case below. CHECK_NE(dstArray, srcArray); - Object* const * srcObjects = reinterpret_cast<Object* const *>(srcBytes + srcPos * width); - Object** dstObjects = reinterpret_cast<Object**>(dstBytes + dstPos * width); - Class* dstClass = dstArray->GetClass()->GetComponentType(); + mirror::Object* const * srcObjects = + reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width); + mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width); + mirror::Class* dstClass = dstArray->GetClass()->GetComponentType(); // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that // we know is assignable to the destination array's component type. - Class* lastAssignableElementClass = dstClass; + mirror::Class* lastAssignableElementClass = dstClass; - Object* o = NULL; + mirror::Object* o = NULL; int i = 0; for (; i < length; ++i) { o = srcObjects[i]; if (o != NULL) { - Class* oClass = o->GetClass(); + mirror::Class* oClass = o->GetClass(); if (lastAssignableElementClass == oClass) { dstObjects[i] = o; } else if (dstClass->IsAssignableFrom(oClass)) { @@ -243,7 +248,7 @@ static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) { ScopedObjectAccess soa(env); - Object* o = soa.Decode<Object*>(javaObject); + mirror::Object* o = soa.Decode<mirror::Object*>(javaObject); return static_cast<jint>(o->IdentityHashCode()); } diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc index 473369ef1a..ca4be9de9b 100644 --- a/src/native/java_lang_Thread.cc +++ b/src/native/java_lang_Thread.cc @@ -17,7 +17,7 @@ #include "debugger.h" #include "jni_internal.h" #include "monitor.h" -#include "object.h" +#include "mirror/object.h" #include "scoped_thread_state_change.h" #include "ScopedUtfChars.h" #include "thread.h" @@ -88,7 +88,7 @@ static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean ha static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject java_object) { ScopedObjectAccess soa(env); - Object* object = soa.Decode<Object*>(java_object); + mirror::Object* object = soa.Decode<mirror::Object*>(java_object); if (object == NULL) { Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "object == null"); return JNI_FALSE; @@ -111,7 +111,7 @@ static void Thread_nativeSetName(JNIEnv* env, jobject peer, jstring java_name) { ScopedUtfChars name(env, java_name); { ScopedObjectAccess soa(env); - if (soa.Decode<Object*>(peer) == soa.Self()->GetPeer()) { + if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) { soa.Self()->SetThreadName(name.c_str()); return; } @@ -149,7 +149,7 @@ static void Thread_nativeSetPriority(JNIEnv* env, jobject java_thread, jint new_ static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) { ScopedObjectAccess soa(env); - Object* lock = soa.Decode<Object*>(java_lock); + mirror::Object* lock = soa.Decode<mirror::Object*>(java_lock); Monitor::Wait(Thread::Current(), lock, ms, ns, true, kSleeping); } diff --git a/src/native/java_lang_VMClassLoader.cc b/src/native/java_lang_VMClassLoader.cc index 4b5c31c64b..02b7c25523 100644 --- a/src/native/java_lang_VMClassLoader.cc +++ b/src/native/java_lang_VMClassLoader.cc @@ -15,8 +15,8 @@ */ #include "class_linker.h" -#include "class_loader.h" #include "jni_internal.h" +#include "mirror/class_loader.h" #include "scoped_thread_state_change.h" #include "ScopedUtfChars.h" #include "zip_archive.h" @@ -25,14 +25,14 @@ namespace art { static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, jstring javaName) { ScopedObjectAccess soa(env); - ClassLoader* loader = soa.Decode<ClassLoader*>(javaLoader); + mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader); ScopedUtfChars name(env, javaName); if (name.c_str() == NULL) { return NULL; } std::string descriptor(DotToDescriptor(name.c_str())); - Class* c = Runtime::Current()->GetClassLinker()->LookupClass(descriptor.c_str(), loader); + mirror::Class* c = Runtime::Current()->GetClassLinker()->LookupClass(descriptor.c_str(), loader); if (c != NULL && c->IsResolved()) { return soa.AddLocalReference<jclass>(c); } else { diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc index 15aeed211d..2833cb09cb 100644 --- a/src/native/java_lang_reflect_Array.cc +++ b/src/native/java_lang_reflect_Array.cc @@ -16,7 +16,8 @@ #include "class_linker.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/class.h" +#include "mirror/object-inl.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "sirt_ref.h" @@ -26,21 +27,21 @@ namespace art { static jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) { ScopedObjectAccess soa(env); DCHECK(javaElementClass != NULL); - Class* element_class = soa.Decode<Class*>(javaElementClass); + mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); DCHECK(element_class->IsClass()); DCHECK(javaDimArray != NULL); - Object* dimensions_obj = soa.Decode<Object*>(javaDimArray); + mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray); DCHECK(dimensions_obj->IsArrayInstance()); DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor(), "[I"); - IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj); - Array* new_array = Array::CreateMultiArray(soa.Self(), element_class, dimensions_array); + mirror::IntArray* dimensions_array = down_cast<mirror::IntArray*>(dimensions_obj); + mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class, dimensions_array); return soa.AddLocalReference<jobject>(new_array); } static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length) { ScopedObjectAccess soa(env); DCHECK(javaElementClass != NULL); - Class* element_class = soa.Decode<Class*>(javaElementClass); + mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); if (UNLIKELY(length < 0)) { soa.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length); return NULL; @@ -49,13 +50,13 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl descriptor += ClassHelper(element_class).GetDescriptor(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader()); + mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader()); if (UNLIKELY(array_class == NULL)) { CHECK(soa.Self()->IsExceptionPending()); return NULL; } DCHECK(array_class->IsArrayClass()); - Array* new_array = Array::Alloc(soa.Self(), array_class, length); + mirror::Array* new_array = mirror::Array::Alloc(soa.Self(), array_class, length); return soa.AddLocalReference<jobject>(new_array); } diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc index ed0d1f127b..fb84dfd2bd 100644 --- a/src/native/java_lang_reflect_Constructor.cc +++ b/src/native/java_lang_reflect_Constructor.cc @@ -16,7 +16,10 @@ #include "class_linker.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" #include "object_utils.h" #include "reflection.h" #include "scoped_thread_state_change.h" @@ -32,8 +35,8 @@ namespace art { */ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) { ScopedObjectAccess soa(env); - AbstractMethod* m = soa.Decode<Object*>(javaMethod)->AsMethod(); - Class* c = m->GetDeclaringClass(); + mirror::AbstractMethod* m = soa.Decode<mirror::Object*>(javaMethod)->AsMethod(); + mirror::Class* c = m->GetDeclaringClass(); if (c->IsAbstract()) { soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Can't instantiate abstract class %s", PrettyDescriptor(c).c_str()); @@ -45,7 +48,7 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA return NULL; } - Object* receiver = c->AllocObject(soa.Self()); + mirror::Object* receiver = c->AllocObject(soa.Self()); if (receiver == NULL) { return NULL; } diff --git a/src/native/java_lang_reflect_Field.cc b/src/native/java_lang_reflect_Field.cc index fde8f94921..9a2671c167 100644 --- a/src/native/java_lang_reflect_Field.cc +++ b/src/native/java_lang_reflect_Field.cc @@ -15,15 +15,17 @@ */ #include "class_linker.h" +#include "class_linker-inl.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/field.h" +#include "mirror/field-inl.h" #include "object_utils.h" #include "reflection.h" #include "scoped_thread_state_change.h" namespace art { -static bool GetFieldValue(const ScopedObjectAccess& soa, Object* o, Field* f, +static bool GetFieldValue(const ScopedObjectAccess& soa, mirror::Object* o, mirror::Field* f, JValue& value, bool allow_references) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_EQ(value.GetJ(), 0LL); @@ -72,16 +74,16 @@ static bool GetFieldValue(const ScopedObjectAccess& soa, Object* o, Field* f, return false; } -static bool CheckReceiver(const ScopedObjectAccess& soa, jobject javaObj, Field* f, - Object*& o) +static bool CheckReceiver(const ScopedObjectAccess& soa, jobject javaObj, mirror::Field* f, + mirror::Object*& o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (f->IsStatic()) { o = f->GetDeclaringClass(); return true; } - o = soa.Decode<Object*>(javaObj); - Class* declaringClass = f->GetDeclaringClass(); + o = soa.Decode<mirror::Object*>(javaObj); + mirror::Class* declaringClass = f->GetDeclaringClass(); if (!VerifyObjectInClass(o, declaringClass)) { return false; } @@ -90,8 +92,8 @@ static bool CheckReceiver(const ScopedObjectAccess& soa, jobject javaObj, Field* static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { ScopedObjectAccess soa(env); - Field* f = soa.DecodeField(env->FromReflectedField(javaField)); - Object* o = NULL; + mirror::Field* f = soa.DecodeField(env->FromReflectedField(javaField)); + mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { return NULL; } @@ -107,8 +109,8 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char dst_descriptor) { ScopedObjectAccess soa(env); - Field* f = soa.DecodeField(env->FromReflectedField(javaField)); - Object* o = NULL; + mirror::Field* f = soa.DecodeField(env->FromReflectedField(javaField)); + mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { return JValue(); } @@ -121,7 +123,7 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, // Widen it if necessary (and possible). JValue wide_value; - Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor); + mirror::Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor); if (!ConvertPrimitiveValue(FieldHelper(f).GetTypeAsPrimitiveType(), dst_type->GetPrimitiveType(), field_value, wide_value)) { return JValue(); @@ -161,7 +163,8 @@ static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) { return GetPrimitiveField(env, javaField, javaObj, 'S').GetS(); } -static void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_references) +static void SetFieldValue(mirror::Object* o, mirror::Field* f, const JValue& new_value, + bool allow_references) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(), true, true)) { @@ -214,17 +217,17 @@ static void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool all static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) { ScopedObjectAccess soa(env); - Field* f = soa.DecodeField(env->FromReflectedField(javaField)); + mirror::Field* f = soa.DecodeField(env->FromReflectedField(javaField)); // Unbox the value, if necessary. - Object* boxed_value = soa.Decode<Object*>(javaValue); + mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue); JValue unboxed_value; if (!UnboxPrimitiveForField(boxed_value, FieldHelper(f).GetType(), unboxed_value, f)) { return; } // Check that the receiver is non-null and an instance of the field's declaring class. - Object* o = NULL; + mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { return; } @@ -235,8 +238,8 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor, const JValue& new_value) { ScopedObjectAccess soa(env); - Field* f = soa.DecodeField(env->FromReflectedField(javaField)); - Object* o = NULL; + mirror::Field* f = soa.DecodeField(env->FromReflectedField(javaField)); + mirror::Object* o = NULL; if (!CheckReceiver(soa, javaObj, f, o)) { return; } @@ -249,7 +252,7 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, c // Widen the value if necessary (and possible). JValue wide_value; - Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor); + mirror::Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor); if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(), new_value, wide_value)) { return; diff --git a/src/native/java_lang_reflect_Method.cc b/src/native/java_lang_reflect_Method.cc index b1eb6e07d7..14dc6a44ee 100644 --- a/src/native/java_lang_reflect_Method.cc +++ b/src/native/java_lang_reflect_Method.cc @@ -16,7 +16,12 @@ #include "class_linker.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/proxy.h" #include "object_utils.h" #include "reflection.h" #include "scoped_thread_state_change.h" @@ -30,10 +35,10 @@ static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiv static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { ScopedObjectAccess soa(env); - AbstractMethod* proxy_method = soa.Decode<Object*>(javaMethod)->AsMethod(); + mirror::AbstractMethod* proxy_method = soa.Decode<mirror::Object*>(javaMethod)->AsMethod(); CHECK(proxy_method->GetDeclaringClass()->IsProxyClass()); - SynthesizedProxyClass* proxy_class = - down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass()); + mirror::SynthesizedProxyClass* proxy_class = + down_cast<mirror::SynthesizedProxyClass*>(proxy_method->GetDeclaringClass()); int throws_index = -1; size_t num_virt_methods = proxy_class->NumVirtualMethods(); for (size_t i = 0; i < num_virt_methods; i++) { @@ -43,13 +48,13 @@ static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { } } CHECK_NE(throws_index, -1); - ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); + mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); return soa.AddLocalReference<jobject>(declared_exceptions->Clone(soa.Self())); } static jobject Method_findOverriddenMethodNative(JNIEnv* env, jobject javaMethod) { ScopedObjectAccess soa(env); - AbstractMethod* method = soa.Decode<Object*>(javaMethod)->AsMethod(); + mirror::AbstractMethod* method = soa.Decode<mirror::Object*>(javaMethod)->AsMethod(); return soa.AddLocalReference<jobject>(method->FindOverriddenMethod()); } diff --git a/src/native/java_lang_reflect_Proxy.cc b/src/native/java_lang_reflect_Proxy.cc index a56726824a..547ce7b38d 100644 --- a/src/native/java_lang_reflect_Proxy.cc +++ b/src/native/java_lang_reflect_Proxy.cc @@ -15,22 +15,28 @@ */ #include "class_linker.h" -#include "class_loader.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/class_loader.h" +#include "mirror/object_array.h" +#include "mirror/string.h" #include "scoped_thread_state_change.h" namespace art { -static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring javaName, jobjectArray javaInterfaces, jobject javaLoader, jobjectArray javaMethods, jobjectArray javaThrows) { +static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring javaName, + jobjectArray javaInterfaces, jobject javaLoader, + jobjectArray javaMethods, jobjectArray javaThrows) { ScopedObjectAccess soa(env); - String* name = soa.Decode<String*>(javaName); - ObjectArray<Class>* interfaces = soa.Decode<ObjectArray<Class>*>(javaInterfaces); - ClassLoader* loader = soa.Decode<ClassLoader*>(javaLoader); - ObjectArray<AbstractMethod>* methods = soa.Decode<ObjectArray<AbstractMethod>*>(javaMethods); - ObjectArray<ObjectArray<Class> >* throws = soa.Decode<ObjectArray<ObjectArray<Class> >*>(javaThrows); + mirror::String* name = soa.Decode<mirror::String*>(javaName); + mirror::ObjectArray<mirror::Class>* interfaces = + soa.Decode<mirror::ObjectArray<mirror::Class>*>(javaInterfaces); + mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader); + mirror::ObjectArray<mirror::AbstractMethod>* methods = + soa.Decode<mirror::ObjectArray<mirror::AbstractMethod>*>(javaMethods); + mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >* throws = + soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(javaThrows); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* result = class_linker->CreateProxyClass(name, interfaces, loader, methods, throws); + mirror::Class* result = class_linker->CreateProxyClass(name, interfaces, loader, methods, throws); return soa.AddLocalReference<jclass>(result); } diff --git a/src/native/sun_misc_Unsafe.cc b/src/native/sun_misc_Unsafe.cc index cb06a0b944..abb0d5cd5c 100644 --- a/src/native/sun_misc_Unsafe.cc +++ b/src/native/sun_misc_Unsafe.cc @@ -14,15 +14,18 @@ * limitations under the License. */ +#include "atomic.h" +#include "gc/card_table-inl.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/object.h" +#include "mirror/object-inl.h" #include "scoped_thread_state_change.h" namespace art { static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr); // Note: android_atomic_release_cas() returns 0 on success, not failure. @@ -32,7 +35,7 @@ static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr); // Note: android_atomic_cmpxchg() returns 0 on success, not failure. @@ -42,9 +45,9 @@ static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* expectedValue = soa.Decode<Object*>(javaExpectedValue); - Object* newValue = soa.Decode<Object*>(javaNewValue); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue); + mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); byte* raw_addr = reinterpret_cast<byte*>(obj) + offset; int32_t* address = reinterpret_cast<int32_t*>(raw_addr); // Note: android_atomic_cmpxchg() returns 0 on success, not failure. @@ -58,98 +61,98 @@ static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaOb static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField32(MemberOffset(offset), false); } static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField32(MemberOffset(offset), true); } static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField32(MemberOffset(offset), newValue, false); } static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField32(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); ANDROID_MEMBAR_STORE(); obj->SetField32(MemberOffset(offset), newValue, false); } static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField64(MemberOffset(offset), false); } static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); return obj->GetField64(MemberOffset(offset), true); } static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField64(MemberOffset(offset), newValue, false); } static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); obj->SetField64(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); ANDROID_MEMBAR_STORE(); obj->SetField64(MemberOffset(offset), newValue, false); } static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), true); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true); return soa.AddLocalReference<jobject>(value); } static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), false); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false); return soa.AddLocalReference<jobject>(value); } static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* newValue = soa.Decode<Object*>(javaNewValue); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); obj->SetFieldObject(MemberOffset(offset), newValue, false); } static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* newValue = soa.Decode<Object*>(javaNewValue); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); obj->SetFieldObject(MemberOffset(offset), newValue, true); } static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) { ScopedObjectAccess soa(env); - Object* obj = soa.Decode<Object*>(javaObj); - Object* newValue = soa.Decode<Object*>(javaNewValue); + mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj); + mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); ANDROID_MEMBAR_STORE(); obj->SetFieldObject(MemberOffset(offset), newValue, false); } diff --git a/src/nth_caller_visitor.h b/src/nth_caller_visitor.h index efed16316d..7d9feb622e 100644 --- a/src/nth_caller_visitor.h +++ b/src/nth_caller_visitor.h @@ -17,10 +17,11 @@ #ifndef ART_SRC_NTH_CALLER_VISITOR_H_ #define ART_SRC_NTH_CALLER_VISITOR_H_ -#include "object.h" -#include "thread.h" +#include "mirror/abstract_method.h" +#include "stack.h" namespace art { +class Thread; // Walks up the stack 'n' callers, when used with Thread::WalkStack. struct NthCallerVisitor : public StackVisitor { @@ -38,7 +39,7 @@ struct NthCallerVisitor : public StackVisitor { size_t n; size_t count; - AbstractMethod* caller; + mirror::AbstractMethod* caller; }; } // namespace art diff --git a/src/oat.cc b/src/oat.cc index 8032a11c91..b0a9aef4f0 100644 --- a/src/oat.cc +++ b/src/oat.cc @@ -15,6 +15,7 @@ */ #include "oat.h" +#include "utils.h" #include <zlib.h> diff --git a/src/oat/jni/arm/jni_internal_arm.cc b/src/oat/jni/arm/jni_internal_arm.cc index 36d436f9b5..4af4f528f5 100644 --- a/src/oat/jni/arm/jni_internal_arm.cc +++ b/src/oat/jni/arm/jni_internal_arm.cc @@ -23,9 +23,9 @@ #include "compiler.h" #include "invoke_arg_array_builder.h" #include "jni_internal.h" +#include "mirror/abstract_method.h" #include "oat/utils/arm/assembler_arm.h" #include "oat/utils/assembler.h" -#include "object.h" namespace art { namespace arm { @@ -131,7 +131,7 @@ CompiledInvokeStub* CreateInvokeStub(bool is_static, const char* shorty, uint32_ } // Load the code pointer we are about to call. - __ LoadFromOffset(kLoadWord, IP, R0, AbstractMethod::GetCodeOffset().Int32Value()); + __ LoadFromOffset(kLoadWord, IP, R0, mirror::AbstractMethod::GetCodeOffset().Int32Value()); // Do the call. __ blx(IP); diff --git a/src/oat/jni/jni_compiler.cc b/src/oat/jni/jni_compiler.cc index ac35143e73..c0298de023 100644 --- a/src/oat/jni/jni_compiler.cc +++ b/src/oat/jni/jni_compiler.cc @@ -118,7 +118,7 @@ CompiledMethod* ArtJniCompileMethodInternal(Compiler& compiler, // Check sirt offset is within frame CHECK_LT(sirt_offset.Uint32Value(), frame_size); __ LoadRef(main_jni_conv->InterproceduralScratchRegister(), - mr_conv->MethodRegister(), AbstractMethod::DeclaringClassOffset()); + mr_conv->MethodRegister(), mirror::AbstractMethod::DeclaringClassOffset()); __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false); __ StoreRef(sirt_offset, main_jni_conv->InterproceduralScratchRegister()); main_jni_conv->Next(); // in SIRT so move to next argument @@ -269,7 +269,7 @@ CompiledMethod* ArtJniCompileMethodInternal(Compiler& compiler, } // 9. Plant call to native code associated with method. - __ Call(main_jni_conv->MethodStackOffset(), AbstractMethod::NativeMethodOffset(), + __ Call(main_jni_conv->MethodStackOffset(), mirror::AbstractMethod::NativeMethodOffset(), mr_conv->InterproceduralScratchRegister()); // 10. Fix differences in result widths. diff --git a/src/oat/jni/mips/jni_internal_mips.cc b/src/oat/jni/mips/jni_internal_mips.cc index 4cfeaa9267..69e86c357c 100644 --- a/src/oat/jni/mips/jni_internal_mips.cc +++ b/src/oat/jni/mips/jni_internal_mips.cc @@ -23,9 +23,9 @@ #include "compiler.h" #include "invoke_arg_array_builder.h" #include "jni_internal.h" +#include "mirror/abstract_method.h" #include "oat/utils/mips/assembler_mips.h" #include "oat/utils/assembler.h" -#include "object.h" namespace art { namespace mips { @@ -128,7 +128,7 @@ CompiledInvokeStub* CreateInvokeStub(bool is_static, const char* shorty, uint32_ } // Load the code pointer we are about to call. - __ LoadFromOffset(kLoadWord, T9, A0, AbstractMethod::GetCodeOffset().Int32Value()); + __ LoadFromOffset(kLoadWord, T9, A0, mirror::AbstractMethod::GetCodeOffset().Int32Value()); // Do the call. __ Jalr(T9); diff --git a/src/oat/jni/x86/jni_internal_x86.cc b/src/oat/jni/x86/jni_internal_x86.cc index 9d41edaba7..fabd283a3d 100644 --- a/src/oat/jni/x86/jni_internal_x86.cc +++ b/src/oat/jni/x86/jni_internal_x86.cc @@ -18,9 +18,9 @@ #include "compiler.h" #include "invoke_arg_array_builder.h" #include "jni_internal.h" +#include "mirror/abstract_method.h" #include "oat/utils/assembler.h" #include "oat/utils/x86/assembler_x86.h" -#include "object.h" namespace art { namespace x86 { @@ -127,7 +127,7 @@ CompiledInvokeStub* CreateInvokeStub(bool is_static, const char* shorty, uint32_ } } - __ call(Address(EAX, AbstractMethod::GetCodeOffset())); // Call code off of method + __ call(Address(EAX, mirror::AbstractMethod::GetCodeOffset())); // Call code off of method // Pop arguments up to EBX and the return address. __ addl(ESP, Immediate(frame_size + pad_size - (2 * kPointerSize))); diff --git a/src/oat/runtime/argument_visitor.h b/src/oat/runtime/argument_visitor.h index 06256caec5..df7bc122fd 100644 --- a/src/oat/runtime/argument_visitor.h +++ b/src/oat/runtime/argument_visitor.h @@ -46,7 +46,7 @@ class ArgumentVisitor { #define STACK_ARG_SKIP 0 #endif - ArgumentVisitor(MethodHelper& caller_mh, AbstractMethod** sp) + ArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : caller_mh_(caller_mh), args_in_regs_(ComputeArgsInRegs(caller_mh)), diff --git a/src/oat/runtime/arm/context_arm.cc b/src/oat/runtime/arm/context_arm.cc index 5bd4b3d02e..2e7605064e 100644 --- a/src/oat/runtime/arm/context_arm.cc +++ b/src/oat/runtime/arm/context_arm.cc @@ -16,7 +16,9 @@ #include "context_arm.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "stack.h" +#include "thread.h" namespace art { namespace arm { @@ -38,7 +40,7 @@ void ArmContext::Reset() { } void ArmContext::FillCalleeSaves(const StackVisitor& fr) { - AbstractMethod* method = fr.GetMethod(); + mirror::AbstractMethod* method = fr.GetMethod(); uint32_t core_spills = method->GetCoreSpillMask(); uint32_t fp_core_spills = method->GetFpSpillMask(); size_t spill_count = __builtin_popcount(core_spills); diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc index 15218b8013..c43b7e279e 100644 --- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc +++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc @@ -28,12 +28,13 @@ extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t); extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t); // Cast entrypoints. -extern "C" uint32_t artIsAssignableFromCode(const Class* klass, const Class* ref_class); +extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass, + const mirror::Class* ref_class); extern "C" void art_can_put_array_element_from_code(void*, void*); extern "C" void art_check_cast_from_code(void*, void*); // Debug entrypoints. -extern void DebugMe(AbstractMethod* method, uint32_t info); +extern void DebugMe(mirror::AbstractMethod* method, uint32_t info); extern "C" void art_update_debugger(void*, void*, int32_t, void*); // DexCache entrypoints. @@ -69,11 +70,11 @@ extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self); extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self); extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked, Thread* self); -extern Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, - Thread* self); -extern Object* JniMethodEndWithReferenceSynchronized(jobject result, - uint32_t saved_local_ref_cookie, - jobject locked, Thread* self); +extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, + Thread* self); +extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, + uint32_t saved_local_ref_cookie, + jobject locked, Thread* self); // Lock entrypoints. extern "C" void art_lock_object_from_code(void*); @@ -113,7 +114,8 @@ extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t); extern "C" int32_t art_string_compareto(void*, void*); // Invoke entrypoints. -const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod*, AbstractMethod**, Thread*, +const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*, + mirror::AbstractMethod**, Thread*, Runtime::TrampolineType); extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*); extern "C" void art_invoke_interface_trampoline(uint32_t, void*); @@ -127,7 +129,8 @@ extern void CheckSuspendFromCode(Thread* thread); extern "C" void art_test_suspend(); // Throw entrypoints. -extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp); +extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, + mirror::AbstractMethod** sp); extern "C" void art_deliver_exception_from_code(void*); extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_throw_div_zero_from_code(); diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc index 4099ddbc98..90dfffc27f 100644 --- a/src/oat/runtime/arm/stub_arm.cc +++ b/src/oat/runtime/arm/stub_arm.cc @@ -15,10 +15,10 @@ */ #include "jni_internal.h" +#include "mirror/array.h" #include "oat/utils/arm/assembler_arm.h" #include "oat/runtime/oat_support_entrypoints.h" #include "oat/runtime/stub.h" -#include "object.h" #include "stack_indirect_reference_table.h" #include "sirt_ref.h" @@ -27,7 +27,7 @@ namespace art { namespace arm { -ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) { +mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) { UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); #if !defined(ART_USE_LLVM_COMPILER) // | Out args | @@ -83,7 +83,7 @@ ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -91,9 +91,9 @@ ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) { return resolution_trampoline.get(); } -typedef void (*ThrowAme)(AbstractMethod*, Thread*); +typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); -ByteArray* CreateAbstractMethodErrorStub() { +mirror::ByteArray* CreateAbstractMethodErrorStub() { UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); #if !defined(ART_USE_LLVM_COMPILER) // Save callee saves and ready frame for exception delivery @@ -130,7 +130,7 @@ ByteArray* CreateAbstractMethodErrorStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -138,7 +138,7 @@ ByteArray* CreateAbstractMethodErrorStub() { return abstract_stub.get(); } -ByteArray* CreateJniDlsymLookupStub() { +mirror::ByteArray* CreateJniDlsymLookupStub() { UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); // Build frame and save argument registers and LR. RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR); @@ -159,7 +159,7 @@ ByteArray* CreateJniDlsymLookupStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oat/runtime/callee_save_frame.h b/src/oat/runtime/callee_save_frame.h index fe66b91f64..08cf9d86be 100644 --- a/src/oat/runtime/callee_save_frame.h +++ b/src/oat/runtime/callee_save_frame.h @@ -21,11 +21,12 @@ #include "thread.h" namespace art { - +namespace mirror { class AbstractMethod; +} // namespace mirror // Place a special frame at the TOS that will save the callee saves for the given type. -static void FinishCalleeSaveFrameSetup(Thread* self, AbstractMethod** sp, +static void FinishCalleeSaveFrameSetup(Thread* self, mirror::AbstractMethod** sp, Runtime::CalleeSaveType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Be aware the store below may well stomp on an incoming argument. diff --git a/src/oat/runtime/mips/context_mips.cc b/src/oat/runtime/mips/context_mips.cc index 0c2f9159d0..36eb5b9d9a 100644 --- a/src/oat/runtime/mips/context_mips.cc +++ b/src/oat/runtime/mips/context_mips.cc @@ -16,7 +16,7 @@ #include "context_mips.h" -#include "object.h" +#include "mirror/object.h" namespace art { namespace mips { diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc index 4cb8813800..fda9941de8 100644 --- a/src/oat/runtime/mips/stub_mips.cc +++ b/src/oat/runtime/mips/stub_mips.cc @@ -15,10 +15,10 @@ */ #include "jni_internal.h" +#include "mirror/array.h" #include "oat/runtime/oat_support_entrypoints.h" #include "oat/runtime/stub.h" #include "oat/utils/mips/assembler_mips.h" -#include "object.h" #include "stack_indirect_reference_table.h" #include "sirt_ref.h" @@ -27,7 +27,7 @@ namespace art { namespace mips { -ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) { +mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) { UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); #if !defined(ART_USE_LLVM_COMPILER) // | Out args | @@ -113,7 +113,7 @@ ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -121,9 +121,9 @@ ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) { return resolution_trampoline.get(); } -typedef void (*ThrowAme)(AbstractMethod*, Thread*); +typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); -ByteArray* CreateAbstractMethodErrorStub() { +mirror::ByteArray* CreateAbstractMethodErrorStub() { UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); #if !defined(ART_USE_LLVM_COMPILER) // Save callee saves and ready frame for exception delivery @@ -161,7 +161,7 @@ ByteArray* CreateAbstractMethodErrorStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -169,7 +169,7 @@ ByteArray* CreateAbstractMethodErrorStub() { return abstract_stub.get(); } -ByteArray* CreateJniDlsymLookupStub() { +mirror::ByteArray* CreateJniDlsymLookupStub() { UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); // Build frame and save argument registers and RA. @@ -203,7 +203,7 @@ ByteArray* CreateJniDlsymLookupStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h index 113a56c08b..a08a584660 100644 --- a/src/oat/runtime/oat_support_entrypoints.h +++ b/src/oat/runtime/oat_support_entrypoints.h @@ -24,10 +24,12 @@ static_cast<uintptr_t>(OFFSETOF_MEMBER(EntryPoints, x))) namespace art { - +namespace mirror { +class AbstractMethod; class Class; +class Object; +} // namespace mirror class DvmDex; -class AbstractMethod; class Thread; struct PACKED(4) EntryPoints { @@ -40,12 +42,12 @@ struct PACKED(4) EntryPoints { void* (*pCheckAndAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t); // Cast - uint32_t (*pInstanceofNonTrivialFromCode)(const Class*, const Class*); + uint32_t (*pInstanceofNonTrivialFromCode)(const mirror::Class*, const mirror::Class*); void (*pCanPutArrayElementFromCode)(void*, void*); void (*pCheckCastFromCode)(void*, void*); // Debug - void (*pDebugMe)(AbstractMethod*, uint32_t); + void (*pDebugMe)(mirror::AbstractMethod*, uint32_t); void (*pUpdateDebuggerFromCode)(void*, void*, int32_t, void*); // DexCache @@ -77,8 +79,8 @@ struct PACKED(4) EntryPoints { uint32_t (*pJniMethodStartSynchronized)(jobject to_lock, Thread* self); void (*pJniMethodEnd)(uint32_t cookie, Thread* self); void (*pJniMethodEndSynchronized)(uint32_t cookie, jobject locked, Thread* self); - Object* (*pJniMethodEndWithReference)(jobject result, uint32_t cookie, Thread* self); - Object* (*pJniMethodEndWithReferenceSynchronized)(jobject result, uint32_t cookie, + mirror::Object* (*pJniMethodEndWithReference)(jobject result, uint32_t cookie, Thread* self); + mirror::Object* (*pJniMethodEndWithReferenceSynchronized)(jobject result, uint32_t cookie, jobject locked, Thread* self); // Locks @@ -114,7 +116,8 @@ struct PACKED(4) EntryPoints { void* (*pMemcpy)(void*, const void*, size_t); // Invocation - const void* (*pUnresolvedDirectMethodTrampolineFromCode)(AbstractMethod*, AbstractMethod**, Thread*, + const void* (*pUnresolvedDirectMethodTrampolineFromCode)(mirror::AbstractMethod*, + mirror::AbstractMethod**, Thread*, Runtime::TrampolineType); void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*); void (*pInvokeInterfaceTrampoline)(uint32_t, void*); @@ -129,7 +132,8 @@ struct PACKED(4) EntryPoints { // Throws void (*pDeliverException)(void*); - void (*pThrowAbstractMethodErrorFromCode)(AbstractMethod* m, Thread* thread, AbstractMethod** sp); + void (*pThrowAbstractMethodErrorFromCode)(mirror::AbstractMethod* m, Thread* thread, + mirror::AbstractMethod** sp); void (*pThrowArrayBoundsFromCode)(int32_t, int32_t); void (*pThrowDivZeroFromCode)(); void (*pThrowNoSuchMethodFromCode)(int32_t); diff --git a/src/oat/runtime/stub.h b/src/oat/runtime/stub.h index 0e5f0dd67d..2679793332 100644 --- a/src/oat/runtime/stub.h +++ b/src/oat/runtime/stub.h @@ -20,31 +20,35 @@ #include "runtime.h" namespace art { +namespace mirror { +template<class T> class PrimitiveArray; +typedef PrimitiveArray<int8_t> ByteArray; +} // namespace mirror namespace arm { - ByteArray* CreateAbstractMethodErrorStub() + mirror::ByteArray* CreateAbstractMethodErrorStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) + mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* CreateJniDlsymLookupStub() + mirror::ByteArray* CreateJniDlsymLookupStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } namespace mips { - ByteArray* CreateAbstractMethodErrorStub() + mirror::ByteArray* CreateAbstractMethodErrorStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) + mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* CreateJniDlsymLookupStub() + mirror::ByteArray* CreateJniDlsymLookupStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } namespace x86 { - ByteArray* CreateAbstractMethodErrorStub() + mirror::ByteArray* CreateAbstractMethodErrorStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) + mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ByteArray* CreateJniDlsymLookupStub() + mirror::ByteArray* CreateJniDlsymLookupStub() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } diff --git a/src/oat/runtime/support_alloc.cc b/src/oat/runtime/support_alloc.cc index fb70285073..5e3af78c94 100644 --- a/src/oat/runtime/support_alloc.cc +++ b/src/oat/runtime/support_alloc.cc @@ -15,51 +15,61 @@ */ #include "callee_save_frame.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "runtime_support.h" namespace art { -extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, AbstractMethod* method, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Object* artAllocObjectFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return AllocObjectFromCode(type_idx, method, self, false); } -extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, AbstractMethod* method, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, + mirror::AbstractMethod* method, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return AllocObjectFromCode(type_idx, method, self, true); } -extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Array* artAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + int32_t component_count, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return AllocArrayFromCode(type_idx, method, component_count, self, false); } -extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, AbstractMethod* method, - int32_t component_count, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, + mirror::AbstractMethod* method, + int32_t component_count, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return AllocArrayFromCode(type_idx, method, component_count, self, true); } -extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, - int32_t component_count, Thread* self, - AbstractMethod** sp) +extern "C" mirror::Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, + mirror::AbstractMethod* method, + int32_t component_count, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, false); } -extern "C" Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, - AbstractMethod* method, - int32_t component_count, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, + mirror::AbstractMethod* method, + int32_t component_count, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, true); diff --git a/src/oat/runtime/support_cast.cc b/src/oat/runtime/support_cast.cc index 0db743b16c..71a37efe2c 100644 --- a/src/oat/runtime/support_cast.cc +++ b/src/oat/runtime/support_cast.cc @@ -15,12 +15,15 @@ */ #include "callee_save_frame.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" #include "runtime_support.h" namespace art { // Assignable test for code, won't throw. Null and equality tests already performed -extern "C" uint32_t artIsAssignableFromCode(const Class* klass, const Class* ref_class) +extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass, + const mirror::Class* ref_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(klass != NULL); DCHECK(ref_class != NULL); @@ -28,8 +31,8 @@ extern "C" uint32_t artIsAssignableFromCode(const Class* klass, const Class* ref } // Check whether it is safe to cast one class to the other, throw exception and return -1 on failure -extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, - AbstractMethod** sp) +extern "C" int artCheckCastFromCode(const mirror::Class* a, const mirror::Class* b, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(a->IsClass()) << PrettyClass(a); DCHECK(b->IsClass()) << PrettyClass(b); @@ -47,13 +50,14 @@ extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self // Tests whether 'element' can be assigned into an array of type 'array_class'. // Returns 0 on success and -1 if an exception is pending. -extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class, - Thread* self, AbstractMethod** sp) +extern "C" int artCanPutArrayElementFromCode(const mirror::Object* element, + const mirror::Class* array_class, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(array_class != NULL); // element can't be NULL as we catch this is screened in runtime_support - Class* element_class = element->GetClass(); - Class* component_type = array_class->GetComponentType(); + mirror::Class* element_class = element->GetClass(); + mirror::Class* component_type = array_class->GetComponentType(); if (LIKELY(component_type->IsAssignableFrom(element_class))) { return 0; // Success } else { diff --git a/src/oat/runtime/support_debug.cc b/src/oat/runtime/support_debug.cc index e2ca493c05..0d67dd92c3 100644 --- a/src/oat/runtime/support_debug.cc +++ b/src/oat/runtime/support_debug.cc @@ -25,14 +25,14 @@ namespace art { * method entry and offset 0 within the method, we'll use an offset of -1 * to denote method entry. */ -extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, AbstractMethod** sp) +extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs); Dbg::UpdateDebugger(dex_pc, self); } // Temporary debugging hook for compiler. -extern void DebugMe(AbstractMethod* method, uint32_t info) +extern void DebugMe(mirror::AbstractMethod* method, uint32_t info) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { LOG(INFO) << "DebugMe"; if (method != NULL) { diff --git a/src/oat/runtime/support_deoptimize.cc b/src/oat/runtime/support_deoptimize.cc index 75e671febd..0d88c520d2 100644 --- a/src/oat/runtime/support_deoptimize.cc +++ b/src/oat/runtime/support_deoptimize.cc @@ -16,7 +16,8 @@ #include "callee_save_frame.h" #include "interpreter/interpreter.h" -#include "object.h" // for JValue +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "stack.h" #include "thread.h" @@ -24,7 +25,7 @@ namespace art { -extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, AbstractMethod** sp) +extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); // Return value may hold Object* so avoid suspension. @@ -36,7 +37,7 @@ extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, AbstractMethod** : StackVisitor(thread, context), shadow_frame_(NULL), runtime_frames_(0) { } virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m->IsRuntimeMethod()) { if (runtime_frames_ == 0) { runtime_frames_++; @@ -84,7 +85,7 @@ extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, AbstractMethod** } -extern "C" JValue artEnterInterpreterFromDeoptimize(Thread* self, AbstractMethod** sp) +extern "C" JValue artEnterInterpreterFromDeoptimize(Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); JValue return_value; diff --git a/src/oat/runtime/support_dexcache.cc b/src/oat/runtime/support_dexcache.cc index 10c7930f3c..da15917ed8 100644 --- a/src/oat/runtime/support_dexcache.cc +++ b/src/oat/runtime/support_dexcache.cc @@ -15,12 +15,17 @@ */ #include "callee_save_frame.h" +#include "class_linker-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "runtime_support.h" namespace art { -extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const AbstractMethod* referrer, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, + const mirror::AbstractMethod* referrer, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called to ensure static storage base is initialized for direct static field reads and writes. // A class may be accessing another class' fields when it doesn't have access, as access has been @@ -29,18 +34,19 @@ extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Ab return ResolveVerifyAndClinit(type_idx, referrer, self, true, false); } -extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const AbstractMethod* referrer, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, + const mirror::AbstractMethod* referrer, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when method->dex_cache_resolved_types_[] misses. FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return ResolveVerifyAndClinit(type_idx, referrer, self, false, false); } -extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, - const AbstractMethod* referrer, - Thread* self, - AbstractMethod** sp) +extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, + const mirror::AbstractMethod* referrer, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when caller isn't guaranteed to have access to a type and the dex cache may be // unpopulated. @@ -48,8 +54,9 @@ extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, return ResolveVerifyAndClinit(type_idx, referrer, self, false, true); } -extern "C" String* artResolveStringFromCode(AbstractMethod* referrer, int32_t string_idx, - Thread* self, AbstractMethod** sp) +extern "C" mirror::String* artResolveStringFromCode(mirror::AbstractMethod* referrer, + int32_t string_idx, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); return ResolveStringFromCode(referrer, string_idx); diff --git a/src/oat/runtime/support_field.cc b/src/oat/runtime/support_field.cc index 93362473c1..a564fa95df 100644 --- a/src/oat/runtime/support_field.cc +++ b/src/oat/runtime/support_field.cc @@ -15,16 +15,20 @@ */ #include "callee_save_frame.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" #include "runtime_support.h" #include <stdint.h> namespace art { -extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer, - Thread* self, AbstractMethod** sp) +extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, + const mirror::AbstractMethod* referrer, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t)); if (LIKELY(field != NULL)) { return field->Get32(field->GetDeclaringClass()); } @@ -36,10 +40,11 @@ extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const AbstractMet return 0; // Will throw exception by checking with Thread::Current } -extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer, - Thread* self, AbstractMethod** sp) +extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, + const mirror::AbstractMethod* referrer, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t)); if (LIKELY(field != NULL)) { return field->Get64(field->GetDeclaringClass()); } @@ -51,26 +56,28 @@ extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const AbstractMet return 0; // Will throw exception by checking with Thread::Current } -extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const AbstractMethod* referrer, - Thread* self, AbstractMethod** sp) +extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx, + const mirror::AbstractMethod* referrer, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, + sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(field->GetDeclaringClass()); } FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - field = FindFieldFromCode(field_idx, referrer, self, StaticObjectRead, sizeof(Object*)); + field = FindFieldFromCode(field_idx, referrer, self, StaticObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { return field->GetObj(field->GetDeclaringClass()); } return NULL; // Will throw exception by checking with Thread::Current } -extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t)); if (LIKELY(field != NULL && obj != NULL)) { return field->Get32(obj); } @@ -86,11 +93,11 @@ extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj, return 0; // Will throw exception by checking with Thread::Current } -extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t)); if (LIKELY(field != NULL && obj != NULL)) { return field->Get64(obj); } @@ -106,16 +113,17 @@ extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj, return 0; // Will throw exception by checking with Thread::Current } -extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj, + const mirror::AbstractMethod* referrer, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL && obj != NULL)) { return field->GetObj(obj); } FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectRead, sizeof(Object*)); + field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectRead, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { if (UNLIKELY(obj == NULL)) { ThrowNullPointerExceptionForFieldAccess(field, true); @@ -127,10 +135,10 @@ extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj, } extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t)); if (LIKELY(field != NULL)) { field->Set32(field->GetDeclaringClass(), new_value); return 0; // success @@ -144,10 +152,10 @@ extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value, return -1; // failure } -extern "C" int artSet64StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer, - uint64_t new_value, Thread* self, AbstractMethod** sp) +extern "C" int artSet64StaticFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer, + uint64_t new_value, Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t)); if (LIKELY(field != NULL)) { field->Set64(field->GetDeclaringClass(), new_value); return 0; // success @@ -161,11 +169,12 @@ extern "C" int artSet64StaticFromCode(uint32_t field_idx, const AbstractMethod* return -1; // failure } -extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value, + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, + sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { if (LIKELY(!FieldHelper(field).IsPrimitiveType())) { field->SetObj(field->GetDeclaringClass(), new_value); @@ -173,7 +182,7 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value, } } FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - field = FindFieldFromCode(field_idx, referrer, self, StaticObjectWrite, sizeof(Object*)); + field = FindFieldFromCode(field_idx, referrer, self, StaticObjectWrite, sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { field->SetObj(field->GetDeclaringClass(), new_value); return 0; // success @@ -181,11 +190,11 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value, return -1; // failure } -extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value, + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t)); if (LIKELY(field != NULL && obj != NULL)) { field->Set32(obj, new_value); return 0; // success @@ -203,12 +212,14 @@ extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_ return -1; // failure } -extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_t new_value, - Thread* self, AbstractMethod** sp) +extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint64_t new_value, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly); - AbstractMethod* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(AbstractMethod*)]; - Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t)); + mirror::AbstractMethod* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly); + mirror::AbstractMethod* referrer = + sp[callee_save->GetFrameSizeInBytes() / sizeof(mirror::AbstractMethod*)]; + mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, + sizeof(int64_t)); if (LIKELY(field != NULL && obj != NULL)) { field->Set64(obj, new_value); return 0; // success @@ -227,17 +238,20 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_ return -1; // failure } -extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value, - const AbstractMethod* referrer, Thread* self, - AbstractMethod** sp) +extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj, + mirror::Object* new_value, + const mirror::AbstractMethod* referrer, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*)); + mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, + sizeof(mirror::Object*)); if (LIKELY(field != NULL && obj != NULL)) { field->SetObj(obj, new_value); return 0; // success } FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectWrite, sizeof(Object*)); + field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectWrite, + sizeof(mirror::Object*)); if (LIKELY(field != NULL)) { if (UNLIKELY(obj == NULL)) { ThrowNullPointerExceptionForFieldAccess(field, false); diff --git a/src/oat/runtime/support_fillarray.cc b/src/oat/runtime/support_fillarray.cc index 9c6231f1fe..73f832aa35 100644 --- a/src/oat/runtime/support_fillarray.cc +++ b/src/oat/runtime/support_fillarray.cc @@ -16,7 +16,8 @@ #include "callee_save_frame.h" #include "dex_instruction.h" -#include "object.h" +#include "mirror/array.h" +#include "mirror/object-inl.h" namespace art { @@ -35,9 +36,9 @@ namespace art { * ubyte data[size*width] table of data values (may contain a single-byte * padding at the end) */ -extern "C" int artHandleFillArrayDataFromCode(Array* array, +extern "C" int artHandleFillArrayDataFromCode(mirror::Array* array, const Instruction::ArrayDataPayload* payload, - Thread* self, AbstractMethod** sp) + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature)); diff --git a/src/oat/runtime/support_instrumentation.cc b/src/oat/runtime/support_instrumentation.cc index 73e43717a3..f65717aa73 100644 --- a/src/oat/runtime/support_instrumentation.cc +++ b/src/oat/runtime/support_instrumentation.cc @@ -22,8 +22,10 @@ namespace art { -extern "C" const void* artInstrumentationMethodEntryFromCode(AbstractMethod* method, Thread* self, - AbstractMethod** sp, uintptr_t lr) +extern "C" const void* artInstrumentationMethodEntryFromCode(mirror::AbstractMethod* method, + Thread* self, + mirror::AbstractMethod** sp, + uintptr_t lr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { self->SetTopOfStack(sp, lr); self->VerifyStack(); @@ -41,7 +43,7 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(AbstractMethod* met return instrumentation->GetSavedCodeFromMap(method); } -extern "C" uint64_t artInstrumentationMethodExitFromCode(Thread* self, AbstractMethod** sp) +extern "C" uint64_t artInstrumentationMethodExitFromCode(Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { self->SetTopOfStack(sp, 0); self->VerifyStack(); diff --git a/src/oat/runtime/support_interpreter.cc b/src/oat/runtime/support_interpreter.cc index 98751cc7c5..a02ef2719a 100644 --- a/src/oat/runtime/support_interpreter.cc +++ b/src/oat/runtime/support_interpreter.cc @@ -17,7 +17,9 @@ #include "argument_visitor.h" #include "callee_save_frame.h" #include "interpreter/interpreter.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" namespace art { @@ -25,7 +27,7 @@ namespace art { // Visits arguments on the stack placing them into the shadow frame. class BuildShadowFrameVisitor : public ArgumentVisitor { public: - BuildShadowFrameVisitor(MethodHelper& caller_mh, AbstractMethod** sp, + BuildShadowFrameVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp, ShadowFrame& sf, size_t first_arg_reg) : ArgumentVisitor(caller_mh, sp), sf_(sf), cur_reg_(first_arg_reg) {} @@ -41,7 +43,7 @@ class BuildShadowFrameVisitor : public ArgumentVisitor { } break; case Primitive::kPrimNot: - sf_.SetVRegReference(cur_reg_, *reinterpret_cast<Object**>(GetParamAddress())); + sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress())); break; case Primitive::kPrimBoolean: // Fall-through. case Primitive::kPrimByte: // Fall-through. @@ -65,7 +67,8 @@ class BuildShadowFrameVisitor : public ArgumentVisitor { DISALLOW_COPY_AND_ASSIGN(BuildShadowFrameVisitor); }; -extern "C" uint64_t artInterpreterEntry(AbstractMethod* method, Thread* self, AbstractMethod** sp) +extern "C" uint64_t artInterpreterEntry(mirror::AbstractMethod* method, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Ensure we don't get thread suspension until the object arguments are safely in the shadow // frame. diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc index 7a49489f8d..438ac8f4c3 100644 --- a/src/oat/runtime/support_invoke.cc +++ b/src/oat/runtime/support_invoke.cc @@ -15,16 +15,22 @@ */ #include "callee_save_frame.h" +#include "dex_instruction.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "runtime_support.h" namespace art { // Determine target of interface dispatch. This object is known non-null. -extern "C" uint64_t artInvokeInterfaceTrampoline(AbstractMethod* interface_method, - Object* this_object, AbstractMethod* caller_method, - Thread* self, AbstractMethod** sp) +extern "C" uint64_t artInvokeInterfaceTrampoline(mirror::AbstractMethod* interface_method, + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method; + mirror::AbstractMethod* method; if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex16)) { method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method); if (UNLIKELY(method == NULL)) { @@ -131,10 +137,13 @@ extern "C" uint64_t artInvokeInterfaceTrampoline(AbstractMethod* interface_metho } -static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, AbstractMethod* caller_method, - Thread* self, AbstractMethod** sp, bool access_check, InvokeType type) +static uint64_t artInvokeCommon(uint32_t method_idx, mirror::Object* this_object, + mirror::AbstractMethod* caller_method, + Thread* self, mirror::AbstractMethod** sp, bool access_check, + InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type); + mirror::AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, + access_check, type); if (UNLIKELY(method == NULL)) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs); method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type); @@ -163,47 +172,47 @@ static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, Abstra // See comments in runtime_support_asm.S extern "C" uint64_t artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx, - Object* this_object, - AbstractMethod* caller_method, + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kInterface); } extern "C" uint64_t artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx, - Object* this_object, - AbstractMethod* caller_method, + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kDirect); } extern "C" uint64_t artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx, - Object* this_object, - AbstractMethod* caller_method, - Thread* self, - AbstractMethod** sp) + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, + Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kStatic); } extern "C" uint64_t artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx, - Object* this_object, - AbstractMethod* caller_method, + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kSuper); } extern "C" uint64_t artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx, - Object* this_object, - AbstractMethod* caller_method, + mirror::Object* this_object, + mirror::AbstractMethod* caller_method, Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kVirtual); } diff --git a/src/oat/runtime/support_jni.cc b/src/oat/runtime/support_jni.cc index e1ae530b9c..0e21700cac 100644 --- a/src/oat/runtime/support_jni.cc +++ b/src/oat/runtime/support_jni.cc @@ -14,7 +14,11 @@ * limitations under the License. */ -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "runtime_support.h" #include "scoped_thread_state_change.h" @@ -28,7 +32,7 @@ extern void* FindNativeMethod(Thread* self) LOCKS_EXCLUDED(Locks::mutator_lock_) DCHECK(Thread::Current() == self); ScopedObjectAccess soa(self); - AbstractMethod* method = self->GetCurrentMethod(); + mirror::AbstractMethod* method = self->GetCurrentMethod(); DCHECK(method != NULL); // Lookup symbol address for method, on failure we'll return NULL with an @@ -81,11 +85,11 @@ extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject lo PopLocalReferences(saved_local_ref_cookie, self); } -extern Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, - Thread* self) +extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, + Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { self->TransitionFromSuspendedToRunnable(); - Object* o = self->DecodeJObject(result); // Must decode before pop. + mirror::Object* o = self->DecodeJObject(result); // Must decode before pop. PopLocalReferences(saved_local_ref_cookie, self); // Process result. if (UNLIKELY(self->GetJniEnv()->check_jni)) { @@ -97,13 +101,13 @@ extern Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_re return o; } -extern Object* JniMethodEndWithReferenceSynchronized(jobject result, - uint32_t saved_local_ref_cookie, - jobject locked, Thread* self) +extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, + uint32_t saved_local_ref_cookie, + jobject locked, Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { self->TransitionFromSuspendedToRunnable(); UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. - Object* o = self->DecodeJObject(result); + mirror::Object* o = self->DecodeJObject(result); PopLocalReferences(saved_local_ref_cookie, self); // Process result. if (UNLIKELY(self->GetJniEnv()->check_jni)) { @@ -117,9 +121,10 @@ extern Object* JniMethodEndWithReferenceSynchronized(jobject result, static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) { intptr_t value = *arg_ptr; - Object** value_as_jni_rep = reinterpret_cast<Object**>(value); - Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL; - CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep)) << value_as_work_around_rep; + mirror::Object** value_as_jni_rep = reinterpret_cast<mirror::Object**>(value); + mirror::Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL; + CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep)) + << value_as_work_around_rep; *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep); } @@ -137,7 +142,7 @@ extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) // | unused | // | unused | // | unused | <- sp - AbstractMethod* jni_method = self->GetCurrentMethod(); + mirror::AbstractMethod* jni_method = self->GetCurrentMethod(); DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method); intptr_t* arg_ptr = sp + 4; // pointer to r1 on stack // Fix up this/jclass argument diff --git a/src/oat/runtime/support_locks.cc b/src/oat/runtime/support_locks.cc index f3a31067dc..38fc48cba0 100644 --- a/src/oat/runtime/support_locks.cc +++ b/src/oat/runtime/support_locks.cc @@ -15,11 +15,12 @@ */ #include "callee_save_frame.h" -#include "object.h" +#include "mirror/object.h" namespace art { -extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, AbstractMethod** sp) +extern "C" int artUnlockObjectFromCode(mirror::Object* obj, Thread* self, + mirror::AbstractMethod** sp) UNLOCK_FUNCTION(monitor_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); DCHECK(obj != NULL); // Assumed to have been checked before entry @@ -27,7 +28,8 @@ extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, AbstractMethod return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */; } -extern "C" void artLockObjectFromCode(Object* obj, Thread* thread, AbstractMethod** sp) +extern "C" void artLockObjectFromCode(mirror::Object* obj, Thread* thread, + mirror::AbstractMethod** sp) EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); DCHECK(obj != NULL); // Assumed to have been checked before entry diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc index f0f07a11c2..65e404ab55 100644 --- a/src/oat/runtime/support_proxy.cc +++ b/src/oat/runtime/support_proxy.cc @@ -15,7 +15,9 @@ */ #include "argument_visitor.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "reflection.h" #include "runtime_support.h" @@ -31,7 +33,7 @@ namespace art { // to jobjects. class BuildArgumentVisitor : public ArgumentVisitor { public: - BuildArgumentVisitor(MethodHelper& caller_mh, AbstractMethod** sp, + BuildArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp, ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) : ArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {} @@ -40,7 +42,7 @@ class BuildArgumentVisitor : public ArgumentVisitor { Primitive::Type type = GetParamPrimitiveType(); switch (type) { case Primitive::kPrimNot: { - Object* obj = *reinterpret_cast<Object**>(GetParamAddress()); + mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress()); val.l = soa_.AddLocalReference<jobject>(obj); break; } @@ -79,8 +81,9 @@ class BuildArgumentVisitor : public ArgumentVisitor { // which is responsible for recording callee save registers. We explicitly place into jobjects the // incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a // field within the proxy object, which will box the primitive arguments and deal with error cases. -extern "C" uint64_t artProxyInvokeHandler(AbstractMethod* proxy_method, Object* receiver, - Thread* self, AbstractMethod** sp) +extern "C" uint64_t artProxyInvokeHandler(mirror::AbstractMethod* proxy_method, + mirror::Object* receiver, + Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Ensure we don't get thread suspension until the object arguments are safely in jobjects. const char* old_cause = @@ -106,7 +109,7 @@ extern "C" uint64_t artProxyInvokeHandler(AbstractMethod* proxy_method, Object* args.erase(args.begin()); // Convert proxy method into expected interface method. - AbstractMethod* interface_method = proxy_method->FindOverriddenMethod(); + mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod(); DCHECK(interface_method != NULL); DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method); diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc index ac188a82f8..dcfea3aae8 100644 --- a/src/oat/runtime/support_stubs.cc +++ b/src/oat/runtime/support_stubs.cc @@ -17,8 +17,12 @@ #if !defined(ART_USE_LLVM_COMPILER) #include "callee_save_frame.h" #endif +#include "class_linker-inl.h" #include "dex_instruction.h" -#include "object.h" +#include "mirror/class-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #if defined(ART_USE_LLVM_COMPILER) #include "nth_caller_visitor.h" @@ -32,7 +36,8 @@ namespace art { #if !defined(ART_USE_LLVM_COMPILER) // Lazily resolve a method. Called by stub code. -const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, AbstractMethod** sp, Thread* thread, +const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called, + mirror::AbstractMethod** sp, Thread* thread, Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__arm__) @@ -52,7 +57,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // | R0 | // | Method* | <- sp DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()); - AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48); + mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48); uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize); uint32_t pc_offset = 10; uintptr_t caller_pc = regs[pc_offset]; @@ -72,7 +77,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // | ECX | arg1 // | EAX/Method* | <- sp DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()); - AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32); + mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32); uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp)); uintptr_t caller_pc = regs[7]; #elif defined(__mips__) @@ -91,13 +96,13 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // | A1 | arg1 // | A0/Method* | <- sp DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()); - AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48); + mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48); uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp)); uint32_t pc_offset = 11; uintptr_t caller_pc = regs[pc_offset]; #else UNIMPLEMENTED(FATAL); - AbstractMethod** caller_sp = NULL; + mirror::AbstractMethod** caller_sp = NULL; uintptr_t* regs = NULL; uintptr_t caller_pc = 0; #endif @@ -109,7 +114,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // Compute details about the called method (avoid GCs) ClassLinker* linker = Runtime::Current()->GetClassLinker(); - AbstractMethod* caller = *caller_sp; + mirror::AbstractMethod* caller = *caller_sp; InvokeType invoke_type; uint32_t dex_method_idx; #if !defined(__i386__) @@ -173,7 +178,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // Place into local references incoming arguments from the caller's register arguments size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1 if (invoke_type != kStatic) { - Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]); cur_arg++; if (args_in_regs < 3) { // If we thought we had fewer than 3 arguments in registers, account for the receiver @@ -188,7 +193,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs char c = shorty[shorty_index]; shorty_index++; if (c == 'L') { - Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]); soa.AddLocalReference<jobject>(obj); } cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); @@ -199,7 +204,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs char c = shorty[shorty_index]; shorty_index++; if (c == 'L') { - Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]); soa.AddLocalReference<jobject>(obj); } cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); @@ -214,7 +219,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // Incompatible class change should have been handled in resolve method. CHECK(!called->CheckIncompatibleClassChange(invoke_type)); // Ensure that the called method's class is initialized. - Class* called_class = called->GetDeclaringClass(); + mirror::Class* called_class = called->GetDeclaringClass(); linker->EnsureInitialized(called_class, true, true); if (LIKELY(called_class->IsInitialized())) { code = called->GetCode(); @@ -252,7 +257,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs Thread* thread, Runtime::TrampolineType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t dex_pc; - AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc); + mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc); ClassLinker* linker = Runtime::Current()->GetClassLinker(); InvokeType invoke_type; @@ -299,7 +304,7 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs // Incompatible class change should have been handled in resolve method. CHECK(!called->CheckIncompatibleClassChange(invoke_type)); // Ensure that the called method's class is initialized. - Class* called_class = called->GetDeclaringClass(); + mirror::Class* called_class = called->GetDeclaringClass(); linker->EnsureInitialized(called_class, true, true); if (LIKELY(called_class->IsInitialized())) { code = called->GetCode(); @@ -342,7 +347,8 @@ const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, Abs #if !defined(ART_USE_LLVM_COMPILER) // Called by the AbstractMethodError. Called by stub code. -extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp) +extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", @@ -350,7 +356,8 @@ extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thr thread->QuickDeliverException(); } #else // ART_USE_LLVM_COMPILER -extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod**) +extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, + mirror::AbstractMethod**) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", "abstract method \"%s\"", PrettyMethod(method).c_str()); diff --git a/src/oat/runtime/support_thread.cc b/src/oat/runtime/support_thread.cc index 04038ab2e1..e7117147a9 100644 --- a/src/oat/runtime/support_thread.cc +++ b/src/oat/runtime/support_thread.cc @@ -28,7 +28,7 @@ void CheckSuspendFromCode(Thread* thread) CheckSuspend(thread); } -extern "C" void artTestSuspendFromCode(Thread* thread, AbstractMethod** sp) +extern "C" void artTestSuspendFromCode(Thread* thread, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Called when suspend count check value is 0 and thread->suspend_count_ != 0 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc index 5bf48e4329..80ba118d96 100644 --- a/src/oat/runtime/support_throw.cc +++ b/src/oat/runtime/support_throw.cc @@ -15,7 +15,7 @@ */ #include "callee_save_frame.h" -#include "object.h" +#include "mirror/object.h" #include "object_utils.h" #include "runtime_support.h" #include "thread.h" @@ -26,21 +26,21 @@ namespace art { // Used to implement MOVE_EXCEPTION. extern "C" void* GetAndClearException(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(self->IsExceptionPending()); - Throwable* exception = self->GetException(); + mirror::Throwable* exception = self->GetException(); self->ClearException(); return exception; } // Deliver an exception that's pending on thread helping set up a callee save frame on the way. -extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, AbstractMethod** sp) +extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->QuickDeliverException(); } // Called by generated call to throw an exception. -extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, - AbstractMethod** sp) +extern "C" void artDeliverExceptionFromCode(mirror::Throwable* exception, Thread* thread, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { /* * exception may be NULL, in which case this routine should @@ -56,18 +56,18 @@ extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread // Called by generated call to throw a NPE exception. extern "C" void artThrowNullPointerExceptionFromCode(Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); uint32_t dex_pc; - AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc); + mirror::AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc); ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc); self->QuickDeliverException(); } // Called by generated call to throw an arithmetic divide by zero exception. extern "C" void artThrowDivZeroFromCode(Thread* thread, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero"); @@ -76,7 +76,7 @@ extern "C" void artThrowDivZeroFromCode(Thread* thread, // Called by generated call to throw an array index out of bounds exception. extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", @@ -84,7 +84,7 @@ extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread thread->QuickDeliverException(); } -extern "C" void artThrowStackOverflowFromCode(Thread* self, AbstractMethod** sp) +extern "C" void artThrowStackOverflowFromCode(Thread* self, mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); ThrowStackOverflowError(self); @@ -92,10 +92,10 @@ extern "C" void artThrowStackOverflowFromCode(Thread* self, AbstractMethod** sp) } extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, - AbstractMethod** sp) + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); - AbstractMethod* method = self->GetCurrentMethod(); + mirror::AbstractMethod* method = self->GetCurrentMethod(); ThrowNoSuchMethodError(method_idx, method); self->QuickDeliverException(); } diff --git a/src/oat/runtime/x86/context_x86.cc b/src/oat/runtime/x86/context_x86.cc index 4efdf81d5e..9d930ca5a8 100644 --- a/src/oat/runtime/x86/context_x86.cc +++ b/src/oat/runtime/x86/context_x86.cc @@ -16,7 +16,8 @@ #include "context_x86.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "stack.h" namespace art { namespace x86 { @@ -34,7 +35,7 @@ void X86Context::Reset() { } void X86Context::FillCalleeSaves(const StackVisitor& fr) { - AbstractMethod* method = fr.GetMethod(); + mirror::AbstractMethod* method = fr.GetMethod(); uint32_t core_spills = method->GetCoreSpillMask(); size_t spill_count = __builtin_popcount(core_spills); DCHECK_EQ(method->GetFpSpillMask(), 0u); diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc index fce2251908..445ae2a5a7 100644 --- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc +++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc @@ -28,12 +28,13 @@ extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t); extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t); // Cast entrypoints. -extern "C" uint32_t art_is_assignable_from_code(const Class* klass, const Class* ref_class); +extern "C" uint32_t art_is_assignable_from_code(const mirror::Class* klass, + const mirror::Class* ref_class); extern "C" void art_can_put_array_element_from_code(void*, void*); extern "C" void art_check_cast_from_code(void*, void*); // Debug entrypoints. -extern void DebugMe(AbstractMethod* method, uint32_t info); +extern void DebugMe(mirror::AbstractMethod* method, uint32_t info); extern "C" void art_update_debugger(void*, void*, int32_t, void*); // DexCache entrypoints. @@ -66,11 +67,11 @@ extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self); extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self); extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked, Thread* self); -extern Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, - Thread* self); -extern Object* JniMethodEndWithReferenceSynchronized(jobject result, - uint32_t saved_local_ref_cookie, - jobject locked, Thread* self); +extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, + Thread* self); +extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, + uint32_t saved_local_ref_cookie, + jobject locked, Thread* self); // Lock entrypoints. extern "C" void art_lock_object_from_code(void*); @@ -98,7 +99,8 @@ extern "C" int32_t art_string_compareto(void*, void*); extern "C" void* art_memcpy(void*, const void*, size_t); // Invoke entrypoints. -const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod*, AbstractMethod**, Thread*, +const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*, + mirror::AbstractMethod**, Thread*, Runtime::TrampolineType); extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*); extern "C" void art_invoke_interface_trampoline(uint32_t, void*); @@ -112,7 +114,8 @@ extern void CheckSuspendFromCode(Thread* thread); extern "C" void art_test_suspend(); // Throw entrypoints. -extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp); +extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, + mirror::AbstractMethod** sp); extern "C" void art_deliver_exception_from_code(void*); extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_throw_div_zero_from_code(); diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc index cade99deb8..92f3c5f238 100644 --- a/src/oat/runtime/x86/stub_x86.cc +++ b/src/oat/runtime/x86/stub_x86.cc @@ -15,10 +15,10 @@ */ #include "jni_internal.h" +#include "mirror/array.h" #include "oat/runtime/oat_support_entrypoints.h" #include "oat/runtime/stub.h" #include "oat/utils/x86/assembler_x86.h" -#include "object.h" #include "stack_indirect_reference_table.h" #include "sirt_ref.h" @@ -27,7 +27,7 @@ namespace art { namespace x86 { -ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) { +mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) { UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); #if !defined(ART_USE_LLVM_COMPILER) @@ -93,7 +93,7 @@ ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -101,9 +101,9 @@ ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) { return resolution_trampoline.get(); } -typedef void (*ThrowAme)(AbstractMethod*, Thread*); +typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); -ByteArray* CreateAbstractMethodErrorStub() { +mirror::ByteArray* CreateAbstractMethodErrorStub() { UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); #if !defined(ART_USE_LLVM_COMPILER) @@ -148,7 +148,7 @@ ByteArray* CreateAbstractMethodErrorStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -156,7 +156,7 @@ ByteArray* CreateAbstractMethodErrorStub() { return abstract_stub.get(); } -ByteArray* CreateJniDlsymLookupStub() { +mirror::ByteArray* CreateJniDlsymLookupStub() { UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); // Pad stack to ensure 16-byte alignment @@ -182,7 +182,7 @@ ByteArray* CreateJniDlsymLookupStub() { size_t cs = assembler->CodeSize(); Thread* self = Thread::Current(); - SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); + SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oat_compilation_unit.h b/src/oat_compilation_unit.h index ec7c9a30e8..7eac3223a3 100644 --- a/src/oat_compilation_unit.h +++ b/src/oat_compilation_unit.h @@ -22,11 +22,12 @@ #include <stdint.h> namespace art { - +namespace mirror { class ClassLoader; +class DexCache; +} // namespace mirror class ClassLinker; class DexFile; -class DexCache; class OatCompilationUnit { public: diff --git a/src/oat_file.cc b/src/oat_file.cc index 8229f630b1..b806df82d6 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -22,7 +22,11 @@ #include "base/unix_file/fd_file.h" #include "elf_file.h" #include "oat.h" +#include "mirror/class.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" #include "os.h" +#include "utils.h" namespace art { @@ -296,7 +300,7 @@ const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_ind const byte* oat_class_pointer = oat_file_->Begin() + oat_class_offset; CHECK_LT(oat_class_pointer, oat_file_->End()); - Class::Status status = *reinterpret_cast<const Class::Status*>(oat_class_pointer); + mirror::Class::Status status = *reinterpret_cast<const mirror::Class::Status*>(oat_class_pointer); const byte* methods_pointer = oat_class_pointer + sizeof(status); CHECK_LT(methods_pointer, oat_file_->End()); @@ -307,13 +311,13 @@ const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_ind } OatFile::OatClass::OatClass(const OatFile* oat_file, - Class::Status status, + mirror::Class::Status status, const OatMethodOffsets* methods_pointer) : oat_file_(oat_file), status_(status), methods_pointer_(methods_pointer) {} OatFile::OatClass::~OatClass() {} -Class::Status OatFile::OatClass::GetStatus() const { +mirror::Class::Status OatFile::OatClass::GetStatus() const { return status_; } @@ -392,9 +396,9 @@ uint32_t OatFile::OatMethod::GetCodeSize() const { return reinterpret_cast<uint32_t*>(code)[-1]; } -AbstractMethod::InvokeStub* OatFile::OatMethod::GetInvokeStub() const { +mirror::AbstractMethod::InvokeStub* OatFile::OatMethod::GetInvokeStub() const { const byte* stub = GetOatPointer<const byte*>(invoke_stub_offset_); - return reinterpret_cast<AbstractMethod::InvokeStub*>(const_cast<byte*>(stub)); + return reinterpret_cast<mirror::AbstractMethod::InvokeStub*>(const_cast<byte*>(stub)); } uint32_t OatFile::OatMethod::GetInvokeStubSize() const { @@ -413,7 +417,7 @@ const void* OatFile::OatMethod::GetProxyStub() const { } #endif -void OatFile::OatMethod::LinkMethodPointers(AbstractMethod* method) const { +void OatFile::OatMethod::LinkMethodPointers(mirror::AbstractMethod* method) const { CHECK(method != NULL); method->SetCode(GetCode()); method->SetFrameSizeInBytes(frame_size_in_bytes_); @@ -425,7 +429,7 @@ void OatFile::OatMethod::LinkMethodPointers(AbstractMethod* method) const { method->SetInvokeStub(GetInvokeStub()); } -void OatFile::OatMethod::LinkMethodOffsets(AbstractMethod* method) const { +void OatFile::OatMethod::LinkMethodOffsets(mirror::AbstractMethod* method) const { CHECK(method != NULL); method->SetOatCodeOffset(GetCodeOffset()); method->SetFrameSizeInBytes(GetFrameSizeInBytes()); diff --git a/src/oat_file.h b/src/oat_file.h index ff5cd80ebf..bff48faa7f 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -20,8 +20,11 @@ #include <string> #include <vector> -#include "globals.h" -#include "object.h" +#include "dex_file.h" +#include "invoke_type.h" +#include "mem_map.h" +#include "mirror/abstract_method.h" +#include "oat.h" #include "os.h" namespace art { @@ -65,10 +68,10 @@ class OatFile { class OatMethod { public: // Link Method for execution using the contents of this OatMethod - void LinkMethodPointers(AbstractMethod* method) const; + void LinkMethodPointers(mirror::AbstractMethod* method) const; // Link Method for image writing using the contents of this OatMethod - void LinkMethodOffsets(AbstractMethod* method) const; + void LinkMethodOffsets(mirror::AbstractMethod* method) const; uint32_t GetCodeOffset() const { return code_offset_; @@ -108,7 +111,7 @@ class OatFile { return GetOatPointer<const uint8_t*>(native_gc_map_offset_); } - AbstractMethod::InvokeStub* GetInvokeStub() const; + mirror::AbstractMethod::InvokeStub* GetInvokeStub() const; uint32_t GetInvokeStubSize() const; #if defined(ART_USE_LLVM_COMPILER) @@ -161,7 +164,7 @@ class OatFile { class OatClass { public: - Class::Status GetStatus() const; + mirror::Class::Status GetStatus() const; // get the OatMethod entry based on its index into the class // defintion. direct methods come first, followed by virtual @@ -172,11 +175,11 @@ class OatFile { private: OatClass(const OatFile* oat_file, - Class::Status status, + mirror::Class::Status status, const OatMethodOffsets* methods_pointer); const OatFile* oat_file_; - const Class::Status status_; + const mirror::Class::Status status_; const OatMethodOffsets* methods_pointer_; friend class OatDexFile; diff --git a/src/oat_test.cc b/src/oat_test.cc index ec0fa7da0f..8da3626e8c 100644 --- a/src/oat_test.cc +++ b/src/oat_test.cc @@ -14,6 +14,9 @@ * limitations under the License. */ +#include "mirror/abstract_method-inl.h" +#include "mirror/class-inl.h" +#include "mirror/object_array-inl.h" #include "oat_file.h" #include "oat_writer.h" #include "vector_output_stream.h" @@ -24,7 +27,7 @@ namespace art { class OatTest : public CommonTest { protected: - void CheckMethod(AbstractMethod* method, + void CheckMethod(mirror::AbstractMethod* method, const OatFile::OatMethod& oat_method, const DexFile* dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -119,7 +122,7 @@ TEST_F(OatTest, WriteRead) { UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i)); - Class* klass = class_linker->FindClass(descriptor, NULL); + mirror::Class* klass = class_linker->FindClass(descriptor, NULL); size_t method_index = 0; for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) { diff --git a/src/oat_writer.cc b/src/oat_writer.cc index 113bebaa53..6fcea5d8e2 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -21,7 +21,9 @@ #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" -#include "class_loader.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/array.h" +#include "mirror/class_loader.h" #include "os.h" #include "output_stream.h" #include "safe_map.h" @@ -134,13 +136,13 @@ size_t OatWriter::InitOatClasses(size_t offset) { Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index); CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref); - Class::Status status; + mirror::Class::Status status; if (compiled_class != NULL) { status = compiled_class->GetStatus(); } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) { - status = Class::kStatusError; + status = mirror::Class::kStatusError; } else { - status = Class::kStatusNotReady; + status = mirror::Class::kStatusNotReady; } OatClass* oat_class = new OatClass(status, num_methods); @@ -307,16 +309,18 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, // We expect GC maps except when the class hasn't been verified or the method is native Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index); CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref); - Class::Status status; + mirror::Class::Status status; if (compiled_class != NULL) { status = compiled_class->GetStatus(); } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) { - status = Class::kStatusError; + status = mirror::Class::kStatusError; } else { - status = Class::kStatusNotReady; + status = mirror::Class::kStatusNotReady; } - CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified) - << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file); + CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) + << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " + << (status < mirror::Class::kStatusVerified) << " " << status << " " + << PrettyMethod(method_idx, *dex_file); #endif // Deduplicate GC maps @@ -396,11 +400,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, if (compiler_->IsImage()) { ClassLinker* linker = Runtime::Current()->GetClassLinker(); - DexCache* dex_cache = linker->FindDexCache(*dex_file); + mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file); // Unchecked as we hold mutator_lock_ on entry. ScopedObjectAccessUnchecked soa(Thread::Current()); - AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, - NULL, NULL, type); + mirror::AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, + NULL, NULL, type); CHECK(method != NULL); method->SetFrameSizeInBytes(frame_size_in_bytes); method->SetCoreSpillMask(core_spill_mask); @@ -836,7 +840,7 @@ bool OatWriter::OatDexFile::Write(OutputStream& out) const { return true; } -OatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) { +OatWriter::OatClass::OatClass(mirror::Class::Status status, uint32_t methods_count) { status_ = status; method_offsets_.resize(methods_count); } diff --git a/src/oat_writer.h b/src/oat_writer.h index 2bcbbc526e..e1638d0fc6 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -22,10 +22,9 @@ #include <cstddef> #include "compiler.h" -#include "dex_cache.h" #include "mem_map.h" #include "oat.h" -#include "object.h" +#include "mirror/class.h" #include "safe_map.h" #include "UniquePtr.h" @@ -136,13 +135,13 @@ class OatWriter { class OatClass { public: - explicit OatClass(Class::Status status, uint32_t methods_count); + explicit OatClass(mirror::Class::Status status, uint32_t methods_count); size_t SizeOf() const; void UpdateChecksum(OatHeader& oat_header) const; bool Write(OutputStream& out) const; // data to write - Class::Status status_; + mirror::Class::Status status_; std::vector<OatMethodOffsets> method_offsets_; private: diff --git a/src/oatdump.cc b/src/oatdump.cc index 5ee433c4e1..3fe62bce24 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -25,6 +25,7 @@ #include "base/stringpiece.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" +#include "class_linker-inl.h" #include "dex_instruction.h" #include "disassembler.h" #include "gc_map.h" @@ -32,6 +33,12 @@ #include "gc/space.h" #include "image.h" #include "indenter.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/array-inl.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "oat.h" #include "object_utils.h" #include "os.h" @@ -162,7 +169,7 @@ class OatDumper { return oat_file_.GetOatHeader().GetInstructionSet(); } - const void* GetOatCode(AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const void* GetOatCode(mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { MethodHelper mh(m); for (size_t i = 0; i < oat_dex_files_.size(); i++) { const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; @@ -580,8 +587,8 @@ class OatDumper { uint32_t method_access_flags, uint32_t dex_pc) { bool first = true; ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); - ClassLoader* class_loader = NULL; + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); + mirror::ClassLoader* class_loader = NULL; std::vector<int32_t> kinds = verifier::MethodVerifier::DescribeVRegs(dex_method_idx, dex_file, dex_cache, class_loader, class_def_idx, code_item, NULL, @@ -633,8 +640,8 @@ class OatDumper { uint32_t method_access_flags) { if ((method_access_flags & kAccNative) == 0) { ScopedObjectAccess soa(Thread::Current()); - DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); - ClassLoader* class_loader = NULL; + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); + mirror::ClassLoader* class_loader = NULL; verifier::MethodVerifier::VerifyMethodAndDump(os, dex_method_idx, dex_file, dex_cache, class_loader, class_def_idx, code_item, NULL, method_access_flags); @@ -713,17 +720,17 @@ class ImageDumper { for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i); const char* image_root_description = image_roots_descriptions_[i]; - Object* image_root_object = image_header_.GetImageRoot(image_root); + mirror::Object* image_root_object = image_header_.GetImageRoot(image_root); indent1_os << StringPrintf("%s: %p\n", image_root_description, image_root_object); if (image_root_object->IsObjectArray()) { Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count); std::ostream indent2_os(&indent2_filter); // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this) - ObjectArray<Object>* image_root_object_array - = down_cast<ObjectArray<Object>*>(image_root_object); + mirror::ObjectArray<mirror::Object>* image_root_object_array + = down_cast<mirror::ObjectArray<mirror::Object>*>(image_root_object); // = image_root_object->AsObjectArray<Object>(); for (int i = 0; i < image_root_object_array->GetLength(); i++) { - Object* value = image_root_object_array->Get(i); + mirror::Object* value = image_root_object_array->Get(i); if (value != NULL) { indent2_os << i << ": "; PrettyObjectValue(indent2_os, value->GetClass(), value); @@ -737,7 +744,7 @@ class ImageDumper { os << "\n"; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Object* oat_location_object = image_header_.GetImageRoot(ImageHeader::kOatLocation); + mirror::Object* oat_location_object = image_header_.GetImageRoot(ImageHeader::kOatLocation); std::string oat_location(oat_location_object->AsString()->ToModifiedUtf8()); os << "OAT LOCATION: " << oat_location; if (!host_prefix_.empty()) { @@ -811,36 +818,36 @@ class ImageDumper { } private: - static void PrettyObjectValue(std::ostream& os, Class* type, Object* value) + static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(type != NULL); if (value == NULL) { os << StringPrintf("null %s\n", PrettyDescriptor(type).c_str()); } else if (type->IsStringClass()) { - String* string = value->AsString(); + mirror::String* string = value->AsString(); os << StringPrintf("%p String: %s\n", string, PrintableString(string->ToModifiedUtf8()).c_str()); } else if (type->IsClassClass()) { - Class* klass = value->AsClass(); + mirror::Class* klass = value->AsClass(); os << StringPrintf("%p Class: %s\n", klass, PrettyDescriptor(klass).c_str()); } else if (type->IsFieldClass()) { - Field* field = value->AsField(); + mirror::Field* field = value->AsField(); os << StringPrintf("%p Field: %s\n", field, PrettyField(field).c_str()); } else if (type->IsMethodClass()) { - AbstractMethod* method = value->AsMethod(); + mirror::AbstractMethod* method = value->AsMethod(); os << StringPrintf("%p Method: %s\n", method, PrettyMethod(method).c_str()); } else { os << StringPrintf("%p %s\n", value, PrettyDescriptor(type).c_str()); } } - static void PrintField(std::ostream& os, Field* field, Object* obj) + static void PrintField(std::ostream& os, mirror::Field* field, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FieldHelper fh(field); const char* descriptor = fh.GetTypeDescriptor(); os << StringPrintf("%s: ", fh.GetName()); if (descriptor[0] != 'L' && descriptor[0] != '[') { - Class* type = fh.GetType(); + mirror::Class* type = fh.GetType(); if (type->IsPrimitiveLong()) { os << StringPrintf("%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj)); } else if (type->IsPrimitiveDouble()) { @@ -854,7 +861,7 @@ class ImageDumper { } else { // Get the value, don't compute the type unless it is non-null as we don't want // to cause class loading. - Object* value = field->GetObj(obj); + mirror::Object* value = field->GetObj(obj); if (value == NULL) { os << StringPrintf("null %s\n", PrettyDescriptor(descriptor).c_str()); } else { @@ -863,26 +870,26 @@ class ImageDumper { } } - static void DumpFields(std::ostream& os, Object* obj, Class* klass) + static void DumpFields(std::ostream& os, mirror::Object* obj, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* super = klass->GetSuperClass(); + mirror::Class* super = klass->GetSuperClass(); if (super != NULL) { DumpFields(os, obj, super); } - ObjectArray<Field>* fields = klass->GetIFields(); + mirror::ObjectArray<mirror::Field>* fields = klass->GetIFields(); if (fields != NULL) { for (int32_t i = 0; i < fields->GetLength(); i++) { - Field* field = fields->Get(i); + mirror::Field* field = fields->Get(i); PrintField(os, field, obj); } } } - bool InDumpSpace(const Object* object) { + bool InDumpSpace(const mirror::Object* object) { return image_space_.Contains(object); } - const void* GetOatCodeBegin(AbstractMethod* m) + const void* GetOatCodeBegin(mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Runtime* runtime = Runtime::Current(); const void* code = m->GetCode(); @@ -895,7 +902,7 @@ class ImageDumper { return code; } - uint32_t GetOatCodeSize(AbstractMethod* m) + uint32_t GetOatCodeSize(mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m)); if (oat_code_begin == NULL) { @@ -904,7 +911,7 @@ class ImageDumper { return oat_code_begin[-1]; } - const void* GetOatCodeEnd(AbstractMethod* m) + const void* GetOatCodeEnd(mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m)); if (oat_code_begin == NULL) { @@ -913,7 +920,7 @@ class ImageDumper { return oat_code_begin + GetOatCodeSize(m); } - static void Callback(Object* obj, void* arg) + static void Callback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(obj != NULL); DCHECK(arg != NULL); @@ -928,12 +935,12 @@ class ImageDumper { state->stats_.alignment_bytes += alignment_bytes; std::ostream& os = *state->os_; - Class* obj_class = obj->GetClass(); + mirror::Class* obj_class = obj->GetClass(); if (obj_class->IsArrayClass()) { os << StringPrintf("%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(), obj->AsArray()->GetLength()); } else if (obj->IsClass()) { - Class* klass = obj->AsClass(); + mirror::Class* klass = obj->AsClass(); os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str()) << klass->GetStatus() << ")\n"; } else if (obj->IsField()) { @@ -952,10 +959,10 @@ class ImageDumper { std::ostream indent_os(&indent_filter); DumpFields(indent_os, obj, obj_class); if (obj->IsObjectArray()) { - ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>(); + mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>(); int32_t length = obj_array->GetLength(); for (int32_t i = 0; i < length; i++) { - Object* value = obj_array->Get(i); + mirror::Object* value = obj_array->Get(i); size_t run = 0; for (int32_t j = i + 1; j < length; j++) { if (value == obj_array->Get(j)) { @@ -970,22 +977,22 @@ class ImageDumper { indent_os << StringPrintf("%d to %zd: ", i, i + run); i = i + run; } - Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass(); + mirror::Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass(); PrettyObjectValue(indent_os, value_class, value); } } else if (obj->IsClass()) { - ObjectArray<Field>* sfields = obj->AsClass()->GetSFields(); + mirror::ObjectArray<mirror::Field>* sfields = obj->AsClass()->GetSFields(); if (sfields != NULL) { indent_os << "STATICS:\n"; Indenter indent2_filter(indent_os.rdbuf(), kIndentChar, kIndentBy1Count); std::ostream indent2_os(&indent2_filter); for (int32_t i = 0; i < sfields->GetLength(); i++) { - Field* field = sfields->Get(i); + mirror::Field* field = sfields->Get(i); PrintField(indent2_os, field, field->GetDeclaringClass()); } } } else if (obj->IsMethod()) { - AbstractMethod* method = obj->AsMethod(); + mirror::AbstractMethod* method = obj->AsMethod(); if (method->IsNative()) { DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method); DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method); @@ -1110,7 +1117,7 @@ class ImageDumper { size_t dex_instruction_bytes; - std::vector<AbstractMethod*> method_outlier; + std::vector<mirror::AbstractMethod*> method_outlier; std::vector<size_t> method_outlier_size; std::vector<double> method_outlier_expansion; std::vector<std::pair<std::string, size_t> > oat_dex_file_sizes; @@ -1163,7 +1170,7 @@ class ImageDumper { return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100; } - void ComputeOutliers(size_t total_size, double expansion, AbstractMethod* method) { + void ComputeOutliers(size_t total_size, double expansion, mirror::AbstractMethod* method) { method_outlier_size.push_back(total_size); method_outlier_expansion.push_back(expansion); method_outlier.push_back(method); diff --git a/src/oatexec.cc b/src/oatexec.cc index ede4799877..c05266ca52 100644 --- a/src/oatexec.cc +++ b/src/oatexec.cc @@ -23,7 +23,7 @@ #include "base/logging.h" #include "jni.h" -#include "object.h" +#include "modifiers.h" #include "ScopedLocalRef.h" #include "toStringArray.h" #include "UniquePtr.h" diff --git a/src/object.cc b/src/object.cc deleted file mode 100644 index 10bf672655..0000000000 --- a/src/object.cc +++ /dev/null @@ -1,1828 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "object.h" - -#include <string.h> - -#include <algorithm> -#include <iostream> -#include <string> -#include <utility> - -#include "base/logging.h" -#include "class_linker.h" -#include "class_loader.h" -#include "dex_cache.h" -#include "dex_file.h" -#include "globals.h" -#include "heap.h" -#include "intern_table.h" -#include "interpreter/interpreter.h" -#include "monitor.h" -#include "object_utils.h" -#include "runtime.h" -#include "runtime_support.h" -#include "sirt_ref.h" -#include "stack.h" -#include "utils.h" -#include "well_known_classes.h" - -namespace art { - -BooleanArray* Object::AsBooleanArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean()); - return down_cast<BooleanArray*>(this); -} - -ByteArray* Object::AsByteArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte()); - return down_cast<ByteArray*>(this); -} - -CharArray* Object::AsCharArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar()); - return down_cast<CharArray*>(this); -} - -ShortArray* Object::AsShortArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort()); - return down_cast<ShortArray*>(this); -} - -IntArray* Object::AsIntArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() || - GetClass()->GetComponentType()->IsPrimitiveFloat()); - return down_cast<IntArray*>(this); -} - -LongArray* Object::AsLongArray() { - DCHECK(GetClass()->IsArrayClass()); - DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() || - GetClass()->GetComponentType()->IsPrimitiveDouble()); - return down_cast<LongArray*>(this); -} - -String* Object::AsString() { - DCHECK(GetClass()->IsStringClass()); - return down_cast<String*>(this); -} - -Throwable* Object::AsThrowable() { - DCHECK(GetClass()->IsThrowableClass()); - return down_cast<Throwable*>(this); -} - -Object* Object::Clone(Thread* self) { - Class* c = GetClass(); - DCHECK(!c->IsClassClass()); - - // Object::SizeOf gets the right size even if we're an array. - // Using c->AllocObject() here would be wrong. - size_t num_bytes = SizeOf(); - Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes)); - if (copy.get() == NULL) { - return NULL; - } - - // Copy instance data. We assume memcpy copies by words. - // TODO: expose and use move32. - byte* src_bytes = reinterpret_cast<byte*>(this); - byte* dst_bytes = reinterpret_cast<byte*>(copy.get()); - size_t offset = sizeof(Object); - memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset); - - // Perform write barriers on copied object references. - if (c->IsArrayClass()) { - if (!c->GetComponentType()->IsPrimitive()) { - const ObjectArray<Object>* array = copy->AsObjectArray<Object>(); - heap->WriteBarrierArray(copy.get(), 0, array->GetLength()); - } - } else { - for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) { - size_t num_reference_fields = klass->NumReferenceInstanceFields(); - for (size_t i = 0; i < num_reference_fields; ++i) { - Field* field = klass->GetInstanceField(i); - MemberOffset field_offset = field->GetOffset(); - const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false); - heap->WriteBarrierField(copy.get(), field_offset, ref); - } - } - } - - if (c->IsFinalizable()) { - heap->AddFinalizerReference(Thread::Current(), copy.get()); - } - - return copy.get(); -} - -uint32_t Object::GetThinLockId() { - return Monitor::GetThinLockId(monitor_); -} - -void Object::MonitorEnter(Thread* thread) { - Monitor::MonitorEnter(thread, this); -} - -bool Object::MonitorExit(Thread* thread) { - return Monitor::MonitorExit(thread, this); -} - -void Object::Notify() { - Monitor::Notify(Thread::Current(), this); -} - -void Object::NotifyAll() { - Monitor::NotifyAll(Thread::Current(), this); -} - -void Object::Wait() { - Monitor::Wait(Thread::Current(), this, 0, 0, true, kWaiting); -} - -void Object::Wait(int64_t ms, int32_t ns) { - Monitor::Wait(Thread::Current(), this, ms, ns, true, kTimedWaiting); -} - -#if VERIFY_OBJECT_ENABLED -void Object::CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) { - const Class* c = GetClass(); - if (Runtime::Current()->GetClassLinker() == NULL || - !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() || - !c->IsResolved()) { - return; - } - for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) { - ObjectArray<Field>* fields = cur->GetIFields(); - if (fields != NULL) { - size_t num_ref_ifields = cur->NumReferenceInstanceFields(); - for (size_t i = 0; i < num_ref_ifields; ++i) { - Field* field = fields->Get(i); - if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { - FieldHelper fh(field); - CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); - return; - } - } - } - } - if (c->IsArrayClass()) { - // Bounds and assign-ability done in the array setter. - return; - } - if (IsClass()) { - ObjectArray<Field>* fields = AsClass()->GetSFields(); - if (fields != NULL) { - size_t num_ref_sfields = AsClass()->NumReferenceStaticFields(); - for (size_t i = 0; i < num_ref_sfields; ++i) { - Field* field = fields->Get(i); - if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { - FieldHelper fh(field); - CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); - return; - } - } - } - } - LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this) - << " of type " << PrettyDescriptor(c) << " at offset " << field_offset; -} -#endif - -// TODO: get global references for these -Class* Field::java_lang_reflect_Field_ = NULL; - -void Field::SetClass(Class* java_lang_reflect_Field) { - CHECK(java_lang_reflect_Field_ == NULL); - CHECK(java_lang_reflect_Field != NULL); - java_lang_reflect_Field_ = java_lang_reflect_Field; -} - -void Field::ResetClass() { - CHECK(java_lang_reflect_Field_ != NULL); - java_lang_reflect_Field_ = NULL; -} - -void Field::SetOffset(MemberOffset num_bytes) { - DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); -#if 0 // TODO enable later in boot and under !NDEBUG - FieldHelper fh(this); - Primitive::Type type = fh.GetTypeAsPrimitiveType(); - if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) { - DCHECK_ALIGNED(num_bytes.Uint32Value(), 8); - } -#endif - SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false); -} - -uint32_t Field::Get32(const Object* object) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - return object->GetField32(GetOffset(), IsVolatile()); -} - -void Field::Set32(Object* object, uint32_t new_value) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - object->SetField32(GetOffset(), new_value, IsVolatile()); -} - -uint64_t Field::Get64(const Object* object) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - return object->GetField64(GetOffset(), IsVolatile()); -} - -void Field::Set64(Object* object, uint64_t new_value) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - object->SetField64(GetOffset(), new_value, IsVolatile()); -} - -Object* Field::GetObj(const Object* object) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - return object->GetFieldObject<Object*>(GetOffset(), IsVolatile()); -} - -void Field::SetObj(Object* object, const Object* new_value) const { - DCHECK(object != NULL) << PrettyField(this); - DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); - object->SetFieldObject(GetOffset(), new_value, IsVolatile()); -} - -bool Field::GetBoolean(const Object* object) const { - DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - return Get32(object); -} - -void Field::SetBoolean(Object* object, bool z) const { - DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Set32(object, z); -} - -int8_t Field::GetByte(const Object* object) const { - DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - return Get32(object); -} - -void Field::SetByte(Object* object, int8_t b) const { - DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Set32(object, b); -} - -uint16_t Field::GetChar(const Object* object) const { - DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - return Get32(object); -} - -void Field::SetChar(Object* object, uint16_t c) const { - DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Set32(object, c); -} - -int16_t Field::GetShort(const Object* object) const { - DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - return Get32(object); -} - -void Field::SetShort(Object* object, int16_t s) const { - DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Set32(object, s); -} - -int32_t Field::GetInt(const Object* object) const { -#ifndef NDEBUG - Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); - CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); -#endif - return Get32(object); -} - -void Field::SetInt(Object* object, int32_t i) const { -#ifndef NDEBUG - Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); - CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); -#endif - Set32(object, i); -} - -int64_t Field::GetLong(const Object* object) const { -#ifndef NDEBUG - Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); - CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); -#endif - return Get64(object); -} - -void Field::SetLong(Object* object, int64_t j) const { -#ifndef NDEBUG - Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType(); - CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); -#endif - Set64(object, j); -} - -union Bits { - jdouble d; - jfloat f; - jint i; - jlong j; -}; - -float Field::GetFloat(const Object* object) const { - DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Bits bits; - bits.i = Get32(object); - return bits.f; -} - -void Field::SetFloat(Object* object, float f) const { - DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Bits bits; - bits.f = f; - Set32(object, bits.i); -} - -double Field::GetDouble(const Object* object) const { - DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Bits bits; - bits.j = Get64(object); - return bits.d; -} - -void Field::SetDouble(Object* object, double d) const { - DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - Bits bits; - bits.d = d; - Set64(object, bits.j); -} - -Object* Field::GetObject(const Object* object) const { - DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - return GetObj(object); -} - -void Field::SetObject(Object* object, const Object* l) const { - DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType()) - << PrettyField(this); - SetObj(object, l); -} - -// TODO: get global references for these -Class* AbstractMethod::java_lang_reflect_Constructor_ = NULL; -Class* AbstractMethod::java_lang_reflect_Method_ = NULL; - -InvokeType AbstractMethod::GetInvokeType() const { - // TODO: kSuper? - if (GetDeclaringClass()->IsInterface()) { - return kInterface; - } else if (IsStatic()) { - return kStatic; - } else if (IsDirect()) { - return kDirect; - } else { - return kVirtual; - } -} - -void AbstractMethod::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) { - CHECK(java_lang_reflect_Constructor_ == NULL); - CHECK(java_lang_reflect_Constructor != NULL); - java_lang_reflect_Constructor_ = java_lang_reflect_Constructor; - - CHECK(java_lang_reflect_Method_ == NULL); - CHECK(java_lang_reflect_Method != NULL); - java_lang_reflect_Method_ = java_lang_reflect_Method; -} - -void AbstractMethod::ResetClasses() { - CHECK(java_lang_reflect_Constructor_ != NULL); - java_lang_reflect_Constructor_ = NULL; - - CHECK(java_lang_reflect_Method_ != NULL); - java_lang_reflect_Method_ = NULL; -} - -ObjectArray<String>* AbstractMethod::GetDexCacheStrings() const { - return GetFieldObject<ObjectArray<String>*>( - OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), false); -} - -void AbstractMethod::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), - new_dex_cache_strings, false); -} - -ObjectArray<AbstractMethod>* AbstractMethod::GetDexCacheResolvedMethods() const { - return GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), false); -} - -void AbstractMethod::SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), - new_dex_cache_methods, false); -} - -ObjectArray<Class>* AbstractMethod::GetDexCacheResolvedTypes() const { - return GetFieldObject<ObjectArray<Class>*>( - OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), false); -} - -void AbstractMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), - new_dex_cache_classes, false); -} - -ObjectArray<StaticStorageBase>* AbstractMethod::GetDexCacheInitializedStaticStorage() const { - return GetFieldObject<ObjectArray<StaticStorageBase>*>( - OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), - false); -} - -void AbstractMethod::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), - new_value, false); -} - -size_t AbstractMethod::NumArgRegisters(const StringPiece& shorty) { - CHECK_LE(1, shorty.length()); - uint32_t num_registers = 0; - for (int i = 1; i < shorty.length(); ++i) { - char ch = shorty[i]; - if (ch == 'D' || ch == 'J') { - num_registers += 2; - } else { - num_registers += 1; - } - } - return num_registers; -} - -bool AbstractMethod::IsProxyMethod() const { - return GetDeclaringClass()->IsProxyClass(); -} - -AbstractMethod* AbstractMethod::FindOverriddenMethod() const { - if (IsStatic()) { - return NULL; - } - Class* declaring_class = GetDeclaringClass(); - Class* super_class = declaring_class->GetSuperClass(); - uint16_t method_index = GetMethodIndex(); - ObjectArray<AbstractMethod>* super_class_vtable = super_class->GetVTable(); - AbstractMethod* result = NULL; - // Did this method override a super class method? If so load the result from the super class' - // vtable - if (super_class_vtable != NULL && method_index < super_class_vtable->GetLength()) { - result = super_class_vtable->Get(method_index); - } else { - // Method didn't override superclass method so search interfaces - if (IsProxyMethod()) { - result = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex()); - CHECK_EQ(result, - Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this)); - } else { - MethodHelper mh(this); - MethodHelper interface_mh; - IfTable* iftable = GetDeclaringClass()->GetIfTable(); - for (size_t i = 0; i < iftable->Count() && result == NULL; i++) { - Class* interface = iftable->GetInterface(i); - for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { - AbstractMethod* interface_method = interface->GetVirtualMethod(j); - interface_mh.ChangeMethod(interface_method); - if (mh.HasSameNameAndSignature(&interface_mh)) { - result = interface_method; - break; - } - } - } - } - } -#ifndef NDEBUG - MethodHelper result_mh(result); - DCHECK(result == NULL || MethodHelper(this).HasSameNameAndSignature(&result_mh)); -#endif - return result; -} - -static const void* GetOatCode(const AbstractMethod* m) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Runtime* runtime = Runtime::Current(); - const void* code = m->GetCode(); - // Peel off any method tracing trampoline. - if (runtime->IsMethodTracingActive() && runtime->GetInstrumentation()->GetSavedCodeFromMap(m) != NULL) { - code = runtime->GetInstrumentation()->GetSavedCodeFromMap(m); - } - // Peel off any resolution stub. - if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) { - code = runtime->GetClassLinker()->GetOatCodeFor(m); - } - return code; -} - -uintptr_t AbstractMethod::NativePcOffset(const uintptr_t pc) const { - return pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); -} - -// Find the lowest-address native safepoint pc for a given dex pc -uintptr_t AbstractMethod::ToFirstNativeSafepointPc(const uint32_t dex_pc) const { -#if !defined(ART_USE_LLVM_COMPILER) - const uint32_t* mapping_table = GetPcToDexMappingTable(); - if (mapping_table == NULL) { - DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); - return DexFile::kDexNoIndex; // Special no mapping case - } - size_t mapping_table_length = GetPcToDexMappingTableLength(); - for (size_t i = 0; i < mapping_table_length; i += 2) { - if (mapping_table[i + 1] == dex_pc) { - return mapping_table[i] + reinterpret_cast<uintptr_t>(GetOatCode(this)); - } - } - LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc - << " in " << PrettyMethod(this); - return 0; -#else - // Compiler LLVM doesn't use the machine pc, we just use dex pc instead. - return static_cast<uint32_t>(dex_pc); -#endif -} - -uint32_t AbstractMethod::ToDexPc(const uintptr_t pc) const { -#if !defined(ART_USE_LLVM_COMPILER) - const uint32_t* mapping_table = GetPcToDexMappingTable(); - if (mapping_table == NULL) { - DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); - return DexFile::kDexNoIndex; // Special no mapping case - } - size_t mapping_table_length = GetPcToDexMappingTableLength(); - uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); - for (size_t i = 0; i < mapping_table_length; i += 2) { - if (mapping_table[i] == sought_offset) { - return mapping_table[i + 1]; - } - } - LOG(ERROR) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset) - << "(PC " << reinterpret_cast<void*>(pc) << ") in " << PrettyMethod(this); - return DexFile::kDexNoIndex; -#else - // Compiler LLVM doesn't use the machine pc, we just use dex pc instead. - return static_cast<uint32_t>(pc); -#endif -} - -uintptr_t AbstractMethod::ToNativePc(const uint32_t dex_pc) const { - const uint32_t* mapping_table = GetDexToPcMappingTable(); - if (mapping_table == NULL) { - DCHECK_EQ(dex_pc, 0U); - return 0; // Special no mapping/pc == 0 case - } - size_t mapping_table_length = GetDexToPcMappingTableLength(); - for (size_t i = 0; i < mapping_table_length; i += 2) { - uint32_t map_offset = mapping_table[i]; - uint32_t map_dex_offset = mapping_table[i + 1]; - if (map_dex_offset == dex_pc) { - return reinterpret_cast<uintptr_t>(GetOatCode(this)) + map_offset; - } - } - LOG(FATAL) << "Looking up Dex PC not contained in method, 0x" << std::hex << dex_pc - << " in " << PrettyMethod(this); - return 0; -} - -uint32_t AbstractMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const { - MethodHelper mh(this); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); - // Iterate over the catch handlers associated with dex_pc - for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) { - uint16_t iter_type_idx = it.GetHandlerTypeIndex(); - // Catch all case - if (iter_type_idx == DexFile::kDexNoIndex16) { - return it.GetHandlerAddress(); - } - // Does this catch exception type apply? - Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); - if (iter_exception_type == NULL) { - // The verifier should take care of resolving all exception classes early - LOG(WARNING) << "Unresolved exception class when finding catch block: " - << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx); - } else if (iter_exception_type->IsAssignableFrom(exception_type)) { - return it.GetHandlerAddress(); - } - } - // Handler not found - return DexFile::kDexNoIndex; -} - -void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) { - if (kIsDebugBuild) { - self->AssertThreadSuspensionIsAllowable(); - CHECK_EQ(kRunnable, self->GetState()); - } - - // Push a transition back into managed code onto the linked list in thread. - ManagedStack fragment; - self->PushManagedStackFragment(&fragment); - - // Call the invoke stub associated with the method. - // Pass everything as arguments. - AbstractMethod::InvokeStub* stub = GetInvokeStub(); - - if (UNLIKELY(!Runtime::Current()->IsStarted())){ - LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started"; - if (result != NULL) { - result->SetJ(0); - } - } else { - bool interpret = self->ReadFlag(kEnterInterpreter) && !IsNative() && !IsProxyMethod(); - const bool kLogInvocationStartAndReturn = false; - if (!interpret && GetCode() != NULL && stub != NULL) { - if (kLogInvocationStartAndReturn) { - LOG(INFO) << StringPrintf("Invoking '%s' code=%p stub=%p", - PrettyMethod(this).c_str(), GetCode(), stub); - } - (*stub)(this, receiver, self, args, result); - if (kLogInvocationStartAndReturn) { - LOG(INFO) << StringPrintf("Returned '%s' code=%p stub=%p", - PrettyMethod(this).c_str(), GetCode(), stub); - } - } else { - const bool kInterpretMethodsWithNoCode = false; - if (interpret || kInterpretMethodsWithNoCode) { - if (kLogInvocationStartAndReturn) { - LOG(INFO) << "Interpreting " << PrettyMethod(this) << "'"; - } - art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args, result); - if (kLogInvocationStartAndReturn) { - LOG(INFO) << "Returned '" << PrettyMethod(this) << "'"; - } - } else { - LOG(INFO) << "Not invoking '" << PrettyMethod(this) - << "' code=" << reinterpret_cast<const void*>(GetCode()) - << " stub=" << reinterpret_cast<void*>(stub); - if (result != NULL) { - result->SetJ(0); - } - } - } - } - - // Pop transition. - self->PopManagedStackFragment(fragment); -} - -bool AbstractMethod::IsRegistered() const { - void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), false); - CHECK(native_method != NULL); - void* jni_stub = Runtime::Current()->GetJniDlsymLookupStub()->GetData(); - return native_method != jni_stub; -} - -void AbstractMethod::RegisterNative(Thread* self, const void* native_method) { - DCHECK(Thread::Current() == self); - CHECK(IsNative()) << PrettyMethod(this); - CHECK(native_method != NULL) << PrettyMethod(this); -#if defined(ART_USE_LLVM_COMPILER) - SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), - native_method, false); -#else - if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) { - SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), - native_method, false); - } else { - // We've been asked to associate this method with the given native method but are working - // around JNI bugs, that include not giving Object** SIRT references to native methods. Direct - // the native method to runtime support and store the target somewhere runtime support will - // find it. -#if defined(__arm__) - SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), - reinterpret_cast<const void*>(art_work_around_app_jni_bugs), false); -#else - UNIMPLEMENTED(FATAL); -#endif - SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), - reinterpret_cast<const uint8_t*>(native_method), false); - } -#endif -} - -void AbstractMethod::UnregisterNative(Thread* self) { - CHECK(IsNative()) << PrettyMethod(this); - // restore stub to lookup native pointer via dlsym - RegisterNative(self, Runtime::Current()->GetJniDlsymLookupStub()->GetData()); -} - -Class* Class::java_lang_Class_ = NULL; - -void Class::SetClassClass(Class* java_lang_Class) { - CHECK(java_lang_Class_ == NULL) << java_lang_Class_ << " " << java_lang_Class; - CHECK(java_lang_Class != NULL); - java_lang_Class_ = java_lang_Class; -} - -void Class::ResetClass() { - CHECK(java_lang_Class_ != NULL); - java_lang_Class_ = NULL; -} - -void Class::SetStatus(Status new_status) { - CHECK(new_status > GetStatus() || new_status == kStatusError || !Runtime::Current()->IsStarted()) - << PrettyClass(this) << " " << GetStatus() << " -> " << new_status; - CHECK(sizeof(Status) == sizeof(uint32_t)) << PrettyClass(this); - if (new_status > kStatusResolved) { - CHECK_EQ(GetThinLockId(), Thread::Current()->GetThinLockId()) << PrettyClass(this); - } - if (new_status == kStatusError) { - CHECK_NE(GetStatus(), kStatusError) << PrettyClass(this); - - // stash current exception - Thread* self = Thread::Current(); - SirtRef<Throwable> exception(self, self->GetException()); - CHECK(exception.get() != NULL); - - // clear exception to call FindSystemClass - self->ClearException(); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* eiie_class = class_linker->FindSystemClass("Ljava/lang/ExceptionInInitializerError;"); - CHECK(!self->IsExceptionPending()); - - // only verification errors, not initialization problems, should set a verify error. - // this is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case. - Class* exception_class = exception->GetClass(); - if (!eiie_class->IsAssignableFrom(exception_class)) { - SetVerifyErrorClass(exception_class); - } - - // restore exception - self->SetException(exception.get()); - } - return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status, false); -} - -DexCache* Class::GetDexCache() const { - return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false); -} - -void Class::SetDexCache(DexCache* new_dex_cache) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false); -} - -Object* Class::AllocObject(Thread* self) { - DCHECK(!IsArrayClass()) << PrettyClass(this); - DCHECK(IsInstantiable()) << PrettyClass(this); - // TODO: decide whether we want this check. It currently fails during bootstrap. - // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); - DCHECK_GE(this->object_size_, sizeof(Object)); - return Runtime::Current()->GetHeap()->AllocObject(self, this, this->object_size_); -} - -void Class::SetClassSize(size_t new_class_size) { - DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this); - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false); -} - -// Return the class' name. The exact format is bizarre, but it's the specified behavior for -// Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int" -// but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than -// slashes (so "java.lang.String" but "[Ljava.lang.String;"). Madness. -String* Class::ComputeName() { - String* name = GetName(); - if (name != NULL) { - return name; - } - std::string descriptor(ClassHelper(this).GetDescriptor()); - if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { - // The descriptor indicates that this is the class for - // a primitive type; special-case the return value. - const char* c_name = NULL; - switch (descriptor[0]) { - case 'Z': c_name = "boolean"; break; - case 'B': c_name = "byte"; break; - case 'C': c_name = "char"; break; - case 'S': c_name = "short"; break; - case 'I': c_name = "int"; break; - case 'J': c_name = "long"; break; - case 'F': c_name = "float"; break; - case 'D': c_name = "double"; break; - case 'V': c_name = "void"; break; - default: - LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]); - } - name = String::AllocFromModifiedUtf8(Thread::Current(), c_name); - } else { - // Convert the UTF-8 name to a java.lang.String. The name must use '.' to separate package - // components. - if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') { - descriptor.erase(0, 1); - descriptor.erase(descriptor.size() - 1); - } - std::replace(descriptor.begin(), descriptor.end(), '/', '.'); - name = String::AllocFromModifiedUtf8(Thread::Current(), descriptor.c_str()); - } - SetName(name); - return name; -} - -void Class::DumpClass(std::ostream& os, int flags) const { - if ((flags & kDumpClassFullDetail) == 0) { - os << PrettyClass(this); - if ((flags & kDumpClassClassLoader) != 0) { - os << ' ' << GetClassLoader(); - } - if ((flags & kDumpClassInitialized) != 0) { - os << ' ' << GetStatus(); - } - os << "\n"; - return; - } - - Class* super = GetSuperClass(); - ClassHelper kh(this); - os << "----- " << (IsInterface() ? "interface" : "class") << " " - << "'" << kh.GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n", - os << " objectSize=" << SizeOf() << " " - << "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n", - os << StringPrintf(" access=0x%04x.%04x\n", - GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask); - if (super != NULL) { - os << " super='" << PrettyClass(super) << "' (cl=" << super->GetClassLoader() << ")\n"; - } - if (IsArrayClass()) { - os << " componentType=" << PrettyClass(GetComponentType()) << "\n"; - } - if (kh.NumDirectInterfaces() > 0) { - os << " interfaces (" << kh.NumDirectInterfaces() << "):\n"; - for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) { - Class* interface = kh.GetDirectInterface(i); - const ClassLoader* cl = interface->GetClassLoader(); - os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl); - } - } - os << " vtable (" << NumVirtualMethods() << " entries, " - << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n"; - for (size_t i = 0; i < NumVirtualMethods(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str()); - } - os << " direct methods (" << NumDirectMethods() << " entries):\n"; - for (size_t i = 0; i < NumDirectMethods(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetDirectMethod(i)).c_str()); - } - if (NumStaticFields() > 0) { - os << " static fields (" << NumStaticFields() << " entries):\n"; - if (IsResolved() || IsErroneous()) { - for (size_t i = 0; i < NumStaticFields(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetStaticField(i)).c_str()); - } - } else { - os << " <not yet available>"; - } - } - if (NumInstanceFields() > 0) { - os << " instance fields (" << NumInstanceFields() << " entries):\n"; - if (IsResolved() || IsErroneous()) { - for (size_t i = 0; i < NumInstanceFields(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetInstanceField(i)).c_str()); - } - } else { - os << " <not yet available>"; - } - } -} - -void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) { - if (new_reference_offsets != CLASS_WALK_SUPER) { - // Sanity check that the number of bits set in the reference offset bitmap - // agrees with the number of references - size_t count = 0; - for (Class* c = this; c != NULL; c = c->GetSuperClass()) { - count += c->NumReferenceInstanceFieldsDuringLinking(); - } - CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), count); - } - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), - new_reference_offsets, false); -} - -void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) { - if (new_reference_offsets != CLASS_WALK_SUPER) { - // Sanity check that the number of bits set in the reference offset bitmap - // agrees with the number of references - CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), - NumReferenceStaticFieldsDuringLinking()); - } - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), - new_reference_offsets, false); -} - -bool Class::Implements(const Class* klass) const { - DCHECK(klass != NULL); - DCHECK(klass->IsInterface()) << PrettyClass(this); - // All interfaces implemented directly and by our superclass, and - // recursively all super-interfaces of those interfaces, are listed - // in iftable_, so we can just do a linear scan through that. - int32_t iftable_count = GetIfTableCount(); - IfTable* iftable = GetIfTable(); - for (int32_t i = 0; i < iftable_count; i++) { - if (iftable->GetInterface(i) == klass) { - return true; - } - } - return false; -} - -// Determine whether "this" is assignable from "src", where both of these -// are array classes. -// -// Consider an array class, e.g. Y[][], where Y is a subclass of X. -// Y[][] = Y[][] --> true (identity) -// X[][] = Y[][] --> true (element superclass) -// Y = Y[][] --> false -// Y[] = Y[][] --> false -// Object = Y[][] --> true (everything is an object) -// Object[] = Y[][] --> true -// Object[][] = Y[][] --> true -// Object[][][] = Y[][] --> false (too many []s) -// Serializable = Y[][] --> true (all arrays are Serializable) -// Serializable[] = Y[][] --> true -// Serializable[][] = Y[][] --> false (unless Y is Serializable) -// -// Don't forget about primitive types. -// Object[] = int[] --> false -// -bool Class::IsArrayAssignableFromArray(const Class* src) const { - DCHECK(IsArrayClass()) << PrettyClass(this); - DCHECK(src->IsArrayClass()) << PrettyClass(src); - return GetComponentType()->IsAssignableFrom(src->GetComponentType()); -} - -bool Class::IsAssignableFromArray(const Class* src) const { - DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom - DCHECK(src->IsArrayClass()) << PrettyClass(src); - if (!IsArrayClass()) { - // If "this" is not also an array, it must be Object. - // src's super should be java_lang_Object, since it is an array. - Class* java_lang_Object = src->GetSuperClass(); - DCHECK(java_lang_Object != NULL) << PrettyClass(src); - DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src); - return this == java_lang_Object; - } - return IsArrayAssignableFromArray(src); -} - -bool Class::IsSubClass(const Class* klass) const { - DCHECK(!IsInterface()) << PrettyClass(this); - DCHECK(!IsArrayClass()) << PrettyClass(this); - const Class* current = this; - do { - if (current == klass) { - return true; - } - current = current->GetSuperClass(); - } while (current != NULL); - return false; -} - -bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) { - size_t i = 0; - while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) { - ++i; - } - if (descriptor1.find('/', i) != StringPiece::npos || - descriptor2.find('/', i) != StringPiece::npos) { - return false; - } else { - return true; - } -} - -bool Class::IsInSamePackage(const Class* that) const { - const Class* klass1 = this; - const Class* klass2 = that; - if (klass1 == klass2) { - return true; - } - // Class loaders must match. - if (klass1->GetClassLoader() != klass2->GetClassLoader()) { - return false; - } - // Arrays are in the same package when their element classes are. - while (klass1->IsArrayClass()) { - klass1 = klass1->GetComponentType(); - } - while (klass2->IsArrayClass()) { - klass2 = klass2->GetComponentType(); - } - // Compare the package part of the descriptor string. - ClassHelper kh(klass1); - std::string descriptor1(kh.GetDescriptor()); - kh.ChangeClass(klass2); - std::string descriptor2(kh.GetDescriptor()); - return IsInSamePackage(descriptor1, descriptor2); -} - -bool Class::IsClassClass() const { - Class* java_lang_Class = GetClass()->GetClass(); - return this == java_lang_Class; -} - -bool Class::IsStringClass() const { - return this == String::GetJavaLangString(); -} - -bool Class::IsThrowableClass() const { - return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this); -} - -bool Class::IsFieldClass() const { - Class* java_lang_Class = GetClass(); - Class* java_lang_reflect_Field = java_lang_Class->GetInstanceField(0)->GetClass(); - return this == java_lang_reflect_Field; - -} - -bool Class::IsMethodClass() const { - return (this == AbstractMethod::GetMethodClass()) || - (this == AbstractMethod::GetConstructorClass()); - -} - -ClassLoader* Class::GetClassLoader() const { - return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false); -} - -void Class::SetClassLoader(ClassLoader* new_class_loader) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false); -} - -AbstractMethod* Class::FindVirtualMethodForInterface(AbstractMethod* method) { - Class* declaring_class = method->GetDeclaringClass(); - DCHECK(declaring_class != NULL) << PrettyClass(this); - DCHECK(declaring_class->IsInterface()) << PrettyMethod(method); - // TODO cache to improve lookup speed - int32_t iftable_count = GetIfTableCount(); - IfTable* iftable = GetIfTable(); - for (int32_t i = 0; i < iftable_count; i++) { - if (iftable->GetInterface(i) == declaring_class) { - return iftable->GetMethodArray(i)->Get(method->GetMethodIndex()); - } - } - return NULL; -} - -AbstractMethod* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature) const { - // Check the current class before checking the interfaces. - AbstractMethod* method = FindDeclaredVirtualMethod(name, signature); - if (method != NULL) { - return method; - } - - int32_t iftable_count = GetIfTableCount(); - IfTable* iftable = GetIfTable(); - for (int32_t i = 0; i < iftable_count; i++) { - method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature); - if (method != NULL) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { - // Check the current class before checking the interfaces. - AbstractMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx); - if (method != NULL) { - return method; - } - - int32_t iftable_count = GetIfTableCount(); - IfTable* iftable = GetIfTable(); - for (int32_t i = 0; i < iftable_count; i++) { - method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(dex_cache, dex_method_idx); - if (method != NULL) { - return method; - } - } - return NULL; -} - - -AbstractMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const { - MethodHelper mh; - for (size_t i = 0; i < NumDirectMethods(); ++i) { - AbstractMethod* method = GetDirectMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { - if (GetDexCache() == dex_cache) { - for (size_t i = 0; i < NumDirectMethods(); ++i) { - AbstractMethod* method = GetDirectMethod(i); - if (method->GetDexMethodIndex() == dex_method_idx) { - return method; - } - } - } - return NULL; -} - -AbstractMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const { - for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { - AbstractMethod* method = klass->FindDeclaredDirectMethod(name, signature); - if (method != NULL) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { - for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { - AbstractMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx); - if (method != NULL) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, - const StringPiece& signature) const { - MethodHelper mh; - for (size_t i = 0; i < NumVirtualMethods(); ++i) { - AbstractMethod* method = GetVirtualMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { - if (GetDexCache() == dex_cache) { - for (size_t i = 0; i < NumVirtualMethods(); ++i) { - AbstractMethod* method = GetVirtualMethod(i); - if (method->GetDexMethodIndex() == dex_method_idx) { - return method; - } - } - } - return NULL; -} - -AbstractMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const { - for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { - AbstractMethod* method = klass->FindDeclaredVirtualMethod(name, signature); - if (method != NULL) { - return method; - } - } - return NULL; -} - -AbstractMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const { - for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) { - AbstractMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx); - if (method != NULL) { - return method; - } - } - return NULL; -} - -Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) { - // Is the field in this class? - // Interfaces are not relevant because they can't contain instance fields. - FieldHelper fh; - for (size_t i = 0; i < NumInstanceFields(); ++i) { - Field* f = GetInstanceField(i); - fh.ChangeField(f); - if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { - return f; - } - } - return NULL; -} - -Field* Class::FindDeclaredInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) { - if (GetDexCache() == dex_cache) { - for (size_t i = 0; i < NumInstanceFields(); ++i) { - Field* f = GetInstanceField(i); - if (f->GetDexFieldIndex() == dex_field_idx) { - return f; - } - } - } - return NULL; -} - -Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& type) { - // Is the field in this class, or any of its superclasses? - // Interfaces are not relevant because they can't contain instance fields. - for (Class* c = this; c != NULL; c = c->GetSuperClass()) { - Field* f = c->FindDeclaredInstanceField(name, type); - if (f != NULL) { - return f; - } - } - return NULL; -} - -Field* Class::FindInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) { - // Is the field in this class, or any of its superclasses? - // Interfaces are not relevant because they can't contain instance fields. - for (Class* c = this; c != NULL; c = c->GetSuperClass()) { - Field* f = c->FindDeclaredInstanceField(dex_cache, dex_field_idx); - if (f != NULL) { - return f; - } - } - return NULL; -} - -Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) { - DCHECK(type != NULL); - FieldHelper fh; - for (size_t i = 0; i < NumStaticFields(); ++i) { - Field* f = GetStaticField(i); - fh.ChangeField(f); - if (name == fh.GetName() && type == fh.GetTypeDescriptor()) { - return f; - } - } - return NULL; -} - -Field* Class::FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) { - if (dex_cache == GetDexCache()) { - for (size_t i = 0; i < NumStaticFields(); ++i) { - Field* f = GetStaticField(i); - if (f->GetDexFieldIndex() == dex_field_idx) { - return f; - } - } - } - return NULL; -} - -Field* Class::FindStaticField(const StringPiece& name, const StringPiece& type) { - // Is the field in this class (or its interfaces), or any of its - // superclasses (or their interfaces)? - ClassHelper kh; - for (Class* k = this; k != NULL; k = k->GetSuperClass()) { - // Is the field in this class? - Field* f = k->FindDeclaredStaticField(name, type); - if (f != NULL) { - return f; - } - // Is this field in any of this class' interfaces? - kh.ChangeClass(k); - for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { - Class* interface = kh.GetDirectInterface(i); - f = interface->FindStaticField(name, type); - if (f != NULL) { - return f; - } - } - } - return NULL; -} - -Field* Class::FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) { - ClassHelper kh; - for (Class* k = this; k != NULL; k = k->GetSuperClass()) { - // Is the field in this class? - Field* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx); - if (f != NULL) { - return f; - } - // Is this field in any of this class' interfaces? - kh.ChangeClass(k); - for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { - Class* interface = kh.GetDirectInterface(i); - f = interface->FindStaticField(dex_cache, dex_field_idx); - if (f != NULL) { - return f; - } - } - } - return NULL; -} - -Field* Class::FindField(const StringPiece& name, const StringPiece& type) { - // Find a field using the JLS field resolution order - ClassHelper kh; - for (Class* k = this; k != NULL; k = k->GetSuperClass()) { - // Is the field in this class? - Field* f = k->FindDeclaredInstanceField(name, type); - if (f != NULL) { - return f; - } - f = k->FindDeclaredStaticField(name, type); - if (f != NULL) { - return f; - } - // Is this field in any of this class' interfaces? - kh.ChangeClass(k); - for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) { - Class* interface = kh.GetDirectInterface(i); - f = interface->FindStaticField(name, type); - if (f != NULL) { - return f; - } - } - } - return NULL; -} - -Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, - size_t component_size) { - DCHECK(array_class != NULL); - DCHECK_GE(component_count, 0); - DCHECK(array_class->IsArrayClass()); - - size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); - size_t data_size = component_count * component_size; - size_t size = header_size + data_size; - - // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. - size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size); - if (data_size >> component_shift != size_t(component_count) || size < data_size) { - self->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;", - "%s of length %d would overflow", - PrettyDescriptor(array_class).c_str(), component_count); - return NULL; - } - - Heap* heap = Runtime::Current()->GetHeap(); - Array* array = down_cast<Array*>(heap->AllocObject(self, array_class, size)); - if (array != NULL) { - DCHECK(array->IsArrayInstance()); - array->SetLength(component_count); - } - return array; -} - -Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) { - DCHECK(array_class->IsArrayClass()); - return Alloc(self, array_class, component_count, array_class->GetComponentSize()); -} - -// Create a multi-dimensional array of Objects or primitive types. -// -// We have to generate the names for X[], X[][], X[][][], and so on. The -// easiest way to deal with that is to create the full name once and then -// subtract pieces off. Besides, we want to start with the outermost -// piece and work our way in. -// Recursively create an array with multiple dimensions. Elements may be -// Objects or primitive types. -static Array* RecursiveCreateMultiArray(Thread* self, Class* array_class, int current_dimension, - IntArray* dimensions) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - int32_t array_length = dimensions->Get(current_dimension); - SirtRef<Array> new_array(self, Array::Alloc(self, array_class, array_length)); - if (UNLIKELY(new_array.get() == NULL)) { - CHECK(self->IsExceptionPending()); - return NULL; - } - if ((current_dimension + 1) < dimensions->GetLength()) { - // Create a new sub-array in every element of the array. - for (int32_t i = 0; i < array_length; i++) { - Array* sub_array = RecursiveCreateMultiArray(self, array_class->GetComponentType(), - current_dimension + 1, dimensions); - if (UNLIKELY(sub_array == NULL)) { - CHECK(self->IsExceptionPending()); - return NULL; - } - new_array->AsObjectArray<Array>()->Set(i, sub_array); - } - } - return new_array.get(); -} - -Array* Array::CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) { - // Verify dimensions. - // - // The caller is responsible for verifying that "dimArray" is non-null - // and has a length > 0 and <= 255. - int num_dimensions = dimensions->GetLength(); - DCHECK_GT(num_dimensions, 0); - DCHECK_LE(num_dimensions, 255); - - for (int i = 0; i < num_dimensions; i++) { - int dimension = dimensions->Get(i); - if (UNLIKELY(dimension < 0)) { - self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", - "Dimension %d: %d", i, dimension); - return NULL; - } - } - - // Generate the full name of the array class. - std::string descriptor(num_dimensions, '['); - descriptor += ClassHelper(element_class).GetDescriptor(); - - // Find/generate the array class. - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader()); - if (UNLIKELY(array_class == NULL)) { - CHECK(self->IsExceptionPending()); - return NULL; - } - // create the array - Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions); - if (UNLIKELY(new_array == NULL)) { - CHECK(self->IsExceptionPending()); - return NULL; - } - return new_array; -} - -bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", - "length=%i; index=%i", length_, index); - return false; -} - -bool Array::ThrowArrayStoreException(Object* object) const { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", - "%s cannot be stored in an array of type %s", - PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str()); - return false; -} - -template<typename T> -PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { - DCHECK(array_class_ != NULL); - Array* raw_array = Array::Alloc(self, array_class_, length, sizeof(T)); - return down_cast<PrimitiveArray<T>*>(raw_array); -} - -template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL; - -// Explicitly instantiate all the primitive array types. -template class PrimitiveArray<uint8_t>; // BooleanArray -template class PrimitiveArray<int8_t>; // ByteArray -template class PrimitiveArray<uint16_t>; // CharArray -template class PrimitiveArray<double>; // DoubleArray -template class PrimitiveArray<float>; // FloatArray -template class PrimitiveArray<int32_t>; // IntArray -template class PrimitiveArray<int64_t>; // LongArray -template class PrimitiveArray<int16_t>; // ShortArray - -// Explicitly instantiate Class[][] -template class ObjectArray<ObjectArray<Class> >; - -// TODO: get global references for these -Class* String::java_lang_String_ = NULL; - -void String::SetClass(Class* java_lang_String) { - CHECK(java_lang_String_ == NULL); - CHECK(java_lang_String != NULL); - java_lang_String_ = java_lang_String; -} - -void String::ResetClass() { - CHECK(java_lang_String_ != NULL); - java_lang_String_ = NULL; -} - -String* String::Intern() { - return Runtime::Current()->GetInternTable()->InternWeak(this); -} - -int32_t String::GetHashCode() { - int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false); - if (result == 0) { - ComputeHashCode(); - } - result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false); - DCHECK(result != 0 || ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0) - << ToModifiedUtf8() << " " << result; - return result; -} - -int32_t String::GetLength() const { - int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false); - DCHECK(result >= 0 && result <= GetCharArray()->GetLength()); - return result; -} - -uint16_t String::CharAt(int32_t index) const { - // TODO: do we need this? Equals is the only caller, and could - // bounds check itself. - if (index < 0 || index >= count_) { - Thread* self = Thread::Current(); - self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;", - "length=%i; index=%i", count_, index); - return 0; - } - return GetCharArray()->Get(index + GetOffset()); -} - -String* String::AllocFromUtf16(Thread* self, - int32_t utf16_length, - const uint16_t* utf16_data_in, - int32_t hash_code) { - CHECK(utf16_data_in != NULL || utf16_length == 0); - String* string = Alloc(self, GetJavaLangString(), utf16_length); - if (string == NULL) { - return NULL; - } - // TODO: use 16-bit wide memset variant - CharArray* array = const_cast<CharArray*>(string->GetCharArray()); - if (array == NULL) { - return NULL; - } - for (int i = 0; i < utf16_length; i++) { - array->Set(i, utf16_data_in[i]); - } - if (hash_code != 0) { - string->SetHashCode(hash_code); - } else { - string->ComputeHashCode(); - } - return string; -} - - String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) { - if (utf == NULL) { - return NULL; - } - size_t char_count = CountModifiedUtf8Chars(utf); - return AllocFromModifiedUtf8(self, char_count, utf); -} - -String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, - const char* utf8_data_in) { - String* string = Alloc(self, GetJavaLangString(), utf16_length); - if (string == NULL) { - return NULL; - } - uint16_t* utf16_data_out = - const_cast<uint16_t*>(string->GetCharArray()->GetData()); - ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in); - string->ComputeHashCode(); - return string; -} - -String* String::Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) { - SirtRef<CharArray> array(self, CharArray::Alloc(self, utf16_length)); - if (array.get() == NULL) { - return NULL; - } - return Alloc(self, java_lang_String, array.get()); -} - -String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) { - // Hold reference in case AllocObject causes GC. - SirtRef<CharArray> array_ref(self, array); - String* string = down_cast<String*>(java_lang_String->AllocObject(self)); - if (string == NULL) { - return NULL; - } - string->SetArray(array); - string->SetCount(array->GetLength()); - return string; -} - -bool String::Equals(const String* that) const { - if (this == that) { - // Quick reference equality test - return true; - } else if (that == NULL) { - // Null isn't an instanceof anything - return false; - } else if (this->GetLength() != that->GetLength()) { - // Quick length inequality test - return false; - } else { - // Note: don't short circuit on hash code as we're presumably here as the - // hash code was already equal - for (int32_t i = 0; i < that->GetLength(); ++i) { - if (this->CharAt(i) != that->CharAt(i)) { - return false; - } - } - return true; - } -} - -bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) const { - if (this->GetLength() != that_length) { - return false; - } else { - for (int32_t i = 0; i < that_length; ++i) { - if (this->CharAt(i) != that_chars[that_offset + i]) { - return false; - } - } - return true; - } -} - -bool String::Equals(const char* modified_utf8) const { - for (int32_t i = 0; i < GetLength(); ++i) { - uint16_t ch = GetUtf16FromUtf8(&modified_utf8); - if (ch == '\0' || ch != CharAt(i)) { - return false; - } - } - return *modified_utf8 == '\0'; -} - -bool String::Equals(const StringPiece& modified_utf8) const { - if (modified_utf8.size() != GetLength()) { - return false; - } - const char* p = modified_utf8.data(); - for (int32_t i = 0; i < GetLength(); ++i) { - uint16_t ch = GetUtf16FromUtf8(&p); - if (ch != CharAt(i)) { - return false; - } - } - return true; -} - -// Create a modified UTF-8 encoded std::string from a java/lang/String object. -std::string String::ToModifiedUtf8() const { - const uint16_t* chars = GetCharArray()->GetData() + GetOffset(); - size_t byte_count = GetUtfLength(); - std::string result(byte_count, static_cast<char>(0)); - ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength()); - return result; -} - -#ifdef HAVE__MEMCMP16 -// "count" is in 16-bit units. -extern "C" uint32_t __memcmp16(const uint16_t* s0, const uint16_t* s1, size_t count); -#define MemCmp16 __memcmp16 -#else -static uint32_t MemCmp16(const uint16_t* s0, const uint16_t* s1, size_t count) { - for (size_t i = 0; i < count; i++) { - if (s0[i] != s1[i]) { - return static_cast<int32_t>(s0[i]) - static_cast<int32_t>(s1[i]); - } - } - return 0; -} -#endif - -int32_t String::CompareTo(String* rhs) const { - // Quick test for comparison of a string with itself. - const String* lhs = this; - if (lhs == rhs) { - return 0; - } - // TODO: is this still true? - // The annoying part here is that 0x00e9 - 0xffff != 0x00ea, - // because the interpreter converts the characters to 32-bit integers - // *without* sign extension before it subtracts them (which makes some - // sense since "char" is unsigned). So what we get is the result of - // 0x000000e9 - 0x0000ffff, which is 0xffff00ea. - int lhsCount = lhs->GetLength(); - int rhsCount = rhs->GetLength(); - int countDiff = lhsCount - rhsCount; - int minCount = (countDiff < 0) ? lhsCount : rhsCount; - const uint16_t* lhsChars = lhs->GetCharArray()->GetData() + lhs->GetOffset(); - const uint16_t* rhsChars = rhs->GetCharArray()->GetData() + rhs->GetOffset(); - int otherRes = MemCmp16(lhsChars, rhsChars, minCount); - if (otherRes != 0) { - return otherRes; - } - return countDiff; -} - -void Throwable::SetCause(Throwable* cause) { - CHECK(cause != NULL); - CHECK(cause != this); - CHECK(GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false) == NULL); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false); -} - -bool Throwable::IsCheckedException() const { - if (InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_Error))) { - return false; - } - return !InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_RuntimeException)); -} - -std::string Throwable::Dump() const { - std::string result(PrettyTypeOf(this)); - result += ": "; - String* msg = GetDetailMessage(); - if (msg != NULL) { - result += msg->ToModifiedUtf8(); - } - result += "\n"; - Object* stack_state = GetStackState(); - // check stack state isn't missing or corrupt - if (stack_state != NULL && stack_state->IsObjectArray()) { - // Decode the internal stack trace into the depth and method trace - ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state); - int32_t depth = method_trace->GetLength() - 1; - IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); - MethodHelper mh; - for (int32_t i = 0; i < depth; ++i) { - AbstractMethod* method = down_cast<AbstractMethod*>(method_trace->Get(i)); - mh.ChangeMethod(method); - uint32_t dex_pc = pc_trace->Get(i); - int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); - const char* source_file = mh.GetDeclaringClassSourceFile(); - result += StringPrintf(" at %s (%s:%d)\n", PrettyMethod(method, true).c_str(), - source_file, line_number); - } - } - Throwable* cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false); - if (cause != NULL && cause != this) { // Constructor makes cause == this by default. - result += "Caused by: "; - result += cause->Dump(); - } - return result; -} - - -Class* Throwable::java_lang_Throwable_ = NULL; - -void Throwable::SetClass(Class* java_lang_Throwable) { - CHECK(java_lang_Throwable_ == NULL); - CHECK(java_lang_Throwable != NULL); - java_lang_Throwable_ = java_lang_Throwable; -} - -void Throwable::ResetClass() { - CHECK(java_lang_Throwable_ != NULL); - java_lang_Throwable_ = NULL; -} - -Class* StackTraceElement::java_lang_StackTraceElement_ = NULL; - -void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) { - CHECK(java_lang_StackTraceElement_ == NULL); - CHECK(java_lang_StackTraceElement != NULL); - java_lang_StackTraceElement_ = java_lang_StackTraceElement; -} - -void StackTraceElement::ResetClass() { - CHECK(java_lang_StackTraceElement_ != NULL); - java_lang_StackTraceElement_ = NULL; -} - -StackTraceElement* StackTraceElement::Alloc(Thread* self, - String* declaring_class, - String* method_name, - String* file_name, - int32_t line_number) { - StackTraceElement* trace = - down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject(self)); - trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), - const_cast<String*>(declaring_class), false); - trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), - const_cast<String*>(method_name), false); - trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), - const_cast<String*>(file_name), false); - trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), - line_number, false); - return trace; -} - -} // namespace art diff --git a/src/object.h b/src/object.h deleted file mode 100644 index f02e312dd6..0000000000 --- a/src/object.h +++ /dev/null @@ -1,2748 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_OBJECT_H_ -#define ART_SRC_OBJECT_H_ - -#include <iosfwd> -#include <vector> - -#include "atomic.h" -#include "base/casts.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/stringpiece.h" -#include "globals.h" -#include "heap.h" -#include "invoke_type.h" -#include "modifiers.h" -#include "offsets.h" -#include "primitive.h" -#include "runtime.h" -#include "thread.h" -#include "UniquePtr.h" -#include "utf.h" - -namespace art { - -class Array; -class Class; -class ClassLoader; -class CodeAndDirectMethods; -class DexCache; -class Field; -class IfTable; -class Monitor; -class Member; -class AbstractMethod; -class Object; -class StaticStorageBase; -class String; -template<class T> class ObjectArray; -template<class T> class PrimitiveArray; -typedef PrimitiveArray<uint8_t> BooleanArray; -typedef PrimitiveArray<int8_t> ByteArray; -typedef PrimitiveArray<uint16_t> CharArray; -typedef PrimitiveArray<double> DoubleArray; -typedef PrimitiveArray<float> FloatArray; -typedef PrimitiveArray<int32_t> IntArray; -typedef PrimitiveArray<int64_t> LongArray; -typedef PrimitiveArray<int16_t> ShortArray; -union JValue; - -#if defined(ART_USE_LLVM_COMPILER) -namespace compiler_llvm { - class InferredRegCategoryMap; -} // namespace compiler_llvm -#endif - -/* - * Definitions for packing refOffsets in Class. - */ -/* - * A magic value for refOffsets. Ignore the bits and walk the super - * chain when this is the value. - * [This is an unlikely "natural" value, since it would be 30 non-ref instance - * fields followed by 2 ref instance fields.] - */ -#define CLASS_WALK_SUPER ((unsigned int)(3)) -#define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8) -#define CLASS_OFFSET_ALIGNMENT 4 -#define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1)) -/* - * Given an offset, return the bit number which would encode that offset. - * Local use only. - */ -#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \ - ((unsigned int)(byteOffset) / \ - CLASS_OFFSET_ALIGNMENT) -/* - * Is the given offset too large to be encoded? - */ -#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \ - (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD) -/* - * Return a single bit, encoding the offset. - * Undefined if the offset is too large, as defined above. - */ -#define CLASS_BIT_FROM_OFFSET(byteOffset) \ - (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset)) -/* - * Return an offset, given a bit number as returned from CLZ. - */ -#define CLASS_OFFSET_FROM_CLZ(rshift) \ - MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT)) - -#define OFFSET_OF_OBJECT_MEMBER(type, field) \ - MemberOffset(OFFSETOF_MEMBER(type, field)) - -// Classes shared with the managed side of the world need to be packed -// so that they don't have extra platform specific padding. -#define MANAGED PACKED(4) - -// C++ mirror of java.lang.Object -class MANAGED Object { - public: - static MemberOffset ClassOffset() { - return OFFSET_OF_OBJECT_MEMBER(Object, klass_); - } - - Class* GetClass() const { - return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false); - } - - void SetClass(Class* new_klass); - - bool InstanceOf(const Class* klass) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - int32_t IdentityHashCode() const { - #ifdef MOVING_GARBAGE_COLLECTOR - // TODO: we'll need to use the Object's internal concept of identity - UNIMPLEMENTED(FATAL); - #endif - return reinterpret_cast<int32_t>(this); - } - - static MemberOffset MonitorOffset() { - return OFFSET_OF_OBJECT_MEMBER(Object, monitor_); - } - - volatile int32_t* GetRawLockWordAddress() { - byte* raw_addr = reinterpret_cast<byte*>(this) + - OFFSET_OF_OBJECT_MEMBER(Object, monitor_).Int32Value(); - int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); - return const_cast<volatile int32_t*>(word_addr); - } - - uint32_t GetThinLockId(); - - void MonitorEnter(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - EXCLUSIVE_LOCK_FUNCTION(monitor_lock_); - - bool MonitorExit(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - UNLOCK_FUNCTION(monitor_lock_); - - void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void Wait(int64_t timeout) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void Wait(int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsClass() const; - - Class* AsClass() { - DCHECK(IsClass()); - return down_cast<Class*>(this); - } - - const Class* AsClass() const { - DCHECK(IsClass()); - return down_cast<const Class*>(this); - } - - bool IsObjectArray() const; - - template<class T> - ObjectArray<T>* AsObjectArray(); - - template<class T> - const ObjectArray<T>* AsObjectArray() const; - - bool IsArrayInstance() const; - - Array* AsArray() { - DCHECK(IsArrayInstance()); - return down_cast<Array*>(this); - } - - const Array* AsArray() const { - DCHECK(IsArrayInstance()); - return down_cast<const Array*>(this); - } - - BooleanArray* AsBooleanArray(); - ByteArray* AsByteArray(); - CharArray* AsCharArray(); - ShortArray* AsShortArray(); - IntArray* AsIntArray(); - LongArray* AsLongArray(); - - String* AsString(); - - Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsMethod() const; - - AbstractMethod* AsMethod() { - DCHECK(IsMethod()); - return down_cast<AbstractMethod*>(this); - } - - const AbstractMethod* AsMethod() const { - DCHECK(IsMethod()); - return down_cast<const AbstractMethod*>(this); - } - - bool IsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Field* AsField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(IsField()); - return down_cast<Field*>(this); - } - - const Field* AsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(IsField()); - return down_cast<const Field*>(this); - } - - bool IsReferenceInstance() const; - - bool IsWeakReferenceInstance() const; - - bool IsSoftReferenceInstance() const; - - bool IsFinalizerReferenceInstance() const; - - bool IsPhantomReferenceInstance() const; - - // Accessors for Java type fields - template<class T> - T GetFieldObject(MemberOffset field_offset, bool is_volatile) const { - T result = reinterpret_cast<T>(GetField32(field_offset, is_volatile)); - Runtime::Current()->GetHeap()->VerifyObject(result); - return result; - } - - void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile, - bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Runtime::Current()->GetHeap()->VerifyObject(new_value); - SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid); - if (new_value != NULL) { - CheckFieldAssignment(field_offset, new_value); - Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); - } - } - - uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const { - Runtime::Current()->GetHeap()->VerifyObject(this); - const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); - const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); - if (UNLIKELY(is_volatile)) { - return android_atomic_acquire_load(word_addr); - } else { - return *word_addr; - } - } - - void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile, bool this_is_valid = true) { - if (this_is_valid) { - Runtime::Current()->GetHeap()->VerifyObject(this); - } - byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); - uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr); - if (UNLIKELY(is_volatile)) { - /* - * TODO: add an android_atomic_synchronization_store() function and - * use it in the 32-bit volatile set handlers. On some platforms we - * can use a fast atomic instruction and avoid the barriers. - */ - ANDROID_MEMBAR_STORE(); - *word_addr = new_value; - ANDROID_MEMBAR_FULL(); - } else { - *word_addr = new_value; - } - } - - uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const { - Runtime::Current()->GetHeap()->VerifyObject(this); - const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); - const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); - if (UNLIKELY(is_volatile)) { - uint64_t result = QuasiAtomic::Read64(addr); - ANDROID_MEMBAR_FULL(); - return result; - } else { - return *addr; - } - } - - void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) { - Runtime::Current()->GetHeap()->VerifyObject(this); - byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); - int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); - if (UNLIKELY(is_volatile)) { - ANDROID_MEMBAR_STORE(); - QuasiAtomic::Write64(addr, new_value); - // Post-store barrier not required due to use of atomic op or mutex. - } else { - *addr = new_value; - } - } - - protected: - // Accessors for non-Java type fields - template<class T> - T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const { - return reinterpret_cast<T>(GetField32(field_offset, is_volatile)); - } - - template<typename T> - void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) { - SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid); - } - - private: -#if VERIFY_OBJECT_ENABLED - void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -#else - void CheckFieldAssignment(MemberOffset, const Object*) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {} -#endif - - Class* klass_; - - uint32_t monitor_; - - friend class ImageWriter; // for abusing monitor_ directly - friend struct ObjectOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(Object); -}; - -// C++ mirror of java.lang.reflect.Field -class MANAGED Field : public Object { - public: - Class* GetDeclaringClass() const; - - void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - uint32_t GetAccessFlags() const; - - void SetAccessFlags(uint32_t new_access_flags) { - SetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), new_access_flags, false); - } - - bool IsPublic() const { - return (GetAccessFlags() & kAccPublic) != 0; - } - - bool IsStatic() const { - return (GetAccessFlags() & kAccStatic) != 0; - } - - bool IsFinal() const { - return (GetAccessFlags() & kAccFinal) != 0; - } - - uint32_t GetDexFieldIndex() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), false); - } - - void SetDexFieldIndex(uint32_t new_idx) { - SetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), new_idx, false); - } - - // Offset to field within an Object - MemberOffset GetOffset() const; - - static MemberOffset OffsetOffset() { - return MemberOffset(OFFSETOF_MEMBER(Field, offset_)); - } - - MemberOffset GetOffsetDuringLinking() const; - - void SetOffset(MemberOffset num_bytes); - - // field access, null object for static fields - bool GetBoolean(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetBoolean(Object* object, bool z) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int8_t GetByte(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetByte(Object* object, int8_t b) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint16_t GetChar(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetChar(Object* object, uint16_t c) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int16_t GetShort(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetShort(Object* object, int16_t s) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int32_t GetInt(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetInt(Object* object, int32_t i) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int64_t GetLong(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetLong(Object* object, int64_t j) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - float GetFloat(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetFloat(Object* object, float f) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - double GetDouble(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetDouble(Object* object, double d) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetObject(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetObject(Object* object, const Object* l) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // raw field accesses - uint32_t Get32(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void Set32(Object* object, uint32_t new_value) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint64_t Get64(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void Set64(Object* object, uint64_t new_value) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetObj(const Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetObj(Object* object, const Object* new_value) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static Class* GetJavaLangReflectField() { - DCHECK(java_lang_reflect_Field_ != NULL); - return java_lang_reflect_Field_; - } - - static void SetClass(Class* java_lang_reflect_Field); - static void ResetClass(); - - bool IsVolatile() const { - return (GetAccessFlags() & kAccVolatile) != 0; - } - - private: - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - // The class we are a part of - Class* declaring_class_; - - uint32_t access_flags_; - - // Dex cache index of field id - uint32_t field_dex_idx_; - - // Offset of field within an instance or in the Class' static fields - uint32_t offset_; - - static Class* java_lang_reflect_Field_; - - friend struct FieldOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(Field); -}; - -// C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor -class MANAGED AbstractMethod : public Object { - public: - // A function that invokes a method with an array of its arguments. - typedef void InvokeStub(const AbstractMethod* method, - Object* obj, - Thread* thread, - JValue* args, - JValue* result); - - Class* GetDeclaringClass() const; - - void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static MemberOffset DeclaringClassOffset() { - return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_)); - } - - uint32_t GetAccessFlags() const; - - void SetAccessFlags(uint32_t new_access_flags) { - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), new_access_flags, false); - } - - // Approximate what kind of method call would be used for this method. - InvokeType GetInvokeType() const; - - // Returns true if the method is declared public. - bool IsPublic() const { - return (GetAccessFlags() & kAccPublic) != 0; - } - - // Returns true if the method is declared private. - bool IsPrivate() const { - return (GetAccessFlags() & kAccPrivate) != 0; - } - - // Returns true if the method is declared static. - bool IsStatic() const { - return (GetAccessFlags() & kAccStatic) != 0; - } - - // Returns true if the method is a constructor. - bool IsConstructor() const { - return (GetAccessFlags() & kAccConstructor) != 0; - } - - // Returns true if the method is static, private, or a constructor. - bool IsDirect() const { - return IsDirect(GetAccessFlags()); - } - - static bool IsDirect(uint32_t access_flags) { - return (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0; - } - - // Returns true if the method is declared synchronized. - bool IsSynchronized() const { - uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized; - return (GetAccessFlags() & synchonized) != 0; - } - - bool IsFinal() const { - return (GetAccessFlags() & kAccFinal) != 0; - } - - bool IsMiranda() const { - return (GetAccessFlags() & kAccMiranda) != 0; - } - - bool IsNative() const { - return (GetAccessFlags() & kAccNative) != 0; - } - - bool IsAbstract() const { - return (GetAccessFlags() & kAccAbstract) != 0; - } - - bool IsSynthetic() const { - return (GetAccessFlags() & kAccSynthetic) != 0; - } - - bool IsProxyMethod() const; - - bool CheckIncompatibleClassChange(InvokeType type); - - uint16_t GetMethodIndex() const; - - size_t GetVtableIndex() const { - return GetMethodIndex(); - } - - void SetMethodIndex(uint16_t new_method_index) { - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), new_method_index, false); - } - - static MemberOffset MethodIndexOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_); - } - - uint32_t GetCodeItemOffset() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), false); - } - - void SetCodeItemOffset(uint32_t new_code_off) { - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), new_code_off, false); - } - - // Number of 32bit registers that would be required to hold all the arguments - static size_t NumArgRegisters(const StringPiece& shorty); - - uint32_t GetDexMethodIndex() const; - - void SetDexMethodIndex(uint32_t new_idx) { - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), new_idx, false); - } - - ObjectArray<String>* GetDexCacheStrings() const; - void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static MemberOffset DexCacheStringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_); - } - - static MemberOffset DexCacheResolvedMethodsOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_); - } - - static MemberOffset DexCacheResolvedTypesOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_); - } - - static MemberOffset DexCacheInitializedStaticStorageOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, - dex_cache_initialized_static_storage_); - } - - ObjectArray<AbstractMethod>* GetDexCacheResolvedMethods() const; - void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - ObjectArray<Class>* GetDexCacheResolvedTypes() const; - void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const; - void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Find the method that this method overrides - AbstractMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - const void* GetCode() const { - return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), false); - } - - void SetCode(const void* code) { - SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), code, false); - } - - uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); - uintptr_t code = reinterpret_cast<uintptr_t>(GetCode()); - if (code == 0) { - return 0; - } - // TODO: make this Thumb2 specific - code &= ~0x1; - return reinterpret_cast<uint32_t*>(code)[-1]; - } - - bool IsWithinCode(uintptr_t pc) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - uintptr_t code = reinterpret_cast<uintptr_t>(GetCode()); - if (code == 0) { - return pc == 0; - } - /* - * During a stack walk, a return PC may point to the end of the code + 1 - * (in the case that the last instruction is a call that isn't expected to - * return. Thus, we check <= code + GetCodeSize(). - */ - return (code <= pc && pc <= code + GetCodeSize()); - } - - void AssertPcIsWithinCode(uintptr_t pc) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - uint32_t GetOatCodeOffset() const { - DCHECK(!Runtime::Current()->IsStarted()); - return reinterpret_cast<uint32_t>(GetCode()); - } - - void SetOatCodeOffset(uint32_t code_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetCode(reinterpret_cast<void*>(code_offset)); - } - - static MemberOffset GetCodeOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_); - } - - const uint32_t* GetMappingTable() const { - const uint32_t* map = GetMappingTableRaw(); - if (map == NULL) { - return map; - } - return map + 1; - } - - uint32_t GetPcToDexMappingTableLength() const { - const uint32_t* map = GetMappingTableRaw(); - if (map == NULL) { - return 0; - } - return map[2]; - } - - const uint32_t* GetPcToDexMappingTable() const { - const uint32_t* map = GetMappingTableRaw(); - if (map == NULL) { - return map; - } - return map + 3; - } - - - uint32_t GetDexToPcMappingTableLength() const { - const uint32_t* map = GetMappingTableRaw(); - if (map == NULL) { - return 0; - } - return map[1] - map[2]; - } - - const uint32_t* GetDexToPcMappingTable() const { - const uint32_t* map = GetMappingTableRaw(); - if (map == NULL) { - return map; - } - return map + 3 + map[2]; - } - - - const uint32_t* GetMappingTableRaw() const { - return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), false); - } - - void SetMappingTable(const uint32_t* mapping_table) { - SetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), - mapping_table, false); - } - - uint32_t GetOatMappingTableOffset() const { - DCHECK(!Runtime::Current()->IsStarted()); - return reinterpret_cast<uint32_t>(GetMappingTableRaw()); - } - - void SetOatMappingTableOffset(uint32_t mapping_table_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table_offset)); - } - - // Callers should wrap the uint16_t* in a VmapTable instance for convenient access. - const uint16_t* GetVmapTableRaw() const { - return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), false); - } - - void SetVmapTable(const uint16_t* vmap_table) { - SetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), vmap_table, false); - } - - uint32_t GetOatVmapTableOffset() const { - DCHECK(!Runtime::Current()->IsStarted()); - return reinterpret_cast<uint32_t>(GetVmapTableRaw()); - } - - void SetOatVmapTableOffset(uint32_t vmap_table_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetVmapTable(reinterpret_cast<uint16_t*>(vmap_table_offset)); - } - - const uint8_t* GetNativeGcMap() const { - return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), false); - } - void SetNativeGcMap(const uint8_t* data) { - SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), data, - false); - } - - // When building the oat need a convenient place to stuff the offset of the native GC map. - void SetOatNativeGcMapOffset(uint32_t gc_map_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); - } - - uint32_t GetOatNativeGcMapOffset() const { - DCHECK(!Runtime::Current()->IsStarted()); - return reinterpret_cast<uint32_t>(GetNativeGcMap()); - } - - size_t GetFrameSizeInBytes() const { - DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); - size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), false); - DCHECK_LE(static_cast<size_t>(kStackAlignment), result); - return result; - } - - void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) { - DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), - new_frame_size_in_bytes, false); - } - - size_t GetReturnPcOffsetInBytes() const { - return GetFrameSizeInBytes() - kPointerSize; - } - - bool IsRegistered() const; - - void RegisterNative(Thread* self, const void* native_method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static MemberOffset NativeMethodOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_); - } - - const void* GetNativeMethod() const { - return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false)); - } - - // Native to managed invocation stub entry point - InvokeStub* GetInvokeStub() const { - InvokeStub* result = GetFieldPtr<InvokeStub*>( - OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), false); - // TODO: DCHECK(result != NULL); should be ahead of time compiled - return result; - } - - void SetInvokeStub(InvokeStub* invoke_stub) { - SetFieldPtr<InvokeStub*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), - invoke_stub, false); - } - - uint32_t GetInvokeStubSize() const { - uintptr_t invoke_stub = reinterpret_cast<uintptr_t>(GetInvokeStub()); - if (invoke_stub == 0) { - return 0; - } - // TODO: make this Thumb2 specific - invoke_stub &= ~0x1; - return reinterpret_cast<const uint32_t*>(invoke_stub)[-1]; - } - - uint32_t GetOatInvokeStubOffset() const { - DCHECK(!Runtime::Current()->IsStarted()); - return reinterpret_cast<uint32_t>(GetInvokeStub()); - } - - void SetOatInvokeStubOffset(uint32_t invoke_stub_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetInvokeStub(reinterpret_cast<InvokeStub*>(invoke_stub_offset)); - } - - static MemberOffset GetInvokeStubOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_); - } - - static MemberOffset GetMethodIndexOffset() { - return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_); - } - - uint32_t GetCoreSpillMask() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), false); - } - - void SetCoreSpillMask(uint32_t core_spill_mask) { - // Computed during compilation - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), core_spill_mask, false); - } - - uint32_t GetFpSpillMask() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), false); - } - - void SetFpSpillMask(uint32_t fp_spill_mask) { - // Computed during compilation - SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), fp_spill_mask, false); - } - - // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal - // conventions for a method of managed code. Returns false for Proxy methods. - bool IsRuntimeMethod() const { - return GetDexMethodIndex() == DexFile::kDexNoIndex16; - } - - // Is this a hand crafted method used for something like describing callee saves? - bool IsCalleeSaveMethod() const { - if (!IsRuntimeMethod()) { - return false; - } - Runtime* runtime = Runtime::Current(); - bool result = false; - for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { - if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) { - result = true; - break; - } - } - return result; - } - - bool IsResolutionMethod() const { - bool result = this == Runtime::Current()->GetResolutionMethod(); - // Check that if we do think it is phony it looks like the resolution method - DCHECK(!result || GetDexMethodIndex() == DexFile::kDexNoIndex16); - return result; - } - - uintptr_t NativePcOffset(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Converts a native PC to a dex PC. - uint32_t ToDexPc(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Converts a dex PC to a native PC. - uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Converts a dex PC to the first corresponding safepoint PC. - uintptr_t ToFirstNativeSafepointPc(const uint32_t dex_pc) - const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Find the catch block for the given exception type and dex_pc - uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static void SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method); - - static Class* GetConstructorClass() { - return java_lang_reflect_Constructor_; - } - - static Class* GetMethodClass() { - return java_lang_reflect_Method_; - } - - static void ResetClasses(); - - protected: - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - // The class we are a part of - Class* declaring_class_; - - // short cuts to declaring_class_->dex_cache_ member for fast compiled code access - ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_; - - // short cuts to declaring_class_->dex_cache_ member for fast compiled code access - ObjectArray<AbstractMethod>* dex_cache_resolved_methods_; - - // short cuts to declaring_class_->dex_cache_ member for fast compiled code access - ObjectArray<Class>* dex_cache_resolved_types_; - - // short cuts to declaring_class_->dex_cache_ member for fast compiled code access - ObjectArray<String>* dex_cache_strings_; - - // Access flags; low 16 bits are defined by spec. - uint32_t access_flags_; - - // Compiled code associated with this method for callers from managed code. - // May be compiled managed code or a bridge for invoking a native method. - const void* code_; - - // Offset to the CodeItem. - uint32_t code_item_offset_; - - // Architecture-dependent register spill mask - uint32_t core_spill_mask_; - - // Architecture-dependent register spill mask - uint32_t fp_spill_mask_; - - // Total size in bytes of the frame - size_t frame_size_in_bytes_; - - // Garbage collection map of native PC offsets to reference bitmaps. - const uint8_t* native_gc_map_; - - // Native invocation stub entry point for calling from native to managed code. - InvokeStub* invoke_stub_; - - // Mapping from native pc to dex pc - const uint32_t* mapping_table_; - - // Index into method_ids of the dex file associated with this method - uint32_t method_dex_index_; - - // For concrete virtual methods, this is the offset of the method in Class::vtable_. - // - // For abstract methods in an interface class, this is the offset of the method in - // "iftable_->Get(n)->GetMethodArray()". - // - // For static and direct methods this is the index in the direct methods table. - uint32_t method_index_; - - // The target native method registered with this method - const void* native_method_; - - // When a register is promoted into a register, the spill mask holds which registers hold dex - // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth - // is vmap_table_[N]. vmap_table_[0] holds the length of the table. - const uint16_t* vmap_table_; - - static Class* java_lang_reflect_Constructor_; - static Class* java_lang_reflect_Method_; - - friend class ImageWriter; // for relocating code_ and invoke_stub_ - friend struct AbstractMethodOffsets; // for verifying offset information - friend struct ConstructorMethodOffsets; // for verifying offset information - friend struct MethodOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod); -}; - -class MANAGED Method : public AbstractMethod { - -}; - -class MANAGED Constructor : public AbstractMethod { - -}; - -class MANAGED Array : public Object { - public: - // A convenience for code that doesn't know the component size, - // and doesn't want to have to work it out itself. - static Array* Alloc(Thread* self, Class* array_class, int32_t component_count) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, - size_t component_size) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - size_t SizeOf() const; - - int32_t GetLength() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false); - } - - void SetLength(int32_t length) { - CHECK_GE(length, 0); - SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false); - } - - static MemberOffset LengthOffset() { - return OFFSET_OF_OBJECT_MEMBER(Array, length_); - } - - static MemberOffset DataOffset(size_t component_size) { - if (component_size != sizeof(int64_t)) { - return OFFSET_OF_OBJECT_MEMBER(Array, first_element_); - } else { - // Align longs and doubles. - return MemberOffset(OFFSETOF_MEMBER(Array, first_element_) + 4); - } - } - - void* GetRawData(size_t component_size) { - intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); - return reinterpret_cast<void*>(data); - } - - const void* GetRawData(size_t component_size) const { - intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); - return reinterpret_cast<const void*>(data); - } - - protected: - bool IsValidIndex(int32_t index) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (UNLIKELY(index < 0 || index >= GetLength())) { - return ThrowArrayIndexOutOfBoundsException(index); - } - return true; - } - - protected: - bool ThrowArrayIndexOutOfBoundsException(int32_t index) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool ThrowArrayStoreException(Object* object) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - private: - // The number of array elements. - int32_t length_; - // Marker for the data (used by generated code) - uint32_t first_element_[0]; - - DISALLOW_IMPLICIT_CONSTRUCTORS(Array); -}; - -template<class T> -class MANAGED ObjectArray : public Array { - public: - static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void Set(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Set element without bound and element type checks, to be used in limited - // circumstances, such as during boot image writing - void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Set element without bound and element type checks, to be used in limited circumstances, such - // as during boot image writing. Does not do write barrier. - void SetPtrWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static void Copy(const ObjectArray<T>* src, int src_pos, - ObjectArray<T>* dst, int dst_pos, - size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - ObjectArray<T>* CopyOf(Thread* self, int32_t new_length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray); -}; - -template<class T> -ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) { - Array* array = Array::Alloc(self, object_array_class, length, sizeof(Object*)); - if (UNLIKELY(array == NULL)) { - return NULL; - } else { - return array->AsObjectArray<T>(); - } -} - -template<class T> -inline T* ObjectArray<T>::Get(int32_t i) const { - if (UNLIKELY(!IsValidIndex(i))) { - return NULL; - } - MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); - return GetFieldObject<T*>(data_offset, false); -} - -template<class T> -ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) { - ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length); - Copy(this, 0, new_array, 0, std::min(GetLength(), new_length)); - return new_array; -} - -class MANAGED IfTable : public ObjectArray<Object> { - public: - Class* GetInterface(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* interface = Get((i * kMax) + kInterface)->AsClass(); - DCHECK(interface != NULL); - return interface; - } - - void SetInterface(int32_t i, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - ObjectArray<AbstractMethod>* GetMethodArray(int32_t i) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<AbstractMethod>* method_array = - down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray)); - DCHECK(method_array != NULL); - return method_array; - } - - size_t GetMethodArrayCount(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<AbstractMethod>* method_array = - down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray)); - if (method_array == NULL) { - return 0; - } - return method_array->GetLength(); - } - - void SetMethodArray(int32_t i, ObjectArray<AbstractMethod>* new_ma) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(new_ma != NULL); - DCHECK(Get((i * kMax) + kMethodArray) == NULL); - Set((i * kMax) + kMethodArray, new_ma); - } - - size_t Count() const { - return GetLength() / kMax; - } - - enum { - // Points to the interface class. - kInterface = 0, - // Method pointers into the vtable, allow fast map from interface method index to concrete - // instance method. - kMethodArray = 1, - kMax = 2, - }; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(IfTable); -}; - -// Type for the InitializedStaticStorage table. Currently the Class -// provides the static storage. However, this might change to an Array -// to improve image sharing, so we use this type to avoid assumptions -// on the current storage. -class MANAGED StaticStorageBase : public Object { -}; - -// C++ mirror of java.lang.Class -class MANAGED Class : public StaticStorageBase { - public: - // Class Status - // - // kStatusNotReady: If a Class cannot be found in the class table by - // FindClass, it allocates an new one with AllocClass in the - // kStatusNotReady and calls LoadClass. Note if it does find a - // class, it may not be kStatusResolved and it will try to push it - // forward toward kStatusResolved. - // - // kStatusIdx: LoadClass populates with Class with information from - // the DexFile, moving the status to kStatusIdx, indicating that the - // Class value in super_class_ has not been populated. The new Class - // can then be inserted into the classes table. - // - // kStatusLoaded: After taking a lock on Class, the ClassLinker will - // attempt to move a kStatusIdx class forward to kStatusLoaded by - // using ResolveClass to initialize the super_class_ and ensuring the - // interfaces are resolved. - // - // kStatusResolved: Still holding the lock on Class, the ClassLinker - // shows linking is complete and fields of the Class populated by making - // it kStatusResolved. Java allows circularities of the form where a super - // class has a field that is of the type of the sub class. We need to be able - // to fully resolve super classes while resolving types for fields. - // - // kStatusRetryVerificationAtRuntime: The verifier sets a class to - // this state if it encounters a soft failure at compile time. This - // often happens when there are unresolved classes in other dex - // files, and this status marks a class as needing to be verified - // again at runtime. - // - // TODO: Explain the other states - enum Status { - kStatusError = -1, - kStatusNotReady = 0, - kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_. - kStatusLoaded = 2, // DEX idx values resolved. - kStatusResolved = 3, // Part of linking. - kStatusVerifying = 4, // In the process of being verified. - kStatusRetryVerificationAtRuntime = 5, // Compile time verification failed, retry at runtime. - kStatusVerifyingAtRuntime = 6, // Retrying verification at runtime. - kStatusVerified = 7, // Logically part of linking; done pre-init. - kStatusInitializing = 8, // Class init in progress. - kStatusInitialized = 9, // Ready to go. - }; - - Status GetStatus() const { - DCHECK_EQ(sizeof(Status), sizeof(uint32_t)); - return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false)); - } - - void SetStatus(Status new_status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Returns true if the class has failed to link. - bool IsErroneous() const { - return GetStatus() == kStatusError; - } - - // Returns true if the class has been loaded. - bool IsIdxLoaded() const { - return GetStatus() >= kStatusIdx; - } - - // Returns true if the class has been loaded. - bool IsLoaded() const { - return GetStatus() >= kStatusLoaded; - } - - // Returns true if the class has been linked. - bool IsResolved() const { - return GetStatus() >= kStatusResolved; - } - - // Returns true if the class was compile-time verified. - bool IsCompileTimeVerified() const { - return GetStatus() >= kStatusRetryVerificationAtRuntime; - } - - // Returns true if the class has been verified. - bool IsVerified() const { - return GetStatus() >= kStatusVerified; - } - - // Returns true if the class is initializing. - bool IsInitializing() const { - return GetStatus() >= kStatusInitializing; - } - - // Returns true if the class is initialized. - bool IsInitialized() const { - return GetStatus() == kStatusInitialized; - } - - uint32_t GetAccessFlags() const; - - void SetAccessFlags(uint32_t new_access_flags) { - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags, false); - } - - // Returns true if the class is an interface. - bool IsInterface() const { - return (GetAccessFlags() & kAccInterface) != 0; - } - - // Returns true if the class is declared public. - bool IsPublic() const { - return (GetAccessFlags() & kAccPublic) != 0; - } - - // Returns true if the class is declared final. - bool IsFinal() const { - return (GetAccessFlags() & kAccFinal) != 0; - } - - bool IsFinalizable() const { - return (GetAccessFlags() & kAccClassIsFinalizable) != 0; - } - - void SetFinalizable() { - uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); - SetAccessFlags(flags | kAccClassIsFinalizable); - } - - // Returns true if the class is abstract. - bool IsAbstract() const { - return (GetAccessFlags() & kAccAbstract) != 0; - } - - // Returns true if the class is an annotation. - bool IsAnnotation() const { - return (GetAccessFlags() & kAccAnnotation) != 0; - } - - // Returns true if the class is synthetic. - bool IsSynthetic() const { - return (GetAccessFlags() & kAccSynthetic) != 0; - } - - bool IsReferenceClass() const { - return (GetAccessFlags() & kAccClassIsReference) != 0; - } - - bool IsWeakReferenceClass() const { - return (GetAccessFlags() & kAccClassIsWeakReference) != 0; - } - - bool IsSoftReferenceClass() const { - return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference; - } - - bool IsFinalizerReferenceClass() const { - return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0; - } - - bool IsPhantomReferenceClass() const { - return (GetAccessFlags() & kAccClassIsPhantomReference) != 0; - } - - - String* GetName() const; // Returns the cached name. - void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name. - // Computes the name, then sets the cached value. - String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsProxyClass() const { - // Read access flags without using getter as whether something is a proxy can be check in - // any loaded state - // TODO: switch to a check if the super class is java.lang.reflect.Proxy? - uint32_t access_flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); - return (access_flags & kAccClassIsProxy) != 0; - } - - Primitive::Type GetPrimitiveType() const { - DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t)); - return static_cast<Primitive::Type>( - GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false)); - } - - void SetPrimitiveType(Primitive::Type new_type) { - DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t)); - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false); - } - - // Returns true if the class is a primitive type. - bool IsPrimitive() const { - return GetPrimitiveType() != Primitive::kPrimNot; - } - - bool IsPrimitiveBoolean() const { - return GetPrimitiveType() == Primitive::kPrimBoolean; - } - - bool IsPrimitiveByte() const { - return GetPrimitiveType() == Primitive::kPrimByte; - } - - bool IsPrimitiveChar() const { - return GetPrimitiveType() == Primitive::kPrimChar; - } - - bool IsPrimitiveShort() const { - return GetPrimitiveType() == Primitive::kPrimShort; - } - - bool IsPrimitiveInt() const { - return GetPrimitiveType() == Primitive::kPrimInt; - } - - bool IsPrimitiveLong() const { - return GetPrimitiveType() == Primitive::kPrimLong; - } - - bool IsPrimitiveFloat() const { - return GetPrimitiveType() == Primitive::kPrimFloat; - } - - bool IsPrimitiveDouble() const { - return GetPrimitiveType() == Primitive::kPrimDouble; - } - - bool IsPrimitiveVoid() const { - return GetPrimitiveType() == Primitive::kPrimVoid; - } - - bool IsPrimitiveArray() const { - return IsArrayClass() && GetComponentType()->IsPrimitive(); - } - - // Depth of class from java.lang.Object - size_t Depth() { - size_t depth = 0; - for (Class* klass = this; klass->GetSuperClass() != NULL; klass = klass->GetSuperClass()) { - depth++; - } - return depth; - } - - bool IsArrayClass() const { - return GetComponentType() != NULL; - } - - bool IsClassClass() const; - - bool IsStringClass() const; - - bool IsThrowableClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsMethodClass() const; - - Class* GetComponentType() const { - return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false); - } - - void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(GetComponentType() == NULL); - DCHECK(new_component_type != NULL); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), new_component_type, false); - } - - size_t GetComponentSize() const { - return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType()); - } - - bool IsObjectClass() const { - return !IsPrimitive() && GetSuperClass() == NULL; - } - bool IsInstantiable() const { - return !IsPrimitive() && !IsInterface() && !IsAbstract(); - } - - bool IsObjectArrayClass() const { - return GetComponentType() != NULL && !GetComponentType()->IsPrimitive(); - } - - // Creates a raw object instance but does not invoke the default constructor. - Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool IsVariableSize() const { - // Classes and arrays vary in size, and so the object_size_ field cannot - // be used to get their instance size - return IsClassClass() || IsArrayClass(); - } - - size_t SizeOf() const { - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false); - } - - size_t GetClassSize() const { - DCHECK_EQ(sizeof(size_t), sizeof(uint32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false); - } - - void SetClassSize(size_t new_class_size) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - size_t GetObjectSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false); - CHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this); - return result; - } - - void SetObjectSize(size_t new_object_size) { - DCHECK(!IsVariableSize()); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size, false); - } - - // Returns true if this class is in the same packages as that class. - bool IsInSamePackage(const Class* that) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2); - - // Returns true if this class can access that class. - bool CanAccess(Class* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return that->IsPublic() || this->IsInSamePackage(that); - } - - // Can this class access a member in the provided class with the provided member access flags? - // Note that access to the class isn't checked in case the declaring class is protected and the - // method has been exposed by a public sub-class - bool CanAccessMember(Class* access_to, uint32_t member_flags) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Classes can access all of their own members - if (this == access_to) { - return true; - } - // Public members are trivially accessible - if (member_flags & kAccPublic) { - return true; - } - // Private members are trivially not accessible - if (member_flags & kAccPrivate) { - return false; - } - // Check for protected access from a sub-class, which may or may not be in the same package. - if (member_flags & kAccProtected) { - if (this->IsSubClass(access_to)) { - return true; - } - } - // Allow protected access from other classes in the same package. - return this->IsInSamePackage(access_to); - } - - bool IsSubClass(const Class* klass) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Can src be assigned to this class? For example, String can be assigned to Object (by an - // upcast), however, an Object cannot be assigned to a String as a potentially exception throwing - // downcast would be necessary. Similarly for interfaces, a class that implements (or an interface - // that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign - // to themselves. Classes for primitive types may not assign to each other. - bool IsAssignableFrom(const Class* src) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(src != NULL); - if (this == src) { - // Can always assign to things of the same type. - return true; - } else if (IsObjectClass()) { - // Can assign any reference to java.lang.Object. - return !src->IsPrimitive(); - } else if (IsInterface()) { - return src->Implements(this); - } else if (src->IsArrayClass()) { - return IsAssignableFromArray(src); - } else { - return !src->IsInterface() && src->IsSubClass(this); - } - } - - Class* GetSuperClass() const { - // Can only get super class for loaded classes (hack for when runtime is - // initializing) - DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded(); - return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false); - } - - void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // super class is assigned once, except during class linker initialization - Class* old_super_class = GetFieldObject<Class*>( - OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false); - DCHECK(old_super_class == NULL || old_super_class == new_super_class); - DCHECK(new_super_class != NULL); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class, false); - } - - bool HasSuperClass() const { - return GetSuperClass() != NULL; - } - - static MemberOffset SuperClassOffset() { - return MemberOffset(OFFSETOF_MEMBER(Class, super_class_)); - } - - ClassLoader* GetClassLoader() const; - - void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static MemberOffset DexCacheOffset() { - return MemberOffset(OFFSETOF_MEMBER(Class, dex_cache_)); - } - - enum { - kDumpClassFullDetail = 1, - kDumpClassClassLoader = (1 << 1), - kDumpClassInitialized = (1 << 2), - }; - - void DumpClass(std::ostream& os, int flags) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - DexCache* GetDexCache() const; - - void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - ObjectArray<AbstractMethod>* GetDirectMethods() const { - DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false); - } - - void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false)); - DCHECK_NE(0, new_direct_methods->GetLength()); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), - new_direct_methods, false); - } - - AbstractMethod* GetDirectMethod(int32_t i) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetDirectMethods()->Get(i); - } - - void SetDirectMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ - ObjectArray<AbstractMethod>* direct_methods = - GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false); - direct_methods->Set(i, f); - } - - // Returns the number of static, private, and constructor methods. - size_t NumDirectMethods() const { - return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0; - } - - ObjectArray<AbstractMethod>* GetVirtualMethods() const { - DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false); - } - - void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // TODO: we reassign virtual methods to grow the table for miranda - // methods.. they should really just be assigned once - DCHECK_NE(0, new_virtual_methods->GetLength()); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), - new_virtual_methods, false); - } - - // Returns the number of non-inherited virtual methods. - size_t NumVirtualMethods() const { - return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0; - } - - AbstractMethod* GetVirtualMethod(uint32_t i) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(IsResolved() || IsErroneous()); - return GetVirtualMethods()->Get(i); - } - - AbstractMethod* GetVirtualMethodDuringLinking(uint32_t i) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(IsLoaded() || IsErroneous()); - return GetVirtualMethods()->Get(i); - } - - void SetVirtualMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<AbstractMethod>* virtual_methods = - GetFieldObject<ObjectArray<AbstractMethod>*>( - OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false); - virtual_methods->Set(i, f); - } - - ObjectArray<AbstractMethod>* GetVTable() const { - DCHECK(IsResolved() || IsErroneous()); - return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false); - } - - ObjectArray<AbstractMethod>* GetVTableDuringLinking() const { - DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false); - } - - void SetVTable(ObjectArray<AbstractMethod>* new_vtable) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false); - } - - static MemberOffset VTableOffset() { - return OFFSET_OF_OBJECT_MEMBER(Class, vtable_); - } - - // Given a method implemented by this class but potentially from a - // super class, return the specific implementation - // method for this class. - AbstractMethod* FindVirtualMethodForVirtual(AbstractMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(!method->GetDeclaringClass()->IsInterface()); - // The argument method may from a super class. - // Use the index to a potentially overridden one for this instance's class. - return GetVTable()->Get(method->GetMethodIndex()); - } - - // Given a method implemented by this class' super class, return the specific implementation - // method for this class. - AbstractMethod* FindVirtualMethodForSuper(AbstractMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(!method->GetDeclaringClass()->IsInterface()); - return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex()); - } - - // Given a method implemented by this class, but potentially from a - // super class or interface, return the specific implementation - // method for this class. - AbstractMethod* FindVirtualMethodForInterface(AbstractMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindVirtualMethodForVirtualOrInterface(AbstractMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (method->IsDirect()) { - return method; - } - if (method->GetDeclaringClass()->IsInterface()) { - return FindVirtualMethodForInterface(method); - } - return FindVirtualMethodForVirtual(method); - } - - AbstractMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - AbstractMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - int32_t GetIfTableCount() const { - IfTable* iftable = GetIfTable(); - if (iftable == NULL) { - return 0; - } - return iftable->Count(); - } - - IfTable* GetIfTable() const { - return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false); - } - - void SetIfTable(IfTable* new_iftable) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false); - } - - // Get instance fields of the class (See also GetSFields). - ObjectArray<Field>* GetIFields() const { - DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false); - } - - void SetIFields(ObjectArray<Field>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>( - OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false)); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false); - } - - size_t NumInstanceFields() const { - return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0; - } - - Field* GetInstanceField(uint32_t i) const // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ - DCHECK_NE(NumInstanceFields(), 0U); - return GetIFields()->Get(i); - } - - void SetInstanceField(uint32_t i, Field* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){ - ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>( - OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false); - ifields->Set(i, f); - } - - // Returns the number of instance fields containing reference types. - size_t NumReferenceInstanceFields() const { - DCHECK(IsResolved() || IsErroneous()); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false); - } - - size_t NumReferenceInstanceFieldsDuringLinking() const { - DCHECK(IsLoaded() || IsErroneous()); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false); - } - - void SetNumReferenceInstanceFields(size_t new_num) { - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num, false); - } - - uint32_t GetReferenceInstanceOffsets() const { - DCHECK(IsResolved() || IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false); - } - - void SetReferenceInstanceOffsets(uint32_t new_reference_offsets); - - // Beginning of static field data - static MemberOffset FieldsOffset() { - return OFFSET_OF_OBJECT_MEMBER(Class, fields_); - } - - // Returns the number of static fields containing reference types. - size_t NumReferenceStaticFields() const { - DCHECK(IsResolved() || IsErroneous()); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false); - } - - size_t NumReferenceStaticFieldsDuringLinking() const { - DCHECK(IsLoaded() || IsErroneous()); - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false); - } - - void SetNumReferenceStaticFields(size_t new_num) { - DCHECK_EQ(sizeof(size_t), sizeof(int32_t)); - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num, false); - } - - // Gets the static fields of the class. - ObjectArray<Field>* GetSFields() const { - DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false); - } - - void SetSFields(ObjectArray<Field>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>( - OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false)); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false); - } - - size_t NumStaticFields() const { - return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0; - } - - Field* GetStaticField(uint32_t i) const // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetSFields()->Get(i); - } - - void SetStaticField(uint32_t i, Field* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<Field>* sfields= GetFieldObject<ObjectArray<Field>*>( - OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false); - sfields->Set(i, f); - } - - uint32_t GetReferenceStaticOffsets() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false); - } - - void SetReferenceStaticOffsets(uint32_t new_reference_offsets); - - // Find a static or instance field using the JLS resolution order - Field* FindField(const StringPiece& name, const StringPiece& type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Finds the given instance field in this class or a superclass. - Field* FindInstanceField(const StringPiece& name, const StringPiece& type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Finds the given instance field in this class or a superclass, only searches classes that - // have the same dex cache. - Field* FindInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Field* FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Field* FindDeclaredInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Finds the given static field in this class or a superclass. - Field* FindStaticField(const StringPiece& name, const StringPiece& type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Finds the given static field in this class or superclass, only searches classes that - // have the same dex cache. - Field* FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - Field* FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - pid_t GetClinitThreadId() const { - DCHECK(IsIdxLoaded() || IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false); - } - - void SetClinitThreadId(pid_t new_clinit_thread_id) { - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id, false); - } - - Class* GetVerifyErrorClass() const { - // DCHECK(IsErroneous()); - return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false); - } - - uint16_t GetDexTypeIndex() const { - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false); - } - - void SetDexTypeIndex(uint16_t type_idx) { - SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false); - } - - static Class* GetJavaLangClass() { - DCHECK(java_lang_Class_ != NULL); - return java_lang_Class_; - } - - // Can't call this SetClass or else gets called instead of Object::SetClass in places. - static void SetClassClass(Class* java_lang_Class); - static void ResetClass(); - - private: - void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK(klass != NULL) << PrettyClass(this); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false); - } - - bool Implements(const Class* klass) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsArrayAssignableFromArray(const Class* klass) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsAssignableFromArray(const Class* klass) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // defining class loader, or NULL for the "bootstrap" system loader - ClassLoader* class_loader_; - - // For array classes, the component class object for instanceof/checkcast - // (for String[][][], this will be String[][]). NULL for non-array classes. - Class* component_type_; - - // DexCache of resolved constant pool entries (will be NULL for classes generated by the - // runtime such as arrays and primitive classes). - DexCache* dex_cache_; - - // static, private, and <init> methods - ObjectArray<AbstractMethod>* direct_methods_; - - // instance fields - // - // These describe the layout of the contents of an Object. - // Note that only the fields directly declared by this class are - // listed in ifields; fields declared by a superclass are listed in - // the superclass's Class.ifields. - // - // All instance fields that refer to objects are guaranteed to be at - // the beginning of the field list. num_reference_instance_fields_ - // specifies the number of reference fields. - ObjectArray<Field>* ifields_; - - // The interface table (iftable_) contains pairs of a interface class and an array of the - // interface methods. There is one pair per interface supported by this class. That means one - // pair for each interface we support directly, indirectly via superclass, or indirectly via a - // superinterface. This will be null if neither we nor our superclass implement any interfaces. - // - // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()". - // Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a - // single vtable. - // - // For every interface a concrete class implements, we create an array of the concrete vtable_ - // methods for the methods in the interface. - IfTable* iftable_; - - // descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName - String* name_; - - // Static fields - ObjectArray<Field>* sfields_; - - // The superclass, or NULL if this is java.lang.Object, an interface or primitive type. - Class* super_class_; - - // If class verify fails, we must return same error on subsequent tries. - Class* verify_error_class_; - - // virtual methods defined in this class; invoked through vtable - ObjectArray<AbstractMethod>* virtual_methods_; - - // Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is - // copied in, and virtual methods from our class either replace those from the super or are - // appended. For abstract classes, methods may be created in the vtable that aren't in - // virtual_ methods_ for miranda methods. - ObjectArray<AbstractMethod>* vtable_; - - // access flags; low 16 bits are defined by VM spec - uint32_t access_flags_; - - // Total size of the Class instance; used when allocating storage on gc heap. - // See also object_size_. - size_t class_size_; - - // tid used to check for recursive <clinit> invocation - pid_t clinit_thread_id_; - - // type index from dex file - // TODO: really 16bits - uint32_t dex_type_idx_; - - // number of instance fields that are object refs - size_t num_reference_instance_fields_; - - // number of static fields that are object refs - size_t num_reference_static_fields_; - - // Total object size; used when allocating storage on gc heap. - // (For interfaces and abstract classes this will be zero.) - // See also class_size_. - size_t object_size_; - - // primitive type value, or Primitive::kPrimNot (0); set for generated prim classes - Primitive::Type primitive_type_; - - // Bitmap of offsets of ifields. - uint32_t reference_instance_offsets_; - - // Bitmap of offsets of sfields. - uint32_t reference_static_offsets_; - - // state of class initialization - Status status_; - - // TODO: ? - // initiating class loader list - // NOTE: for classes with low serialNumber, these are unused, and the - // values are kept in a table in gDvm. - // InitiatingLoaderList initiating_loader_list_; - - // Location of first static field. - uint32_t fields_[0]; - - // java.lang.Class - static Class* java_lang_Class_; - - friend struct ClassOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(Class); -}; - -std::ostream& operator<<(std::ostream& os, const Class::Status& rhs); - -inline void Object::SetClass(Class* new_klass) { - // new_klass may be NULL prior to class linker initialization - // We don't mark the card since the class is guaranteed to be referenced from another location. - // Proxy classes are held live by the class loader, and other classes are roots of the class - // linker. - SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false); -} - -inline bool Object::InstanceOf(const Class* klass) const { - DCHECK(klass != NULL); - DCHECK(GetClass() != NULL); - return klass->IsAssignableFrom(GetClass()); -} - -inline bool Object::IsClass() const { - Class* java_lang_Class = GetClass()->GetClass(); - return GetClass() == java_lang_Class; -} - -inline bool Object::IsObjectArray() const { - return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive(); -} - -template<class T> -inline ObjectArray<T>* Object::AsObjectArray() { - DCHECK(IsObjectArray()); - return down_cast<ObjectArray<T>*>(this); -} - -template<class T> -inline const ObjectArray<T>* Object::AsObjectArray() const { - DCHECK(IsObjectArray()); - return down_cast<const ObjectArray<T>*>(this); -} - -inline bool Object::IsArrayInstance() const { - return GetClass()->IsArrayClass(); -} - -inline bool Object::IsField() const { - return GetClass()->IsFieldClass(); -} - -inline bool Object::IsMethod() const { - return GetClass()->IsMethodClass(); -} - -inline bool Object::IsReferenceInstance() const { - return GetClass()->IsReferenceClass(); -} - -inline bool Object::IsWeakReferenceInstance() const { - return GetClass()->IsWeakReferenceClass(); -} - -inline bool Object::IsSoftReferenceInstance() const { - return GetClass()->IsSoftReferenceClass(); -} - -inline bool Object::IsFinalizerReferenceInstance() const { - return GetClass()->IsFinalizerReferenceClass(); -} - -inline bool Object::IsPhantomReferenceInstance() const { - return GetClass()->IsPhantomReferenceClass(); -} - -inline size_t Object::SizeOf() const { - size_t result; - if (IsArrayInstance()) { - result = AsArray()->SizeOf(); - } else if (IsClass()) { - result = AsClass()->SizeOf(); - } else { - result = GetClass()->GetObjectSize(); - } - DCHECK(!IsField() || result == sizeof(Field)); - DCHECK(!IsMethod() || result == sizeof(AbstractMethod)); - return result; -} - -inline Class* Field::GetDeclaringClass() const { - Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false); - DCHECK(result != NULL); - DCHECK(result->IsLoaded() || result->IsErroneous()); - return result; -} - -inline void Field::SetDeclaringClass(Class *new_declaring_class) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), new_declaring_class, false); -} - -inline Class* AbstractMethod::GetDeclaringClass() const { - Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), false); - DCHECK(result != NULL) << this; - DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this; - return result; -} - -inline void AbstractMethod::SetDeclaringClass(Class *new_declaring_class) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), new_declaring_class, false); -} - -inline size_t Array::SizeOf() const { - // This is safe from overflow because the array was already allocated, so we know it's sane. - size_t component_size = GetClass()->GetComponentSize(); - int32_t component_count = GetLength(); - size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); - size_t data_size = component_count * component_size; - return header_size + data_size; -} - -template<class T> -void ObjectArray<T>::Set(int32_t i, T* object) { - if (LIKELY(IsValidIndex(i))) { - if (object != NULL) { - Class* element_class = GetClass()->GetComponentType(); - if (UNLIKELY(!object->InstanceOf(element_class))) { - ThrowArrayStoreException(object); - return; - } - } - MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); - SetFieldObject(data_offset, object, false); - } -} - -template<class T> -void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) { - DCHECK(IsValidIndex(i)); - MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); - SetFieldObject(data_offset, object, false); -} - -template<class T> -void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) { - DCHECK(IsValidIndex(i)); - MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); - SetFieldPtr(data_offset, object, false); -} - -template<class T> -T* ObjectArray<T>::GetWithoutChecks(int32_t i) const { - DCHECK(IsValidIndex(i)); - MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); - return GetFieldObject<T*>(data_offset, false); -} - -template<class T> -void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos, - ObjectArray<T>* dst, int dst_pos, - size_t length) { - if (src->IsValidIndex(src_pos) && - src->IsValidIndex(src_pos+length-1) && - dst->IsValidIndex(dst_pos) && - dst->IsValidIndex(dst_pos+length-1)) { - MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*)); - MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*)); - Class* array_class = dst->GetClass(); - Heap* heap = Runtime::Current()->GetHeap(); - if (array_class == src->GetClass()) { - // No need for array store checks if arrays are of the same type - for (size_t i = 0; i < length; i++) { - Object* object = src->GetFieldObject<Object*>(src_offset, false); - heap->VerifyObject(object); - // directly set field, we do a bulk write barrier at the end - dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); - src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); - dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); - } - } else { - Class* element_class = array_class->GetComponentType(); - CHECK(!element_class->IsPrimitive()); - for (size_t i = 0; i < length; i++) { - Object* object = src->GetFieldObject<Object*>(src_offset, false); - if (object != NULL && !object->InstanceOf(element_class)) { - dst->ThrowArrayStoreException(object); - return; - } - heap->VerifyObject(object); - // directly set field, we do a bulk write barrier at the end - dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); - src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); - dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); - } - } - heap->WriteBarrierArray(dst, dst_pos, length); - } -} - -inline void IfTable::SetInterface(int32_t i, Class* interface) { - DCHECK(interface != NULL); - DCHECK(interface->IsInterface()); - DCHECK(Get((i * kMax) + kInterface) == NULL); - Set((i * kMax) + kInterface, interface); -} - -class MANAGED ClassClass : public Class { - private: - int32_t padding_; - int64_t serialVersionUID_; - friend struct ClassClassOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(ClassClass); -}; - -class MANAGED StringClass : public Class { - private: - CharArray* ASCII_; - Object* CASE_INSENSITIVE_ORDER_; - uint32_t REPLACEMENT_CHAR_; - int64_t serialVersionUID_; - friend struct StringClassOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(StringClass); -}; - -class MANAGED FieldClass : public Class { - private: - Object* ORDER_BY_NAME_AND_DECLARING_CLASS_; - friend struct FieldClassOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(FieldClass); -}; - -class MANAGED MethodClass : public Class { - private: - Object* ORDER_BY_SIGNATURE_; - friend struct MethodClassOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(MethodClass); -}; - -template<class T> -class MANAGED PrimitiveArray : public Array { - public: - typedef T ElementType; - - static PrimitiveArray<T>* Alloc(Thread* self, size_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - const T* GetData() const { - intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); - return reinterpret_cast<T*>(data); - } - - T* GetData() { - intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); - return reinterpret_cast<T*>(data); - } - - T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (!IsValidIndex(i)) { - return T(0); - } - return GetData()[i]; - } - - void Set(int32_t i, T value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (IsValidIndex(i)) { - GetData()[i] = value; - } - } - - static void SetArrayClass(Class* array_class) { - CHECK(array_class_ == NULL); - CHECK(array_class != NULL); - array_class_ = array_class; - } - - static void ResetArrayClass() { - CHECK(array_class_ != NULL); - array_class_ = NULL; - } - - private: - static Class* array_class_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray); -}; - -// C++ mirror of java.lang.String -class MANAGED String : public Object { - public: - static MemberOffset CountOffset() { - return OFFSET_OF_OBJECT_MEMBER(String, count_); - } - - static MemberOffset ValueOffset() { - return OFFSET_OF_OBJECT_MEMBER(String, array_); - } - - static MemberOffset OffsetOffset() { - return OFFSET_OF_OBJECT_MEMBER(String, offset_); - } - - const CharArray* GetCharArray() const { - return GetFieldObject<const CharArray*>(ValueOffset(), false); - } - - int32_t GetOffset() const { - int32_t result = GetField32(OffsetOffset(), false); - DCHECK_LE(0, result); - return result; - } - - int32_t GetLength() const; - - int32_t GetHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength())); - } - - int32_t GetUtfLength() const { - return CountUtf8Bytes(GetCharArray()->GetData() + GetOffset(), GetLength()); - } - - uint16_t CharAt(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static String* AllocFromUtf16(Thread* self, - int32_t utf16_length, - const uint16_t* utf16_data_in, - int32_t hash_code = 0) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static String* AllocFromModifiedUtf8(Thread* self, const char* utf) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, - const char* utf8_data_in) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool Equals(const char* modified_utf8) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // TODO: do we need this overload? give it a more intention-revealing name. - bool Equals(const StringPiece& modified_utf8) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - bool Equals(const String* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Compare UTF-16 code point values not in a locale-sensitive manner - int Compare(int32_t utf16_length, const char* utf8_data_in); - - // TODO: do we need this overload? give it a more intention-revealing name. - bool Equals(const uint16_t* that_chars, int32_t that_offset, - int32_t that_length) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // Create a modified UTF-8 encoded std::string from a java/lang/String object. - std::string ToModifiedUtf8() const; - - int32_t FastIndexOf(int32_t ch, int32_t start) { - int32_t count = GetLength(); - if (start < 0) { - start = 0; - } else if (start > count) { - start = count; - } - const uint16_t* chars = GetCharArray()->GetData() + GetOffset(); - const uint16_t* p = chars + start; - const uint16_t* end = chars + count; - while (p < end) { - if (*p++ == ch) { - return (p - 1) - chars; - } - } - return -1; - } - - int32_t CompareTo(String* other) const; - - static Class* GetJavaLangString() { - DCHECK(java_lang_String_ != NULL); - return java_lang_String_; - } - - static void SetClass(Class* java_lang_String); - static void ResetClass(); - - private: - void SetHashCode(int32_t new_hash_code) { - DCHECK_EQ(0u, - GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false)); - SetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), - new_hash_code, false); - } - - void SetCount(int32_t new_count) { - DCHECK_LE(0, new_count); - SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false); - } - - void SetOffset(int32_t new_offset) { - DCHECK_LE(0, new_offset); - DCHECK_GE(GetLength(), new_offset); - SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false); - } - - void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(new_array != NULL); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array, false); - } - - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - CharArray* array_; - - int32_t count_; - - uint32_t hash_code_; - - int32_t offset_; - - static Class* java_lang_String_; - - friend struct StringOffsets; // for verifying offset information - FRIEND_TEST(ObjectTest, StringLength); // for SetOffset and SetCount - DISALLOW_IMPLICIT_CONSTRUCTORS(String); -}; - -// TODO: remove? only used in a unit test of itself. -struct StringHashCode { - int32_t operator()(String* string) const { - return string->GetHashCode(); - } -}; - -inline uint32_t Field::GetAccessFlags() const { - DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false); -} - -inline MemberOffset Field::GetOffset() const { - DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); - return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false)); -} - -inline MemberOffset Field::GetOffsetDuringLinking() const { - DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); - return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false)); -} - -inline uint32_t Class::GetAccessFlags() const { - // Check class is loaded or this is java.lang.String that has a - // circularity issue during loading the names of its members - DCHECK(IsLoaded() || IsErroneous() || - this == String::GetJavaLangString() || - this == Field::GetJavaLangReflectField() || - this == AbstractMethod::GetConstructorClass() || - this == AbstractMethod::GetMethodClass()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false); -} - -inline uint32_t AbstractMethod::GetAccessFlags() const { - DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), false); -} - -inline uint16_t AbstractMethod::GetMethodIndex() const { - DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), false); -} - -inline uint32_t AbstractMethod::GetDexMethodIndex() const { - DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), false); -} - -inline bool AbstractMethod::CheckIncompatibleClassChange(InvokeType type) { - switch (type) { - case kStatic: - return !IsStatic(); - case kDirect: - return !IsDirect() || IsStatic(); - case kVirtual: { - Class* methods_class = GetDeclaringClass(); - return IsDirect() || (methods_class->IsInterface() && !IsMiranda()); - } - case kSuper: - return false; // TODO: appropriate checks for call to super class. - case kInterface: { - Class* methods_class = GetDeclaringClass(); - return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); - } - default: - LOG(FATAL) << "Unreachable - invocation type: " << type; - return true; - } -} - -inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const { - if (!kIsDebugBuild) { - return; - } - if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) { - return; - } - Runtime* runtime = Runtime::Current(); - if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) { - return; - } - DCHECK(IsWithinCode(pc)) - << PrettyMethod(this) - << " pc=" << std::hex << pc - << " code=" << GetCode() - << " size=" << GetCodeSize(); -} - -inline String* Class::GetName() const { - return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false); -} -inline void Class::SetName(String* name) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false); -} - -// C++ mirror of java.lang.Throwable -class MANAGED Throwable : public Object { - public: - void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false); - } - String* GetDetailMessage() const { - return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false); - } - std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // This is a runtime version of initCause, you shouldn't use it if initCause may have been - // overridden. Also it asserts rather than throwing exceptions. Currently this is only used - // in cases like the verifier where the checks cannot fail and initCause isn't overridden. - void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static Class* GetJavaLangThrowable() { - DCHECK(java_lang_Throwable_ != NULL); - return java_lang_Throwable_; - } - - static void SetClass(Class* java_lang_Throwable); - static void ResetClass(); - - private: - Object* GetStackState() const { - return GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true); - } - - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - Throwable* cause_; - String* detail_message_; - Object* stack_state_; // Note this is Java volatile: - Object* stack_trace_; - Object* suppressed_exceptions_; - - static Class* java_lang_Throwable_; - - friend struct ThrowableOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable); -}; - -// C++ mirror of java.lang.StackTraceElement -class MANAGED StackTraceElement : public Object { - public: - const String* GetDeclaringClass() const { - return GetFieldObject<const String*>( - OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false); - } - - const String* GetMethodName() const { - return GetFieldObject<const String*>( - OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false); - } - - const String* GetFileName() const { - return GetFieldObject<const String*>( - OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false); - } - - int32_t GetLineNumber() const { - return GetField32( - OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false); - } - - static StackTraceElement* Alloc(Thread* self, - String* declaring_class, - String* method_name, - String* file_name, - int32_t line_number) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static void SetClass(Class* java_lang_StackTraceElement); - - static void ResetClass(); - - private: - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - String* declaring_class_; - String* file_name_; - String* method_name_; - int32_t line_number_; - - static Class* GetStackTraceElement() { - DCHECK(java_lang_StackTraceElement_ != NULL); - return java_lang_StackTraceElement_; - } - - static Class* java_lang_StackTraceElement_; - - friend struct StackTraceElementOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement); -}; - -class MANAGED SynthesizedProxyClass : public Class { - public: - ObjectArray<Class>* GetInterfaces() { - return interfaces_; - } - - ObjectArray<ObjectArray<Class> >* GetThrows() { - return throws_; - } - - private: - ObjectArray<Class>* interfaces_; - ObjectArray<ObjectArray<Class> >* throws_; - DISALLOW_IMPLICIT_CONSTRUCTORS(SynthesizedProxyClass); -}; - -class MANAGED Proxy : public Object { - private: - Object* h_; - - friend struct ProxyOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy); -}; - -} // namespace art - -#endif // ART_SRC_OBJECT_H_ diff --git a/src/object_utils.h b/src/object_utils.h index 068dd66fdd..ea4de903b1 100644 --- a/src/object_utils.h +++ b/src/object_utils.h @@ -18,14 +18,17 @@ #define ART_SRC_OBJECT_UTILS_H_ #include "class_linker.h" -#include "dex_cache.h" #include "dex_file.h" -#include "intern_table.h" #include "monitor.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "mirror/class.h" +#include "mirror/dex_cache.h" +#include "mirror/field.h" +#include "mirror/iftable.h" +#include "mirror/string.h" + #include "runtime.h" #include "sirt_ref.h" -#include "UniquePtr.h" #include <string> @@ -33,7 +36,7 @@ namespace art { class ObjectLock { public: - explicit ObjectLock(Thread* self, Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + explicit ObjectLock(Thread* self, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : self_(self), obj_(object) { CHECK(object != NULL); obj_->MonitorEnter(self_); @@ -57,13 +60,13 @@ class ObjectLock { private: Thread* const self_; - Object* obj_; + mirror::Object* obj_; DISALLOW_COPY_AND_ASSIGN(ObjectLock); }; class ClassHelper { public: - ClassHelper(const Class* c = NULL, ClassLinker* l = NULL) + ClassHelper(const mirror::Class* c = NULL, ClassLinker* l = NULL) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : class_def_(NULL), class_linker_(l), @@ -76,12 +79,12 @@ class ClassHelper { } } - void ChangeClass(const Class* new_c) + void ChangeClass(const mirror::Class* new_c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(new_c != NULL) << "klass_=" << klass_; // Log what we were changing from if any CHECK(new_c->IsClass()) << "new_c=" << new_c; if (dex_cache_ != NULL) { - DexCache* new_c_dex_cache = new_c->GetDexCache(); + mirror::DexCache* new_c_dex_cache = new_c->GetDexCache(); if (new_c_dex_cache != dex_cache_) { dex_cache_ = new_c_dex_cache; dex_file_ = NULL; @@ -112,7 +115,7 @@ class ClassHelper { const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string result("["); - const Class* saved_klass = klass_; + const mirror::Class* saved_klass = klass_; CHECK(saved_klass != NULL); ChangeClass(klass_->GetComponentType()); result += GetDescriptor(); @@ -157,7 +160,7 @@ class ClassHelper { return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_; } - Class* GetDirectInterface(uint32_t idx) + mirror::Class* GetDirectInterface(uint32_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(klass_ != NULL); DCHECK(!klass_->IsPrimitive()); @@ -172,7 +175,7 @@ class ClassHelper { return klass_->GetIfTable()->GetInterface(idx); } else { uint16_t type_idx = GetDirectInterfaceTypeIdx(idx); - Class* interface = GetDexCache()->GetResolvedType(type_idx); + mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx); if (interface == NULL) { interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_); CHECK(interface != NULL || Thread::Current()->IsExceptionPending()); @@ -190,7 +193,7 @@ class ClassHelper { } std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* dex_cache = GetDexCache(); + mirror::DexCache* dex_cache = GetDexCache(); if (dex_cache != NULL && !klass_->IsProxyClass()) { return dex_cache->GetLocation()->ToModifiedUtf8(); } else { @@ -206,8 +209,8 @@ class ClassHelper { return *dex_file_; } - DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* result = dex_cache_; + mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::DexCache* result = dex_cache_; if (result == NULL) { DCHECK(klass_ != NULL); result = klass_->GetDexCache(); @@ -241,10 +244,10 @@ class ClassHelper { const DexFile::ClassDef* class_def_; ClassLinker* class_linker_; - DexCache* dex_cache_; + mirror::DexCache* dex_cache_; const DexFile* dex_file_; const DexFile::TypeList* interface_type_list_; - const Class* klass_; + const mirror::Class* klass_; std::string descriptor_; DISALLOW_COPY_AND_ASSIGN(ClassHelper); @@ -253,14 +256,14 @@ class ClassHelper { class FieldHelper { public: FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {} - explicit FieldHelper(const Field* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {} - FieldHelper(const Field* f, ClassLinker* l) + explicit FieldHelper(const mirror::Field* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {} + FieldHelper(const mirror::Field* f, ClassLinker* l) : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), field_(f) {} - void ChangeField(const Field* new_f) { + void ChangeField(const mirror::Field* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(new_f != NULL); if (dex_cache_ != NULL) { - DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache(); + mirror::DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache(); if (new_f_dex_cache != dex_cache_) { dex_cache_ = new_f_dex_cache; dex_file_ = NULL; @@ -279,22 +282,12 @@ class FieldHelper { return field_index == 0 ? "interfaces" : "throws"; } } - String* GetNameAsString() { - uint32_t field_index = field_->GetDexFieldIndex(); - if (!field_->GetDeclaringClass()->IsProxyClass()) { - const DexFile& dex_file = GetDexFile(); - const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); - return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache()); - } else { - return Runtime::Current()->GetInternTable()->InternStrong(GetName()); - } - } - Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); if (!field_->GetDeclaringClass()->IsProxyClass()) { const DexFile& dex_file = GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); - Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_); + mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_); if (type == NULL) { type = GetClassLinker()->ResolveType(field_id.type_idx_, field_); CHECK(type != NULL || Thread::Current()->IsExceptionPending()); @@ -347,8 +340,8 @@ class FieldHelper { } private: - DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* result = dex_cache_; + mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::DexCache* result = dex_cache_; if (result == NULL) { result = field_->GetDeclaringClass()->GetDexCache(); dex_cache_ = result; @@ -371,9 +364,9 @@ class FieldHelper { } ClassLinker* class_linker_; - DexCache* dex_cache_; + mirror::DexCache* dex_cache_; const DexFile* dex_file_; - const Field* field_; + const mirror::Field* field_; std::string declaring_class_descriptor_; DISALLOW_COPY_AND_ASSIGN(FieldHelper); @@ -385,29 +378,29 @@ class MethodHelper { : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) {} - explicit MethodHelper(const AbstractMethod* m) + explicit MethodHelper(const mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) { SetMethod(m); } - MethodHelper(const AbstractMethod* m, ClassLinker* l) + MethodHelper(const mirror::AbstractMethod* m, ClassLinker* l) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) { SetMethod(m); } - void ChangeMethod(AbstractMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void ChangeMethod(mirror::AbstractMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(new_m != NULL); if (dex_cache_ != NULL) { - Class* klass = new_m->GetDeclaringClass(); + mirror::Class* klass = new_m->GetDeclaringClass(); if (klass->IsProxyClass()) { dex_cache_ = NULL; dex_file_ = NULL; } else { - DexCache* new_m_dex_cache = klass->GetDexCache(); + mirror::DexCache* new_m_dex_cache = klass->GetDexCache(); if (new_m_dex_cache != dex_cache_) { dex_cache_ = new_m_dex_cache; dex_file_ = NULL; @@ -439,7 +432,7 @@ class MethodHelper { } } - String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile& dex_file = GetDexFile(); uint32_t dex_method_idx = method_->GetDexMethodIndex(); const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); @@ -487,17 +480,18 @@ class MethodHelper { return GetDexFile().GetProtoParameters(proto); } - ObjectArray<Class>* GetParameterTypes(Thread* self) + mirror::ObjectArray<mirror::Class>* GetParameterTypes(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile::TypeList* params = GetParameterTypeList(); uint32_t num_params = params == NULL ? 0 : params->Size(); - SirtRef<ObjectArray<Class> > result(self, GetClassLinker()->AllocClassArray(self, num_params)); + SirtRef<mirror::ObjectArray<mirror::Class> > + result(self, GetClassLinker()->AllocClassArray(self, num_params)); if (UNLIKELY(result.get() == NULL)) { CHECK(self->IsExceptionPending()); return NULL; } for (uint32_t i = 0; i < num_params; i++) { - Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_); + mirror::Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_); if (param_type == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); return NULL; @@ -507,7 +501,7 @@ class MethodHelper { return result.get(); } - Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile& dex_file = GetDexFile(); const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex()); const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id); @@ -536,7 +530,7 @@ class MethodHelper { const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* klass = method_->GetDeclaringClass(); + mirror::Class* klass = method_->GetDeclaringClass(); DCHECK(!klass->IsProxyClass()); uint16_t type_idx = klass->GetDexTypeIndex(); const DexFile& dex_file = GetDexFile(); @@ -561,7 +555,7 @@ class MethodHelper { return index; } - ClassLoader* GetClassLoader() + mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return method_->GetDeclaringClass()->GetClassLoader(); } @@ -626,9 +620,9 @@ class MethodHelper { return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL; } - Class* GetClassFromTypeIdx(uint16_t type_idx) + mirror::Class* GetClassFromTypeIdx(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx); + mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx); if (type == NULL) { type = GetClassLinker()->ResolveType(type_idx, method_); CHECK(type != NULL || Thread::Current()->IsExceptionPending()); @@ -642,7 +636,7 @@ class MethodHelper { return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx)); } - Class* GetDexCacheResolvedType(uint16_t type_idx) + mirror::Class* GetDexCacheResolvedType(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return method_->GetDexCacheResolvedTypes()->Get(type_idx); } @@ -650,24 +644,24 @@ class MethodHelper { const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile* result = dex_file_; if (result == NULL) { - const DexCache* dex_cache = GetDexCache(); + const mirror::DexCache* dex_cache = GetDexCache(); result = dex_file_ = dex_cache->GetDexFile(); } return *result; } - DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DexCache* result = dex_cache_; + mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::DexCache* result = dex_cache_; if (result == NULL) { - Class* klass = method_->GetDeclaringClass(); + mirror::Class* klass = method_->GetDeclaringClass(); result = klass->GetDexCache(); dex_cache_ = result; } return result; } - String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - String* s = method_->GetDexCacheStrings()->Get(string_idx); + mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx); if (UNLIKELY(s == NULL)) { s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, GetDexCache()); } @@ -677,11 +671,11 @@ class MethodHelper { private: // Set the method_ field, for proxy methods looking up the interface method via the resolved // methods table. - void SetMethod(const AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void SetMethod(const mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (method != NULL) { - Class* klass = method->GetDeclaringClass(); + mirror::Class* klass = method->GetDeclaringClass(); if (klass->IsProxyClass()) { - AbstractMethod* interface_method = + mirror::AbstractMethod* interface_method = method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex()); CHECK(interface_method != NULL); CHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method)); @@ -701,9 +695,9 @@ class MethodHelper { } ClassLinker* class_linker_; - DexCache* dex_cache_; + mirror::DexCache* dex_cache_; const DexFile* dex_file_; - const AbstractMethod* method_; + const mirror::AbstractMethod* method_; const char* shorty_; uint32_t shorty_len_; diff --git a/src/primitive.h b/src/primitive.h index cb78ccc293..eaa04cd054 100644 --- a/src/primitive.h +++ b/src/primitive.h @@ -23,8 +23,9 @@ #include "base/macros.h" namespace art { - +namespace mirror { class Object; +} // namespace mirror class Primitive { public: @@ -77,7 +78,7 @@ class Primitive { case kPrimFloat: return 4; case kPrimLong: case kPrimDouble: return 8; - case kPrimNot: return sizeof(Object*); + case kPrimNot: return sizeof(mirror::Object*); default: LOG(FATAL) << "Invalid type " << static_cast<int>(type); return 0; diff --git a/src/reference_table.cc b/src/reference_table.cc index cdb3004440..192535ab02 100644 --- a/src/reference_table.cc +++ b/src/reference_table.cc @@ -18,8 +18,14 @@ #include "base/mutex.h" #include "indirect_reference_table.h" - -#include "object.h" +#include "mirror/array.h" +#include "mirror/array-inl.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" +#include "mirror/string.h" +#include "thread.h" +#include "utils.h" namespace art { @@ -32,7 +38,7 @@ ReferenceTable::ReferenceTable(const char* name, size_t initial_size, size_t max ReferenceTable::~ReferenceTable() { } -void ReferenceTable::Add(const Object* obj) { +void ReferenceTable::Add(const mirror::Object* obj) { DCHECK(obj != NULL); if (entries_.size() == max_size_) { LOG(FATAL) << "ReferenceTable '" << name_ << "' " @@ -41,7 +47,7 @@ void ReferenceTable::Add(const Object* obj) { entries_.push_back(obj); } -void ReferenceTable::Remove(const Object* obj) { +void ReferenceTable::Remove(const mirror::Object* obj) { // We iterate backwards on the assumption that references are LIFO. for (int i = entries_.size() - 1; i >= 0; --i) { if (entries_[i] == obj) { @@ -53,7 +59,7 @@ void ReferenceTable::Remove(const Object* obj) { // If "obj" is an array, return the number of elements in the array. // Otherwise, return zero. -static size_t GetElementCount(const Object* obj) { +static size_t GetElementCount(const mirror::Object* obj) { if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) { return 0; } @@ -61,7 +67,7 @@ static size_t GetElementCount(const Object* obj) { } struct ObjectComparator { - bool operator()(const Object* obj1, const Object* obj2) + bool operator()(const mirror::Object* obj1, const mirror::Object* obj2) // TODO: enable analysis when analysis can work with the STL. NO_THREAD_SAFETY_ANALYSIS { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); @@ -99,7 +105,7 @@ struct ObjectComparator { // Pass in the number of elements in the array (or 0 if this is not an // array object), and the number of additional objects that are identical // or equivalent to the original. -static void DumpSummaryLine(std::ostream& os, const Object* obj, size_t element_count, +static void DumpSummaryLine(std::ostream& os, const mirror::Object* obj, size_t element_count, int identical, int equiv) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (obj == NULL) { @@ -153,7 +159,7 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) { } os << " Last " << (count - first) << " entries (of " << count << "):\n"; for (int idx = count - 1; idx >= first; --idx) { - const Object* ref = entries[idx]; + const mirror::Object* ref = entries[idx]; if (ref == NULL) { continue; } @@ -175,7 +181,7 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) { if (element_count != 0) { StringAppendF(&extras, " (%zd elements)", element_count); } else if (ref->GetClass()->IsStringClass()) { - String* s = const_cast<Object*>(ref)->AsString(); + mirror::String* s = const_cast<mirror::Object*>(ref)->AsString(); std::string utf8(s->ToModifiedUtf8()); if (s->GetLength() <= 16) { StringAppendF(&extras, " \"%s\"", utf8.c_str()); @@ -206,8 +212,8 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) { size_t equiv = 0; size_t identical = 0; for (size_t idx = 1; idx < count; idx++) { - const Object* prev = sorted_entries[idx-1]; - const Object* current = sorted_entries[idx]; + const mirror::Object* prev = sorted_entries[idx-1]; + const mirror::Object* current = sorted_entries[idx]; size_t element_count = GetElementCount(prev); if (current == prev) { // Same reference, added more than once. @@ -225,7 +231,7 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) { DumpSummaryLine(os, sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv); } -void ReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void ReferenceTable::VisitRoots(RootVisitor* visitor, void* arg) { typedef Table::const_iterator It; // TODO: C++0x auto for (It it = entries_.begin(), end = entries_.end(); it != end; ++it) { visitor(*it, arg); diff --git a/src/reference_table.h b/src/reference_table.h index f398eb2a44..5abb5c7b46 100644 --- a/src/reference_table.h +++ b/src/reference_table.h @@ -22,11 +22,13 @@ #include <string> #include <vector> -#include "heap.h" +#include "locks.h" +#include "root_visitor.h" namespace art { - +namespace mirror { class Object; +} // namespace mirror // Maintain a table of references. Used for JNI monitor references and // JNI pinned array references. @@ -37,18 +39,18 @@ class ReferenceTable { ReferenceTable(const char* name, size_t initial_size, size_t max_size); ~ReferenceTable(); - void Add(const Object* obj); + void Add(const mirror::Object* obj); - void Remove(const Object* obj); + void Remove(const mirror::Object* obj); size_t Size() const; void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void VisitRoots(Heap::RootVisitor* visitor, void* arg); + void VisitRoots(RootVisitor* visitor, void* arg); private: - typedef std::vector<const Object*> Table; + typedef std::vector<const mirror::Object*> Table; static void Dump(std::ostream& os, const Table& entries) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); friend class IndirectReferenceTable; // For Dump. diff --git a/src/reference_table_test.cc b/src/reference_table_test.cc index c400f83c3c..16fbd94b21 100644 --- a/src/reference_table_test.cc +++ b/src/reference_table_test.cc @@ -25,7 +25,7 @@ class ReferenceTableTest : public CommonTest { TEST_F(ReferenceTableTest, Basics) { ScopedObjectAccess soa(Thread::Current()); - Object* o1 = String::AllocFromModifiedUtf8(soa.Self(), "hello"); + mirror::Object* o1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"); ReferenceTable rt("test", 0, 11); @@ -56,7 +56,7 @@ TEST_F(ReferenceTableTest, Basics) { } // Add a second object 10 times and check dumping is sane. - Object* o2 = ShortArray::Alloc(soa.Self(), 0); + mirror::Object* o2 = mirror::ShortArray::Alloc(soa.Self(), 0); for (size_t i = 0; i < 10; ++i) { rt.Add(o2); EXPECT_EQ(i + 2, rt.Size()); diff --git a/src/reflection.cc b/src/reflection.cc index 1ffad3fbf9..16a5502061 100644 --- a/src/reflection.cc +++ b/src/reflection.cc @@ -18,7 +18,13 @@ #include "class_linker.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "well_known_classes.h" @@ -28,17 +34,17 @@ namespace art { jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject javaReceiver, jobject javaArgs) { jmethodID mid = soa.Env()->FromReflectedMethod(javaMethod); - AbstractMethod* m = soa.DecodeMethod(mid); + mirror::AbstractMethod* m = soa.DecodeMethod(mid); - Class* declaring_class = m->GetDeclaringClass(); + mirror::Class* declaring_class = m->GetDeclaringClass(); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true, true)) { return NULL; } - Object* receiver = NULL; + mirror::Object* receiver = NULL; if (!m->IsStatic()) { // Check that the receiver is non-null and an instance of the field's declaring class. - receiver = soa.Decode<Object*>(javaReceiver); + receiver = soa.Decode<mirror::Object*>(javaReceiver); if (!VerifyObjectInClass(receiver, declaring_class)) { return NULL; } @@ -49,7 +55,8 @@ jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject } // Get our arrays of arguments and their types, and check they're the same size. - ObjectArray<Object>* objects = soa.Decode<ObjectArray<Object>*>(javaArgs); + mirror::ObjectArray<mirror::Object>* objects = + soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs); MethodHelper mh(m); const DexFile::TypeList* classes = mh.GetParameterTypeList(); uint32_t classes_size = classes == NULL ? 0 : classes->Size(); @@ -65,8 +72,8 @@ jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject UniquePtr<jvalue[]> args(new jvalue[arg_count]); JValue* decoded_args = reinterpret_cast<JValue*>(args.get()); for (uint32_t i = 0; i < arg_count; ++i) { - Object* arg = objects->Get(i); - Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_); + mirror::Object* arg = objects->Get(i); + mirror::Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_); if (!UnboxPrimitiveForArgument(arg, dst_class, decoded_args[i], m, i)) { return NULL; } @@ -93,7 +100,7 @@ jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject return soa.AddLocalReference<jobject>(BoxPrimitive(mh.GetReturnType()->GetPrimitiveType(), value)); } -bool VerifyObjectInClass(Object* o, Class* c) { +bool VerifyObjectInClass(mirror::Object* o, mirror::Class* c) { const char* exception = NULL; if (o == NULL) { exception = "Ljava/lang/NullPointerException;"; @@ -194,7 +201,7 @@ bool ConvertPrimitiveValue(Primitive::Type srcType, Primitive::Type dstType, return false; } -Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { +mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { if (src_class == Primitive::kPrimNot) { return value.GetL(); } @@ -242,7 +249,7 @@ Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { return result.GetL(); } -static std::string UnboxingFailureKind(AbstractMethod* m, int index, Field* f) +static std::string UnboxingFailureKind(mirror::AbstractMethod* m, int index, mirror::Field* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (m != NULL && index != -1) { ++index; // Humans count from 1. @@ -254,8 +261,8 @@ static std::string UnboxingFailureKind(AbstractMethod* m, int index, Field* f) return "result"; } -static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, AbstractMethod* m, - int index, Field* f) +static bool UnboxPrimitive(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, + mirror::AbstractMethod* m, int index, mirror::Field* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (!dst_class->IsPrimitive()) { if (o != NULL && !o->InstanceOf(dst_class)) { @@ -285,9 +292,9 @@ static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, A JValue boxed_value; std::string src_descriptor(ClassHelper(o->GetClass()).GetDescriptor()); - Class* src_class = NULL; + mirror::Class* src_class = NULL; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Field* primitive_field = o->GetClass()->GetIFields()->Get(0); + mirror::Field* primitive_field = o->GetClass()->GetIFields()->Get(0); if (src_descriptor == "Ljava/lang/Boolean;") { src_class = class_linker->FindPrimitiveClass('Z'); boxed_value.SetZ(primitive_field->GetBoolean(o)); @@ -325,17 +332,19 @@ static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, A boxed_value, unboxed_value); } -bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, AbstractMethod* m, size_t index) { +bool UnboxPrimitiveForArgument(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, + mirror::AbstractMethod* m, size_t index) { CHECK(m != NULL); return UnboxPrimitive(o, dst_class, unboxed_value, m, index, NULL); } -bool UnboxPrimitiveForField(Object* o, Class* dst_class, JValue& unboxed_value, Field* f) { +bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, + mirror::Field* f) { CHECK(f != NULL); return UnboxPrimitive(o, dst_class, unboxed_value, NULL, -1, f); } -bool UnboxPrimitiveForResult(Object* o, Class* dst_class, JValue& unboxed_value) { +bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value) { return UnboxPrimitive(o, dst_class, unboxed_value, NULL, -1, NULL); } diff --git a/src/reflection.h b/src/reflection.h index 601543f346..8f3224380c 100644 --- a/src/reflection.h +++ b/src/reflection.h @@ -21,22 +21,24 @@ #include "primitive.h" namespace art { - +namespace mirror { +class AbstractMethod; class Class; class Field; -union JValue; -class AbstractMethod; class Object; +} // namespace mirror +union JValue; class ScopedObjectAccess; -Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) +mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, - AbstractMethod* m, size_t index) +bool UnboxPrimitiveForArgument(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, + mirror::AbstractMethod* m, size_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool UnboxPrimitiveForField(Object* o, Class* dst_class, JValue& unboxed_value, Field* f) +bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, + mirror::Field* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool UnboxPrimitiveForResult(Object* o, Class* dst_class, JValue& unboxed_value) +bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, const JValue& src, @@ -46,7 +48,7 @@ bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, jobject InvokeMethod(const ScopedObjectAccess& soa, jobject method, jobject receiver, jobject args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool VerifyObjectInClass(Object* o, Class* c) +bool VerifyObjectInClass(mirror::Object* o, mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } // namespace art diff --git a/src/root_visitor.h b/src/root_visitor.h new file mode 100644 index 0000000000..d53acd3621 --- /dev/null +++ b/src/root_visitor.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_ROOT_VISITOR_H_ +#define ART_SRC_ROOT_VISITOR_H_ + +namespace art { +namespace mirror { +class Object; +} // namespace mirror +class StackVisitor; + +typedef void (RootVisitor)(const mirror::Object* root, void* arg); +typedef void (VerifyRootVisitor)(const mirror::Object* root, void* arg, size_t vreg, + const StackVisitor* visitor); +typedef bool (IsMarkedTester)(const mirror::Object* object, void* arg); + +} // namespace art + +#endif // ART_SRC_ROOT_VISITOR_H_ diff --git a/src/runtime.cc b/src/runtime.cc index 5c73fef7d0..085a9bfdbf 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -24,17 +24,24 @@ #include <limits> #include <vector> +#include "atomic.h" #include "class_linker.h" -#include "class_loader.h" #include "constants_arm.h" #include "constants_mips.h" #include "constants_x86.h" #include "debugger.h" +#include "gc/card_table-inl.h" #include "heap.h" #include "image.h" #include "instrumentation.h" #include "intern_table.h" #include "jni_internal.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/array.h" +#include "mirror/class_loader.h" +#include "mirror/field.h" +#include "mirror/object-inl.h" +#include "mirror/throwable.h" #include "monitor.h" #include "oat_file.h" #include "ScopedLocalRef.h" @@ -627,23 +634,25 @@ static void CreateSystemClassLoader() { ScopedObjectAccess soa(Thread::Current()); - Class* class_loader_class = soa.Decode<Class*>(WellKnownClasses::java_lang_ClassLoader); + mirror::Class* class_loader_class = + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader); CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true)); - AbstractMethod* getSystemClassLoader = class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;"); + mirror::AbstractMethod* getSystemClassLoader = + class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;"); CHECK(getSystemClassLoader != NULL); - ClassLoader* class_loader = - down_cast<ClassLoader*>(InvokeWithJValues(soa, NULL, getSystemClassLoader, NULL).GetL()); + mirror::ClassLoader* class_loader = + down_cast<mirror::ClassLoader*>(InvokeWithJValues(soa, NULL, getSystemClassLoader, NULL).GetL()); CHECK(class_loader != NULL); soa.Self()->SetClassLoaderOverride(class_loader); - Class* thread_class = soa.Decode<Class*>(WellKnownClasses::java_lang_Thread); + mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(thread_class, true, true)); - Field* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader", - "Ljava/lang/ClassLoader;"); + mirror::Field* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader", + "Ljava/lang/ClassLoader;"); CHECK(contextClassLoader != NULL); contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader); @@ -1015,7 +1024,7 @@ void Runtime::DetachCurrentThread() { thread_list_->Unregister(self); } -void Runtime::VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg) { +void Runtime::VisitConcurrentRoots(RootVisitor* visitor, void* arg) { if (intern_table_->IsDirty()) { intern_table_->VisitRoots(visitor, arg); } @@ -1024,7 +1033,7 @@ void Runtime::VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg) { } } -void Runtime::VisitNonThreadRoots(Heap::RootVisitor* visitor, void* arg) { +void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) { Dbg::VisitRoots(visitor, arg); java_vm_->VisitRoots(visitor, arg); if (pre_allocated_OutOfMemoryError_ != NULL) { @@ -1041,7 +1050,7 @@ void Runtime::VisitNonThreadRoots(Heap::RootVisitor* visitor, void* arg) { } } -void Runtime::VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg) { +void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) { thread_list_->VisitRoots(visitor, arg); VisitNonThreadRoots(visitor, arg); } @@ -1053,48 +1062,50 @@ void Runtime::DirtyRoots() { class_linker_->Dirty(); } -void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void Runtime::VisitRoots(RootVisitor* visitor, void* arg) { VisitConcurrentRoots(visitor, arg); VisitNonConcurrentRoots(visitor, arg); } -void Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) { +void Runtime::SetJniDlsymLookupStub(mirror::ByteArray* jni_stub_array) { CHECK(jni_stub_array != NULL) << " jni_stub_array=" << jni_stub_array; CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array) << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array; jni_stub_array_ = jni_stub_array; } -void Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) { +void Runtime::SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array) { CHECK(abstract_method_error_stub_array != NULL); CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array); abstract_method_error_stub_array_ = abstract_method_error_stub_array; } -void Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) { +void Runtime::SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type) { CHECK(resolution_stub_array != NULL); CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array); resolution_stub_array_[type] = resolution_stub_array; } -AbstractMethod* Runtime::CreateResolutionMethod() { - Class* method_class = AbstractMethod::GetMethodClass(); +mirror::AbstractMethod* Runtime::CreateResolutionMethod() { + mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass(); Thread* self = Thread::Current(); - SirtRef<AbstractMethod> method(self, down_cast<AbstractMethod*>(method_class->AllocObject(self))); + SirtRef<mirror::AbstractMethod> + method(self, down_cast<mirror::AbstractMethod*>(method_class->AllocObject(self))); method->SetDeclaringClass(method_class); // TODO: use a special method for resolution method saves method->SetDexMethodIndex(DexFile::kDexNoIndex16); - ByteArray* unknown_resolution_stub = GetResolutionStubArray(kUnknownMethod); + mirror::ByteArray* unknown_resolution_stub = GetResolutionStubArray(kUnknownMethod); CHECK(unknown_resolution_stub != NULL); method->SetCode(unknown_resolution_stub->GetData()); return method.get(); } -AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, - CalleeSaveType type) { - Class* method_class = AbstractMethod::GetMethodClass(); +mirror::AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, + CalleeSaveType type) { + mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass(); Thread* self = Thread::Current(); - SirtRef<AbstractMethod> method(self, down_cast<AbstractMethod*>(method_class->AllocObject(self))); + SirtRef<mirror::AbstractMethod> + method(self, down_cast<mirror::AbstractMethod*>(method_class->AllocObject(self))); method->SetDeclaringClass(method_class); // TODO: use a special method for callee saves method->SetDexMethodIndex(DexFile::kDexNoIndex16); @@ -1154,7 +1165,7 @@ AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, return method.get(); } -void Runtime::SetCalleeSaveMethod(AbstractMethod* method, CalleeSaveType type) { +void Runtime::SetCalleeSaveMethod(mirror::AbstractMethod* method, CalleeSaveType type) { DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType)); callee_save_methods_[type] = method; } diff --git a/src/runtime.h b/src/runtime.h index 84cc8262ca..1d71c1326a 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -32,6 +32,7 @@ #include "instruction_set.h" #include "jobject_comparator.h" #include "locks.h" +#include "root_visitor.h" #include "runtime_stats.h" #include "safe_map.h" @@ -41,21 +42,23 @@ namespace art { +namespace mirror { +class AbstractMethod; +class ClassLoader; template<class T> class PrimitiveArray; typedef PrimitiveArray<int8_t> ByteArray; +class String; +class Throwable; +} // namespace mirror class ClassLinker; -class ClassLoader; class DexFile; class Heap; class Instrumentation; class InternTable; struct JavaVMExt; -class AbstractMethod; class MonitorList; class SignalCatcher; -class String; class ThreadList; -class Throwable; class Trace; class Runtime { @@ -215,7 +218,7 @@ class Runtime { return monitor_list_; } - Throwable* GetPreAllocatedOutOfMemoryError() { + mirror::Throwable* GetPreAllocatedOutOfMemoryError() { return pre_allocated_OutOfMemoryError_; } @@ -235,40 +238,40 @@ class Runtime { void DirtyRoots(); // Visit all the roots. - void VisitRoots(Heap::RootVisitor* visitor, void* arg) + void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Visit all of the roots we can do safely do concurrently. - void VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg); + void VisitConcurrentRoots(RootVisitor* visitor, void* arg); // Visit all of the non thread roots, we can do this with mutators unpaused. - void VisitNonThreadRoots(Heap::RootVisitor* visitor, void* arg); + void VisitNonThreadRoots(RootVisitor* visitor, void* arg); // Visit all other roots which must be done with mutators suspended. - void VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg) + void VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasJniDlsymLookupStub() const { return jni_stub_array_ != NULL; } - ByteArray* GetJniDlsymLookupStub() const { + mirror::ByteArray* GetJniDlsymLookupStub() const { CHECK(HasJniDlsymLookupStub()); return jni_stub_array_; } - void SetJniDlsymLookupStub(ByteArray* jni_stub_array); + void SetJniDlsymLookupStub(mirror::ByteArray* jni_stub_array); bool HasAbstractMethodErrorStubArray() const { return abstract_method_error_stub_array_ != NULL; } - ByteArray* GetAbstractMethodErrorStubArray() const { + mirror::ByteArray* GetAbstractMethodErrorStubArray() const { CHECK(abstract_method_error_stub_array_ != NULL); return abstract_method_error_stub_array_; } - void SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array); + void SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array); enum TrampolineType { kStaticMethod, @@ -280,16 +283,16 @@ class Runtime { return resolution_stub_array_[type] != NULL; } - ByteArray* GetResolutionStubArray(TrampolineType type) const { + mirror::ByteArray* GetResolutionStubArray(TrampolineType type) const { CHECK(HasResolutionStubArray(type)); DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType)); return resolution_stub_array_[type]; } - void SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type); + void SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type); // Returns a special method that calls into a trampoline for runtime method resolution - AbstractMethod* GetResolutionMethod() const { + mirror::AbstractMethod* GetResolutionMethod() const { CHECK(HasResolutionMethod()); return resolution_method_; } @@ -298,11 +301,11 @@ class Runtime { return resolution_method_ != NULL; } - void SetResolutionMethod(AbstractMethod* method) { + void SetResolutionMethod(mirror::AbstractMethod* method) { resolution_method_ = method; } - AbstractMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::AbstractMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns a special method that describes all callee saves being spilled to the stack. enum CalleeSaveType { @@ -316,20 +319,21 @@ class Runtime { return callee_save_methods_[type] != NULL; } - AbstractMethod* GetCalleeSaveMethod(CalleeSaveType type) const { + mirror::AbstractMethod* GetCalleeSaveMethod(CalleeSaveType type) const { DCHECK(HasCalleeSaveMethod(type)); return callee_save_methods_[type]; } - void SetCalleeSaveMethod(AbstractMethod* method, CalleeSaveType type); + void SetCalleeSaveMethod(mirror::AbstractMethod* method, CalleeSaveType type); - AbstractMethod* CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) + mirror::AbstractMethod* CreateCalleeSaveMethod(InstructionSet instruction_set, + CalleeSaveType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateRefOnlyCalleeSaveMethod(InstructionSet instruction_set) + mirror::AbstractMethod* CreateRefOnlyCalleeSaveMethod(InstructionSet instruction_set) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateRefAndArgsCalleeSaveMethod(InstructionSet instruction_set) + mirror::AbstractMethod* CreateRefAndArgsCalleeSaveMethod(InstructionSet instruction_set) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); int32_t GetStat(int kind); @@ -419,20 +423,20 @@ class Runtime { JavaVMExt* java_vm_; - Throwable* pre_allocated_OutOfMemoryError_; + mirror::Throwable* pre_allocated_OutOfMemoryError_; - ByteArray* jni_stub_array_; + mirror::ByteArray* jni_stub_array_; - ByteArray* abstract_method_error_stub_array_; + mirror::ByteArray* abstract_method_error_stub_array_; - ByteArray* resolution_stub_array_[kLastTrampolineMethodType]; + mirror::ByteArray* resolution_stub_array_[kLastTrampolineMethodType]; - AbstractMethod* callee_save_methods_[kLastCalleeSaveType]; + mirror::AbstractMethod* callee_save_methods_[kLastCalleeSaveType]; - AbstractMethod* resolution_method_; + mirror::AbstractMethod* resolution_method_; // As returned by ClassLoader.getSystemClassLoader() - ClassLoader* system_class_loader_; + mirror::ClassLoader* system_class_loader_; // A non-zero value indicates that a thread has been created but not yet initialized. Guarded by // the shutdown lock so that threads aren't born while we're shutting down. diff --git a/src/runtime_support.cc b/src/runtime_support.cc index b276917be9..84a19cf491 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -16,6 +16,14 @@ #include "runtime_support.h" +#include "class_linker-inl.h" +#include "gc/card_table-inl.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class-inl.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/proxy.h" #include "reflection.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" @@ -92,13 +100,14 @@ int32_t art_f2i(float f) { namespace art { // Helper function to allocate array for FILLED_NEW_ARRAY. -Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, - Thread* self, bool access_check) { +mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + int32_t component_count, Thread* self, + bool access_check) { if (UNLIKELY(component_count < 0)) { self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); return NULL; // Failure } - Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); + mirror::Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); if (klass == NULL) { // Error @@ -119,19 +128,19 @@ Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int return NULL; // Failure } else { if (access_check) { - Class* referrer = method->GetDeclaringClass(); + mirror::Class* referrer = method->GetDeclaringClass(); if (UNLIKELY(!referrer->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referrer, klass); return NULL; // Failure } } DCHECK(klass->IsArrayClass()) << PrettyClass(klass); - return Array::Alloc(self, klass, component_count); + return mirror::Array::Alloc(self, klass, component_count); } } -Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self, - FindFieldType type, size_t expected_size) { +mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer, + Thread* self, FindFieldType type, size_t expected_size) { bool is_primitive; bool is_set; bool is_static; @@ -147,7 +156,7 @@ Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thr default: is_primitive = true; is_set = true; is_static = true; break; } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); + mirror::Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); if (UNLIKELY(resolved_field == NULL)) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return NULL; // Failure. @@ -156,8 +165,8 @@ Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thr ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); return NULL; } - Class* fields_class = resolved_field->GetDeclaringClass(); - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(fields_class) || !referring_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()))) { @@ -210,11 +219,12 @@ Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thr } // Slow path method resolution -AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer, - Thread* self, bool access_check, InvokeType type) { +mirror::AbstractMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object, + mirror::AbstractMethod* referrer, + Thread* self, bool access_check, InvokeType type) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); bool is_direct = type == kStatic || type == kDirect; - AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type); + mirror::AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type); if (UNLIKELY(resolved_method == NULL)) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return NULL; // Failure. @@ -228,7 +238,7 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs if (is_direct) { return resolved_method; } else if (type == kInterface) { - AbstractMethod* interface_method = + mirror::AbstractMethod* interface_method = this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); if (UNLIKELY(interface_method == NULL)) { ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, @@ -238,7 +248,7 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs return interface_method; } } else { - ObjectArray<AbstractMethod>* vtable; + mirror::ObjectArray<mirror::AbstractMethod>* vtable; uint16_t vtable_index = resolved_method->GetMethodIndex(); if (type == kSuper) { vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable(); @@ -255,8 +265,8 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs referrer); return NULL; // Failure. } - Class* methods_class = resolved_method->GetDeclaringClass(); - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* methods_class = resolved_method->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(methods_class) || !referring_class->CanAccessMember(methods_class, resolved_method->GetAccessFlags()))) { @@ -280,7 +290,7 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs if (is_direct) { return resolved_method; } else if (type == kInterface) { - AbstractMethod* interface_method = + mirror::AbstractMethod* interface_method = this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); if (UNLIKELY(interface_method == NULL)) { ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, @@ -290,10 +300,10 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs return interface_method; } } else { - ObjectArray<AbstractMethod>* vtable; + mirror::ObjectArray<mirror::AbstractMethod>* vtable; uint16_t vtable_index = resolved_method->GetMethodIndex(); if (type == kSuper) { - Class* super_class = referring_class->GetSuperClass(); + mirror::Class* super_class = referring_class->GetSuperClass(); if (LIKELY(super_class != NULL)) { vtable = referring_class->GetSuperClass()->GetVTable(); } else { @@ -317,16 +327,16 @@ AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, Abs } } -Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self, - bool can_run_clinit, bool verify_access) { +mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, const mirror::AbstractMethod* referrer, + Thread* self, bool can_run_clinit, bool verify_access) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* klass = class_linker->ResolveType(type_idx, referrer); + mirror::Class* klass = class_linker->ResolveType(type_idx, referrer); if (UNLIKELY(klass == NULL)) { CHECK(self->IsExceptionPending()); return NULL; // Failure - Indicate to caller to deliver exception } // Perform access check if necessary. - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referring_class, klass); return NULL; // Failure - Indicate to caller to deliver exception @@ -396,12 +406,12 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char } else { JValue jv; jv.SetJ(args.at(i).j); - Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); + mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); if (val == NULL) { CHECK(soa.Self()->IsExceptionPending()); return zero; } - soa.Decode<ObjectArray<Object>* >(args_jobj)->Set(i, val); + soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set(i, val); } } } @@ -425,9 +435,9 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char return zero; } else { JValue result_unboxed; - MethodHelper mh(soa.Decode<AbstractMethod*>(interface_method_jobj)); - Class* result_type = mh.GetReturnType(); - Object* result_ref = soa.Decode<Object*>(result); + MethodHelper mh(soa.Decode<mirror::AbstractMethod*>(interface_method_jobj)); + mirror::Class* result_type = mh.GetReturnType(); + mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); bool unboxed_okay = UnboxPrimitiveForResult(result_ref, result_type, result_unboxed); if (!unboxed_okay) { soa.Self()->ThrowNewWrappedException("Ljava/lang/ClassCastException;", @@ -441,12 +451,14 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char } else { // In the case of checked exceptions that aren't declared, the exception must be wrapped by // a UndeclaredThrowableException. - Throwable* exception = soa.Self()->GetException(); + mirror::Throwable* exception = soa.Self()->GetException(); if (exception->IsCheckedException()) { - Object* rcvr = soa.Decode<Object*>(rcvr_jobj); - SynthesizedProxyClass* proxy_class = down_cast<SynthesizedProxyClass*>(rcvr->GetClass()); - AbstractMethod* interface_method = soa.Decode<AbstractMethod*>(interface_method_jobj); - AbstractMethod* proxy_method = + mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); + mirror::SynthesizedProxyClass* proxy_class = + down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass()); + mirror::AbstractMethod* interface_method = + soa.Decode<mirror::AbstractMethod*>(interface_method_jobj); + mirror::AbstractMethod* proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); int throws_index = -1; size_t num_virt_methods = proxy_class->NumVirtualMethods(); @@ -457,11 +469,11 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char } } CHECK_NE(throws_index, -1); - ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); - Class* exception_class = exception->GetClass(); + mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); + mirror::Class* exception_class = exception->GetClass(); bool declares_exception = false; for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { - Class* declared_exception = declared_exceptions->Get(i); + mirror::Class* declared_exception = declared_exceptions->Get(i); declares_exception = declared_exception->IsAssignableFrom(exception_class); } if (!declares_exception) { diff --git a/src/runtime_support.h b/src/runtime_support.h index 1c8d1740b1..a504237044 100644 --- a/src/runtime_support.h +++ b/src/runtime_support.h @@ -23,10 +23,11 @@ #include "indirect_reference_table.h" #include "invoke_type.h" #include "jni_internal.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "mirror/array.h" +#include "mirror/throwable.h" #include "object_utils.h" #include "thread.h" -#include "verifier/method_verifier.h" extern "C" void art_interpreter_invoke_handler(); extern "C" void art_proxy_invoke_handler(); @@ -40,21 +41,21 @@ extern "C" int64_t art_f2l(float f); extern "C" int32_t art_f2i(float f); namespace art { - -class Array; +namespace mirror { class Class; class Field; -class AbstractMethod; class Object; +} // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it // cannot be resolved, throw an error. If it can, use it to create an instance. // When verification/compiler hasn't been able to verify access, optionally perform an access // check. -static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* method, Thread* self, - bool access_check) +static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + Thread* self, + bool access_check) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); + mirror::Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); Runtime* runtime = Runtime::Current(); if (UNLIKELY(klass == NULL)) { klass = runtime->GetClassLinker()->ResolveType(type_idx, method); @@ -69,7 +70,7 @@ static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* met PrettyDescriptor(klass).c_str()); return NULL; // Failure } - Class* referrer = method->GetDeclaringClass(); + mirror::Class* referrer = method->GetDeclaringClass(); if (UNLIKELY(!referrer->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referrer, klass); return NULL; // Failure @@ -87,14 +88,15 @@ static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* met // it cannot be resolved, throw an error. If it can, use it to create an array. // When verification/compiler hasn't been able to verify access, optionally perform an access // check. -static inline Array* AllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, - Thread* self, bool access_check) +static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + int32_t component_count, + Thread* self, bool access_check) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (UNLIKELY(component_count < 0)) { self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); return NULL; // Failure } - Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); + mirror::Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); if (klass == NULL) { // Error @@ -104,17 +106,18 @@ static inline Array* AllocArrayFromCode(uint32_t type_idx, AbstractMethod* metho CHECK(klass->IsArrayClass()) << PrettyClass(klass); } if (access_check) { - Class* referrer = method->GetDeclaringClass(); + mirror::Class* referrer = method->GetDeclaringClass(); if (UNLIKELY(!referrer->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referrer, klass); return NULL; // Failure } } - return Array::Alloc(self, klass, component_count); + return mirror::Array::Alloc(self, klass, component_count); } -extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, - Thread* self, bool access_check) +extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method, + int32_t component_count, + Thread* self, bool access_check) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Type of find field operation for fast and slow case. @@ -130,19 +133,21 @@ enum FindFieldType { }; // Slow field find that can initialize classes and may throw exceptions. -extern Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self, - FindFieldType type, size_t expected_size) +extern mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer, + Thread* self, FindFieldType type, size_t expected_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Fast path field resolution that can't initialize classes or throw exceptions. -static inline Field* FindFieldFast(uint32_t field_idx, const AbstractMethod* referrer, - FindFieldType type, size_t expected_size) +static inline mirror::Field* FindFieldFast(uint32_t field_idx, + const mirror::AbstractMethod* referrer, + FindFieldType type, size_t expected_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); + mirror::Field* resolved_field = + referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); if (UNLIKELY(resolved_field == NULL)) { return NULL; } - Class* fields_class = resolved_field->GetDeclaringClass(); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); // Check class is initiliazed or initializing. if (UNLIKELY(!fields_class->IsInitializing())) { return NULL; @@ -167,7 +172,7 @@ static inline Field* FindFieldFast(uint32_t field_idx, const AbstractMethod* ref // Incompatible class change. return NULL; } - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(fields_class) || !referring_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) || @@ -184,14 +189,16 @@ static inline Field* FindFieldFast(uint32_t field_idx, const AbstractMethod* ref } // Fast path method resolution that can't throw exceptions. -static inline AbstractMethod* FindMethodFast(uint32_t method_idx, Object* this_object, - const AbstractMethod* referrer, bool access_check, InvokeType type) +static inline mirror::AbstractMethod* FindMethodFast(uint32_t method_idx, + mirror::Object* this_object, + const mirror::AbstractMethod* referrer, + bool access_check, InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { bool is_direct = type == kStatic || type == kDirect; if (UNLIKELY(this_object == NULL && !is_direct)) { return NULL; } - AbstractMethod* resolved_method = + mirror::AbstractMethod* resolved_method = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx); if (UNLIKELY(resolved_method == NULL)) { return NULL; @@ -202,8 +209,8 @@ static inline AbstractMethod* FindMethodFast(uint32_t method_idx, Object* this_o if (UNLIKELY(icce)) { return NULL; } - Class* methods_class = resolved_method->GetDeclaringClass(); - Class* referring_class = referrer->GetDeclaringClass(); + mirror::Class* methods_class = resolved_method->GetDeclaringClass(); + mirror::Class* referring_class = referrer->GetDeclaringClass(); if (UNLIKELY(!referring_class->CanAccess(methods_class) || !referring_class->CanAccessMember(methods_class, resolved_method->GetAccessFlags()))) { @@ -224,17 +231,20 @@ static inline AbstractMethod* FindMethodFast(uint32_t method_idx, Object* this_o } } -extern AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer, - Thread* self, bool access_check, InvokeType type) +extern mirror::AbstractMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object, + mirror::AbstractMethod* referrer, + Thread* self, bool access_check, InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self, - bool can_run_clinit, bool verify_access) +extern mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, + const mirror::AbstractMethod* referrer, Thread* self, + bool can_run_clinit, bool verify_access) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -static inline String* ResolveStringFromCode(const AbstractMethod* referrer, uint32_t string_idx) +static inline mirror::String* ResolveStringFromCode(const mirror::AbstractMethod* referrer, + uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); return class_linker->ResolveString(string_idx, referrer); @@ -244,7 +254,7 @@ static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) UNLOCK_FUNCTION(monitor_lock_) { // Save any pending exception over monitor exit call. - Throwable* saved_exception = NULL; + mirror::Throwable* saved_exception = NULL; if (UNLIKELY(self->IsExceptionPending())) { saved_exception = self->GetException(); self->ClearException(); @@ -263,7 +273,7 @@ static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) } } -static inline void CheckReferenceResult(Object* o, Thread* self) +static inline void CheckReferenceResult(mirror::Object* o, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (o == NULL) { return; @@ -273,9 +283,9 @@ static inline void CheckReferenceResult(Object* o, Thread* self) PrettyMethod(self->GetCurrentMethod()).c_str()); } // Make sure that the result is an instance of the type this method was expected to return. - AbstractMethod* m = self->GetCurrentMethod(); + mirror::AbstractMethod* m = self->GetCurrentMethod(); MethodHelper mh(m); - Class* return_type = mh.GetReturnType(); + mirror::Class* return_type = mh.GetReturnType(); if (!o->InstanceOf(return_type)) { JniAbortF(NULL, "attempt to return an instance of %s from %s", diff --git a/src/scoped_thread_state_change.h b/src/scoped_thread_state_change.h index 5eabbdf09f..80d47c5528 100644 --- a/src/scoped_thread_state_change.h +++ b/src/scoped_thread_state_change.h @@ -165,7 +165,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { * passed in), or NULL on failure. */ template<typename T> - T AddLocalReference(Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + T AddLocalReference(mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_EQ(thread_state_, kRunnable); // Don't work with raw objects in non-runnable states. if (obj == NULL) { return NULL; @@ -208,7 +208,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { return down_cast<T>(Self()->DecodeJObject(obj)); } - Field* DecodeField(jfieldID fid) const + mirror::Field* DecodeField(jfieldID fid) const LOCKS_EXCLUDED(JavaVMExt::globals_lock, JavaVMExt::weak_globals_lock) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -218,10 +218,10 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { // TODO: we should make these unique weak globals if Field instances can ever move. UNIMPLEMENTED(WARNING); #endif - return reinterpret_cast<Field*>(fid); + return reinterpret_cast<mirror::Field*>(fid); } - jfieldID EncodeField(Field* field) const + jfieldID EncodeField(mirror::Field* field) const LOCKS_EXCLUDED(JavaVMExt::globals_lock, JavaVMExt::weak_globals_lock) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -233,7 +233,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { return reinterpret_cast<jfieldID>(field); } - AbstractMethod* DecodeMethod(jmethodID mid) const + mirror::AbstractMethod* DecodeMethod(jmethodID mid) const LOCKS_EXCLUDED(JavaVMExt::globals_lock, JavaVMExt::weak_globals_lock) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -243,10 +243,10 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { // TODO: we should make these unique weak globals if Method instances can ever move. UNIMPLEMENTED(WARNING); #endif - return reinterpret_cast<AbstractMethod*>(mid); + return reinterpret_cast<mirror::AbstractMethod*>(mid); } - jmethodID EncodeMethod(AbstractMethod* method) const + jmethodID EncodeMethod(mirror::AbstractMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Locks::mutator_lock_->AssertSharedHeld(Self()); DCHECK_EQ(thread_state_, kRunnable); // Don't work with raw objects in non-runnable states. diff --git a/src/stack.cc b/src/stack.cc index 2e1f4ae311..c998f2a4dd 100644 --- a/src/stack.cc +++ b/src/stack.cc @@ -18,7 +18,10 @@ #include "compiler.h" #include "oat/runtime/context.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "thread_list.h" @@ -39,7 +42,7 @@ size_t ManagedStack::NumJniShadowFrameReferences() const { return count; } -bool ManagedStack::ShadowFramesContain(Object** shadow_frame_entry) const { +bool ManagedStack::ShadowFramesContain(mirror::Object** shadow_frame_entry) const { for (const ManagedStack* current_fragment = this; current_fragment != NULL; current_fragment = current_fragment->GetLink()) { for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL; @@ -74,7 +77,7 @@ size_t StackVisitor::GetNativePcOffset() const { return GetMethod()->NativePcOffset(cur_quick_frame_pc_); } -uint32_t StackVisitor::GetVReg(AbstractMethod* m, uint16_t vreg, VRegKind kind) const { +uint32_t StackVisitor::GetVReg(mirror::AbstractMethod* m, uint16_t vreg, VRegKind kind) const { if (cur_quick_frame_ != NULL) { DCHECK(context_ != NULL); // You can't reliably read registers without a context. DCHECK(m == GetMethod()); @@ -98,7 +101,8 @@ uint32_t StackVisitor::GetVReg(AbstractMethod* m, uint16_t vreg, VRegKind kind) } } -void StackVisitor::SetVReg(AbstractMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) { +void StackVisitor::SetVReg(mirror::AbstractMethod* m, uint16_t vreg, uint32_t new_value, + VRegKind kind) { if (cur_quick_frame_ != NULL) { DCHECK(context_ != NULL); // You can't reliably write registers without a context. DCHECK(m == GetMethod()); @@ -136,14 +140,14 @@ void StackVisitor::SetGPR(uint32_t reg, uintptr_t value) { } uintptr_t StackVisitor::GetReturnPc() const { - AbstractMethod** sp = GetCurrentQuickFrame(); + mirror::AbstractMethod** sp = GetCurrentQuickFrame(); DCHECK(sp != NULL); byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes(); return *reinterpret_cast<uintptr_t*>(pc_addr); } void StackVisitor::SetReturnPc(uintptr_t new_ret_pc) { - AbstractMethod** sp = GetCurrentQuickFrame(); + mirror::AbstractMethod** sp = GetCurrentQuickFrame(); CHECK(sp != NULL); byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes(); *reinterpret_cast<uintptr_t*>(pc_addr) = new_ret_pc; @@ -182,7 +186,7 @@ void StackVisitor::DescribeStack(Thread* thread) { std::string StackVisitor::DescribeLocation() const { std::string result("Visiting method '"); - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m == NULL) { return "upcall"; } @@ -200,9 +204,9 @@ InstrumentationStackFrame StackVisitor::GetInstrumentationStackFrame(uint32_t de void StackVisitor::SanityCheckFrame() const { #ifndef NDEBUG - AbstractMethod* method = GetMethod(); - CHECK(method->GetClass() == AbstractMethod::GetMethodClass() || - method->GetClass() == AbstractMethod::GetConstructorClass()); + mirror::AbstractMethod* method = GetMethod(); + CHECK(method->GetClass() == mirror::AbstractMethod::GetMethodClass() || + method->GetClass() == mirror::AbstractMethod::GetConstructorClass()); if (cur_quick_frame_ != NULL) { method->AssertPcIsWithinCode(cur_quick_frame_pc_); // Frame sanity. @@ -229,7 +233,7 @@ void StackVisitor::WalkStack(bool include_transitions) { if (cur_quick_frame_ != NULL) { // Handle quick stack frames. // Can't be both a shadow and a quick fragment. DCHECK(current_fragment->GetTopShadowFrame() == NULL); - AbstractMethod* method = *cur_quick_frame_; + mirror::AbstractMethod* method = *cur_quick_frame_; while (method != NULL) { SanityCheckFrame(); bool should_continue = VisitFrame(); @@ -259,7 +263,7 @@ void StackVisitor::WalkStack(bool include_transitions) { } cur_quick_frame_pc_ = return_pc; byte* next_frame = reinterpret_cast<byte*>(cur_quick_frame_) + frame_size; - cur_quick_frame_ = reinterpret_cast<AbstractMethod**>(next_frame); + cur_quick_frame_ = reinterpret_cast<mirror::AbstractMethod**>(next_frame); cur_depth_++; method = *cur_quick_frame_; } diff --git a/src/stack.h b/src/stack.h index 8d0efe9e33..c3d20f5ef6 100644 --- a/src/stack.h +++ b/src/stack.h @@ -17,11 +17,9 @@ #ifndef ART_SRC_STACK_H_ #define ART_SRC_STACK_H_ -#include "base/macros.h" #include "dex_file.h" -#include "heap.h" #include "instrumentation.h" -#include "jni.h" +#include "base/macros.h" #include "oat/runtime/context.h" #include <stdint.h> @@ -29,9 +27,12 @@ namespace art { +namespace mirror { class AbstractMethod; -class Context; class Object; +} // namespace mirror + +class Context; class ShadowFrame; class StackIndirectReferenceTable; class ScopedObjectAccess; @@ -59,10 +60,10 @@ class ShadowFrame { public: // Create ShadowFrame for interpreter. static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link, - AbstractMethod* method, uint32_t dex_pc) { + mirror::AbstractMethod* method, uint32_t dex_pc) { size_t sz = sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) + - (sizeof(Object*) * num_vregs); + (sizeof(mirror::Object*) * num_vregs); uint8_t* memory = new uint8_t[sz]; ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true); return sf; @@ -121,13 +122,13 @@ class ShadowFrame { return *reinterpret_cast<const double*>(vreg); } - Object* GetVRegReference(size_t i) const { + mirror::Object* GetVRegReference(size_t i) const { DCHECK_LT(i, NumberOfVRegs()); if (HasReferenceArray()) { return References()[i]; } else { const uint32_t* vreg = &vregs_[i]; - return *reinterpret_cast<Object* const*>(vreg); + return *reinterpret_cast<mirror::Object* const*>(vreg); } } @@ -153,26 +154,26 @@ class ShadowFrame { *reinterpret_cast<double*>(vreg) = val; } - void SetVRegReference(size_t i, Object* val) { + void SetVRegReference(size_t i, mirror::Object* val) { DCHECK_LT(i, NumberOfVRegs()); uint32_t* vreg = &vregs_[i]; - *reinterpret_cast<Object**>(vreg) = val; + *reinterpret_cast<mirror::Object**>(vreg) = val; if (HasReferenceArray()) { References()[i] = val; } } - AbstractMethod* GetMethod() const { + mirror::AbstractMethod* GetMethod() const { DCHECK_NE(method_, static_cast<void*>(NULL)); return method_; } - void SetMethod(AbstractMethod* method) { + void SetMethod(mirror::AbstractMethod* method) { DCHECK_NE(method, static_cast<void*>(NULL)); method_ = method; } - bool Contains(Object** shadow_frame_entry_obj) const { + bool Contains(mirror::Object** shadow_frame_entry_obj) const { if (HasReferenceArray()) { return ((&References()[0] <= shadow_frame_entry_obj) && (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1]))); @@ -204,8 +205,8 @@ class ShadowFrame { } private: - ShadowFrame(uint32_t num_vregs, ShadowFrame* link, AbstractMethod* method, uint32_t dex_pc, - bool has_reference_array) + ShadowFrame(uint32_t num_vregs, ShadowFrame* link, mirror::AbstractMethod* method, + uint32_t dex_pc, bool has_reference_array) : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) { CHECK_LT(num_vregs, static_cast<uint32_t>(kHasReferenceArray)); if (has_reference_array) { @@ -220,14 +221,14 @@ class ShadowFrame { } } - Object* const* References() const { + mirror::Object* const* References() const { DCHECK(HasReferenceArray()); const uint32_t* vreg_end = &vregs_[NumberOfVRegs()]; - return reinterpret_cast<Object* const*>(vreg_end); + return reinterpret_cast<mirror::Object* const*>(vreg_end); } - Object** References() { - return const_cast<Object**>(const_cast<const ShadowFrame*>(this)->References()); + mirror::Object** References() { + return const_cast<mirror::Object**>(const_cast<const ShadowFrame*>(this)->References()); } enum ShadowFrameFlag { @@ -237,7 +238,7 @@ class ShadowFrame { uint32_t number_of_vregs_; // Link to previous shadow frame or NULL. ShadowFrame* link_; - AbstractMethod* method_; + mirror::AbstractMethod* method_; uint32_t dex_pc_; uint32_t vregs_[0]; @@ -272,11 +273,11 @@ class PACKED(4) ManagedStack { return link_; } - AbstractMethod** GetTopQuickFrame() const { + mirror::AbstractMethod** GetTopQuickFrame() const { return top_quick_frame_; } - void SetTopQuickFrame(AbstractMethod** top) { + void SetTopQuickFrame(mirror::AbstractMethod** top) { top_quick_frame_ = top; } @@ -320,12 +321,12 @@ class PACKED(4) ManagedStack { size_t NumJniShadowFrameReferences() const; - bool ShadowFramesContain(Object** shadow_frame_entry) const; + bool ShadowFramesContain(mirror::Object** shadow_frame_entry) const; private: ManagedStack* link_; ShadowFrame* top_shadow_frame_; - AbstractMethod** top_quick_frame_; + mirror::AbstractMethod** top_quick_frame_; uintptr_t top_quick_frame_pc_; }; @@ -342,7 +343,7 @@ class StackVisitor { void WalkStack(bool include_transitions = false) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* GetMethod() const { + mirror::AbstractMethod* GetMethod() const { if (cur_shadow_frame_ != NULL) { return cur_shadow_frame_->GetMethod(); } else if (cur_quick_frame_ != NULL) { @@ -388,16 +389,16 @@ class StackVisitor { return num_frames_; } - uint32_t GetVReg(AbstractMethod* m, uint16_t vreg, VRegKind kind) const + uint32_t GetVReg(mirror::AbstractMethod* m, uint16_t vreg, VRegKind kind) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetVReg(AbstractMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) + void SetVReg(mirror::AbstractMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); uintptr_t GetGPR(uint32_t reg) const; void SetGPR(uint32_t reg, uintptr_t value); - uint32_t GetVReg(AbstractMethod** cur_quick_frame, const DexFile::CodeItem* code_item, + uint32_t GetVReg(mirror::AbstractMethod** cur_quick_frame, const DexFile::CodeItem* code_item, uint32_t core_spills, uint32_t fp_spills, size_t frame_size, uint16_t vreg) const { int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg); @@ -471,7 +472,7 @@ class StackVisitor { return cur_quick_frame_pc_; } - AbstractMethod** GetCurrentQuickFrame() const { + mirror::AbstractMethod** GetCurrentQuickFrame() const { return cur_quick_frame_; } @@ -480,7 +481,7 @@ class StackVisitor { } StackIndirectReferenceTable* GetCurrentSirt() const { - AbstractMethod** sp = GetCurrentQuickFrame(); + mirror::AbstractMethod** sp = GetCurrentQuickFrame(); ++sp; // Skip Method*; SIRT comes next; return reinterpret_cast<StackIndirectReferenceTable*>(sp); } @@ -499,7 +500,7 @@ class StackVisitor { Thread* const thread_; ShadowFrame* cur_shadow_frame_; - AbstractMethod** cur_quick_frame_; + mirror::AbstractMethod** cur_quick_frame_; uintptr_t cur_quick_frame_pc_; // Lazily computed, number of frames in the stack. size_t num_frames_; diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h index 92fb00367f..dd106344de 100644 --- a/src/stack_indirect_reference_table.h +++ b/src/stack_indirect_reference_table.h @@ -21,8 +21,9 @@ #include "base/macros.h" namespace art { - +namespace mirror { class Object; +} class Thread; // Stack allocated indirect reference table. It can allocated within @@ -30,7 +31,8 @@ class Thread; // storage or manually allocated by SirtRef to hold one reference. class StackIndirectReferenceTable { public: - explicit StackIndirectReferenceTable(Object* object) : number_of_references_(1), link_(NULL) { + explicit StackIndirectReferenceTable(mirror::Object* object) : + number_of_references_(1), link_(NULL) { references_[0] = object; } @@ -51,17 +53,17 @@ class StackIndirectReferenceTable { link_ = sirt; } - Object* GetReference(size_t i) const { + mirror::Object* GetReference(size_t i) const { DCHECK_LT(i, number_of_references_); return references_[i]; } - void SetReference(size_t i, Object* object) { + void SetReference(size_t i, mirror::Object* object) { DCHECK_LT(i, number_of_references_); references_[i] = object; } - bool Contains(Object** sirt_entry) const { + bool Contains(mirror::Object** sirt_entry) const { // A SIRT should always contain something. One created by the // jni_compiler should have a jobject/jclass as a native method is // passed in a this pointer or a class @@ -87,7 +89,7 @@ class StackIndirectReferenceTable { StackIndirectReferenceTable* link_; // number_of_references_ are available if this is allocated and filled in by jni_compiler. - Object* references_[1]; + mirror::Object* references_[1]; DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable); }; diff --git a/src/thread.cc b/src/thread.cc index 46cba06dc3..01d6072f12 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -30,16 +30,22 @@ #include "base/mutex.h" #include "class_linker.h" -#include "class_loader.h" +#include "class_linker-inl.h" #include "cutils/atomic.h" #include "cutils/atomic-inline.h" #include "debugger.h" #include "gc_map.h" +#include "gc/card_table-inl.h" #include "heap.h" #include "jni_internal.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class-inl.h" +#include "mirror/class_loader.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/stack_trace_element.h" #include "monitor.h" #include "oat/runtime/context.h" -#include "object.h" #include "object_utils.h" #include "reflection.h" #include "runtime.h" @@ -139,20 +145,20 @@ void* Thread::CreateCallback(void* arg) { // Copy peer into self, deleting global reference when done. CHECK(self->jpeer_ != NULL); - self->opeer_ = soa.Decode<Object*>(self->jpeer_); + self->opeer_ = soa.Decode<mirror::Object*>(self->jpeer_); self->GetJniEnv()->DeleteGlobalRef(self->jpeer_); self->jpeer_ = NULL; { - SirtRef<String> thread_name(self, self->GetThreadName(soa)); + SirtRef<mirror::String> thread_name(self, self->GetThreadName(soa)); self->SetThreadName(thread_name->ToModifiedUtf8().c_str()); } Dbg::PostThreadStart(self); // Invoke the 'run' method of our java.lang.Thread. - Object* receiver = self->opeer_; + mirror::Object* receiver = self->opeer_; jmethodID mid = WellKnownClasses::java_lang_Thread_run; - AbstractMethod* m = + mirror::AbstractMethod* m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid)); m->Invoke(self, receiver, NULL, NULL); } @@ -162,8 +168,9 @@ void* Thread::CreateCallback(void* arg) { return NULL; } -Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa, Object* thread_peer) { - Field* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_vmData); +Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa, + mirror::Object* thread_peer) { + mirror::Field* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_vmData); Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetInt(thread_peer))); // Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_ // to stop it from going away. @@ -177,7 +184,7 @@ Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa, Object } Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa, jobject java_thread) { - return FromManagedThread(soa, soa.Decode<Object*>(java_thread)); + return FromManagedThread(soa, soa.Decode<mirror::Object*>(java_thread)); } static size_t FixStackSize(size_t stack_size) { @@ -391,7 +398,7 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group) } { ScopedObjectAccess soa(this); - opeer_ = soa.Decode<Object*>(peer.get()); + opeer_ = soa.Decode<mirror::Object*>(peer.get()); } env->CallNonvirtualVoidMethod(peer.get(), WellKnownClasses::java_lang_Thread, @@ -405,7 +412,7 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group) reinterpret_cast<jint>(self)); ScopedObjectAccess soa(self); - SirtRef<String> peer_thread_name(soa.Self(), GetThreadName(soa)); + SirtRef<mirror::String> peer_thread_name(soa.Self(), GetThreadName(soa)); if (peer_thread_name.get() == NULL) { // The Thread constructor should have set the Thread.name to a // non-null value. However, because we can run without code @@ -414,9 +421,9 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group) soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon)-> SetBoolean(opeer_, thread_is_daemon); soa.DecodeField(WellKnownClasses::java_lang_Thread_group)-> - SetObject(opeer_, soa.Decode<Object*>(thread_group)); + SetObject(opeer_, soa.Decode<mirror::Object*>(thread_group)); soa.DecodeField(WellKnownClasses::java_lang_Thread_name)-> - SetObject(opeer_, soa.Decode<Object*>(thread_name.get())); + SetObject(opeer_, soa.Decode<mirror::Object*>(thread_name.get())); soa.DecodeField(WellKnownClasses::java_lang_Thread_priority)-> SetInt(opeer_, thread_priority); peer_thread_name.reset(GetThreadName(soa)); @@ -506,9 +513,9 @@ void Thread::Dump(std::ostream& os) const { DumpStack(os); } -String* Thread::GetThreadName(const ScopedObjectAccessUnchecked& soa) const { - Field* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - return (opeer_ != NULL) ? reinterpret_cast<String*>(f->GetObject(opeer_)) : NULL; +mirror::String* Thread::GetThreadName(const ScopedObjectAccessUnchecked& soa) const { + mirror::Field* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); + return (opeer_ != NULL) ? reinterpret_cast<mirror::String*>(f->GetObject(opeer_)) : NULL; } void Thread::GetThreadName(std::string& name) const { @@ -748,12 +755,14 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) { priority = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority)->GetInt(thread->opeer_); is_daemon = soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon)->GetBoolean(thread->opeer_); - Object* thread_group = + mirror::Object* thread_group = soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(thread->opeer_); if (thread_group != NULL) { - Field* group_name_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); - String* group_name_string = reinterpret_cast<String*>(group_name_field->GetObject(thread_group)); + mirror::Field* group_name_field = + soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); + mirror::String* group_name_string = + reinterpret_cast<mirror::String*>(group_name_field->GetObject(thread_group)); group_name = (group_name_string != NULL) ? group_name_string->ToModifiedUtf8() : "<null>"; } } else { @@ -848,13 +857,13 @@ struct StackDumpVisitor : public StackVisitor { } bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m->IsRuntimeMethod()) { return true; } const int kMaxRepetition = 3; - Class* c = m->GetDeclaringClass(); - const DexCache* dex_cache = c->GetDexCache(); + mirror::Class* c = m->GetDeclaringClass(); + const mirror::DexCache* dex_cache = c->GetDexCache(); int line_number = -1; if (dex_cache != NULL) { // be tolerant of bad input const DexFile& dex_file = *dex_cache->GetDexFile(); @@ -893,7 +902,7 @@ struct StackDumpVisitor : public StackVisitor { return true; } - static void DumpLockedObject(Object* o, void* context) + static void DumpLockedObject(mirror::Object* o, void* context) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::ostream& os = *reinterpret_cast<std::ostream*>(context); os << " - locked <" << o << "> (a " << PrettyTypeOf(o) << ")\n"; @@ -903,7 +912,7 @@ struct StackDumpVisitor : public StackVisitor { const Thread* thread; bool can_allocate; MethodHelper mh; - AbstractMethod* last_method; + mirror::AbstractMethod* last_method; int last_line_number; int repetition_count; int frame_count; @@ -1016,14 +1025,14 @@ bool Thread::IsStillStarting() const { void Thread::AssertNoPendingException() const { if (UNLIKELY(IsExceptionPending())) { ScopedObjectAccess soa(Thread::Current()); - Throwable* exception = GetException(); + mirror::Throwable* exception = GetException(); LOG(FATAL) << "No pending exception expected: " << exception->Dump(); } } -static void MonitorExitVisitor(const Object* object, void* arg) NO_THREAD_SAFETY_ANALYSIS { +static void MonitorExitVisitor(const mirror::Object* object, void* arg) NO_THREAD_SAFETY_ANALYSIS { Thread* self = reinterpret_cast<Thread*>(arg); - Object* entered_monitor = const_cast<Object*>(object); + mirror::Object* entered_monitor = const_cast<mirror::Object*>(object); if (self->HoldsLock(entered_monitor)) { LOG(WARNING) << "Calling MonitorExit on object " << object << " (" << PrettyTypeOf(object) << ")" @@ -1049,7 +1058,8 @@ void Thread::Destroy() { // Thread.join() is implemented as an Object.wait() on the Thread.lock object. Signal anyone // who is waiting. - Object* lock = soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(opeer_); + mirror::Object* lock = + soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(opeer_); // (This conditional is only needed for tests, where Thread.lock won't have been set.) if (lock != NULL) { lock->MonitorEnter(self); @@ -1125,7 +1135,7 @@ void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) { void Thread::RemoveFromThreadGroup(ScopedObjectAccess& soa) { // this.group.removeThread(this); // group can be null if we're in the compiler or a test. - Object* ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(opeer_); + mirror::Object* ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(opeer_); if (ogroup != NULL) { ScopedLocalRef<jobject> group(soa.Env(), soa.AddLocalReference<jobject>(ogroup)); ScopedLocalRef<jobject> peer(soa.Env(), soa.AddLocalReference<jobject>(opeer_)); @@ -1144,7 +1154,7 @@ size_t Thread::NumSirtReferences() { } bool Thread::SirtContains(jobject obj) const { - Object** sirt_entry = reinterpret_cast<Object**>(obj); + mirror::Object** sirt_entry = reinterpret_cast<mirror::Object**>(obj); for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) { if (cur->Contains(sirt_entry)) { return true; @@ -1154,11 +1164,11 @@ bool Thread::SirtContains(jobject obj) const { return managed_stack_.ShadowFramesContain(sirt_entry); } -void Thread::SirtVisitRoots(Heap::RootVisitor* visitor, void* arg) { +void Thread::SirtVisitRoots(RootVisitor* visitor, void* arg) { for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) { size_t num_refs = cur->NumberOfReferences(); for (size_t j = 0; j < num_refs; j++) { - Object* object = cur->GetReference(j); + mirror::Object* object = cur->GetReference(j); if (object != NULL) { visitor(object, arg); } @@ -1166,19 +1176,19 @@ void Thread::SirtVisitRoots(Heap::RootVisitor* visitor, void* arg) { } } -Object* Thread::DecodeJObject(jobject obj) const { +mirror::Object* Thread::DecodeJObject(jobject obj) const { Locks::mutator_lock_->AssertSharedHeld(this); if (obj == NULL) { return NULL; } IndirectRef ref = reinterpret_cast<IndirectRef>(obj); IndirectRefKind kind = GetIndirectRefKind(ref); - Object* result; + mirror::Object* result; switch (kind) { case kLocal: { IndirectReferenceTable& locals = jni_env_->locals; - result = const_cast<Object*>(locals.Get(ref)); + result = const_cast<mirror::Object*>(locals.Get(ref)); break; } case kGlobal: @@ -1186,7 +1196,7 @@ Object* Thread::DecodeJObject(jobject obj) const { JavaVMExt* vm = Runtime::Current()->GetJavaVM(); IndirectReferenceTable& globals = vm->globals; MutexLock mu(const_cast<Thread*>(this), vm->globals_lock); - result = const_cast<Object*>(globals.Get(ref)); + result = const_cast<mirror::Object*>(globals.Get(ref)); break; } case kWeakGlobal: @@ -1194,7 +1204,7 @@ Object* Thread::DecodeJObject(jobject obj) const { JavaVMExt* vm = Runtime::Current()->GetJavaVM(); IndirectReferenceTable& weak_globals = vm->weak_globals; MutexLock mu(const_cast<Thread*>(this), vm->weak_globals_lock); - result = const_cast<Object*>(weak_globals.Get(ref)); + result = const_cast<mirror::Object*>(weak_globals.Get(ref)); if (result == kClearedJniWeakGlobal) { // This is a special case where it's okay to return NULL. return NULL; @@ -1206,10 +1216,10 @@ Object* Thread::DecodeJObject(jobject obj) const { // TODO: make stack indirect reference table lookup more efficient // Check if this is a local reference in the SIRT if (SirtContains(obj)) { - result = *reinterpret_cast<Object**>(obj); // Read from SIRT + result = *reinterpret_cast<mirror::Object**>(obj); // Read from SIRT } else if (Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs) { // Assume an invalid local reference is actually a direct pointer. - result = reinterpret_cast<Object*>(obj); + result = reinterpret_cast<mirror::Object*>(obj); } else { result = kInvalidIndirectRefObject; } @@ -1272,9 +1282,9 @@ class CountStackDepthVisitor : public StackVisitor { // We want to skip frames up to and including the exception's constructor. // Note we also skip the frame if it doesn't have a method (namely the callee // save frame) - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (skipping_ && !m->IsRuntimeMethod() && - !Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) { + !mirror::Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) { skipping_ = false; } if (!skipping_) { @@ -1310,14 +1320,14 @@ class BuildInternalStackTraceVisitor : public StackVisitor { bool Init(int depth) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Allocate method trace with an extra slot that will hold the PC trace - SirtRef<ObjectArray<Object> > + SirtRef<mirror::ObjectArray<mirror::Object> > method_trace(self_, - Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self_, - depth + 1)); + Runtime::Current()->GetClassLinker()->AllocObjectArray<mirror::Object>(self_, + depth + 1)); if (method_trace.get() == NULL) { return false; } - IntArray* dex_pc_trace = IntArray::Alloc(self_, depth); + mirror::IntArray* dex_pc_trace = mirror::IntArray::Alloc(self_, depth); if (dex_pc_trace == NULL) { return false; } @@ -1347,7 +1357,7 @@ class BuildInternalStackTraceVisitor : public StackVisitor { skip_depth_--; return true; } - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m->IsRuntimeMethod()) { return true; // Ignore runtime frames (in particular callee save). } @@ -1357,7 +1367,7 @@ class BuildInternalStackTraceVisitor : public StackVisitor { return true; } - ObjectArray<Object>* GetInternalStackTrace() const { + mirror::ObjectArray<mirror::Object>* GetInternalStackTrace() const { return method_trace_; } @@ -1368,9 +1378,9 @@ class BuildInternalStackTraceVisitor : public StackVisitor { // Current position down stack trace. uint32_t count_; // Array of dex PC values. - IntArray* dex_pc_trace_; + mirror::IntArray* dex_pc_trace_; // An array of the methods on the stack, the last entry is a reference to the PC trace. - ObjectArray<Object>* method_trace_; + mirror::ObjectArray<mirror::Object>* method_trace_; }; jobject Thread::CreateInternalStackTrace(const ScopedObjectAccessUnchecked& soa) const { @@ -1387,7 +1397,7 @@ jobject Thread::CreateInternalStackTrace(const ScopedObjectAccessUnchecked& soa) return NULL; // Allocation failed. } build_trace_visitor.WalkStack(); - ObjectArray<Object>* trace = build_trace_visitor.GetInternalStackTrace(); + mirror::ObjectArray<mirror::Object>* trace = build_trace_visitor.GetInternalStackTrace(); if (kIsDebugBuild) { for (int32_t i = 0; i < trace->GetLength(); ++i) { CHECK(trace->Get(i) != NULL); @@ -1401,18 +1411,19 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job // Transition into runnable state to work on Object*/Array* ScopedObjectAccess soa(env); // Decode the internal stack trace into the depth, method trace and PC trace - ObjectArray<Object>* method_trace = soa.Decode<ObjectArray<Object>*>(internal); + mirror::ObjectArray<mirror::Object>* method_trace = + soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal); int32_t depth = method_trace->GetLength() - 1; - IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); + mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth)); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); jobjectArray result; - ObjectArray<StackTraceElement>* java_traces; + mirror::ObjectArray<mirror::StackTraceElement>* java_traces; if (output_array != NULL) { // Reuse the array we were given. result = output_array; - java_traces = soa.Decode<ObjectArray<StackTraceElement>*>(output_array); + java_traces = soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(output_array); // ...adjusting the number of frames we'll write to not exceed the array length. depth = std::min(depth, java_traces->GetLength()); } else { @@ -1431,7 +1442,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job MethodHelper mh; for (int32_t i = 0; i < depth; ++i) { // Prepare parameters for StackTraceElement(String cls, String method, String file, int line) - AbstractMethod* method = down_cast<AbstractMethod*>(method_trace->Get(i)); + mirror::AbstractMethod* method = down_cast<mirror::AbstractMethod*>(method_trace->Get(i)); mh.ChangeMethod(method); uint32_t dex_pc = pc_trace->Get(i); int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); @@ -1440,27 +1451,28 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job const char* descriptor = mh.GetDeclaringClassDescriptor(); CHECK(descriptor != NULL); std::string class_name(PrettyDescriptor(descriptor)); - SirtRef<String> class_name_object(soa.Self(), - String::AllocFromModifiedUtf8(soa.Self(), - class_name.c_str())); + SirtRef<mirror::String> class_name_object(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), + class_name.c_str())); if (class_name_object.get() == NULL) { return NULL; } const char* method_name = mh.GetName(); CHECK(method_name != NULL); - SirtRef<String> method_name_object(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), - method_name)); + SirtRef<mirror::String> method_name_object(soa.Self(), + mirror::String::AllocFromModifiedUtf8(soa.Self(), + method_name)); if (method_name_object.get() == NULL) { return NULL; } const char* source_file = mh.GetDeclaringClassSourceFile(); - SirtRef<String> source_name_object(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), - source_file)); - StackTraceElement* obj = StackTraceElement::Alloc(soa.Self(), - class_name_object.get(), - method_name_object.get(), - source_name_object.get(), - line_number); + SirtRef<mirror::String> source_name_object(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), + source_file)); + mirror::StackTraceElement* obj = mirror::StackTraceElement::Alloc(soa.Self(), + class_name_object.get(), + method_name_object.get(), + source_name_object.get(), + line_number); if (obj == NULL) { return NULL; } @@ -1520,10 +1532,11 @@ void Thread::ThrowNewWrappedException(const char* exception_class_descriptor, co env, reinterpret_cast<jthrowable>(env->AllocObject(exception_class.get()))); if (exception.get() != NULL) { ScopedObjectAccessUnchecked soa(env); - Throwable* t = reinterpret_cast<Throwable*>(soa.Self()->DecodeJObject(exception.get())); - t->SetDetailMessage(String::AllocFromModifiedUtf8(soa.Self(), msg)); + mirror::Throwable* t = + reinterpret_cast<mirror::Throwable*>(soa.Self()->DecodeJObject(exception.get())); + t->SetDetailMessage(mirror::String::AllocFromModifiedUtf8(soa.Self(), msg)); if (cause != NULL) { - t->SetCause(soa.Decode<Throwable*>(cause)); + t->SetCause(soa.Decode<mirror::Throwable*>(cause)); } soa.Self()->SetException(t); } else { @@ -1691,7 +1704,7 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset, size_t size_of_ static const bool kDebugExceptionDelivery = false; class CatchBlockStackVisitor : public StackVisitor { public: - CatchBlockStackVisitor(Thread* self, Throwable* exception) + CatchBlockStackVisitor(Thread* self, mirror::Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : StackVisitor(self, self->GetLongJumpContext()), self_(self), exception_(exception), to_find_(exception->GetClass()), throw_method_(NULL), @@ -1708,7 +1721,7 @@ class CatchBlockStackVisitor : public StackVisitor { bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* method = GetMethod(); + mirror::AbstractMethod* method = GetMethod(); if (method == NULL) { // This is the upcall, we remember the frame and last pc so that we may long jump to them. handler_quick_frame_pc_ = GetCurrentQuickFramePc(); @@ -1751,7 +1764,7 @@ class CatchBlockStackVisitor : public StackVisitor { } void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* catch_method = *handler_quick_frame_; + mirror::AbstractMethod* catch_method = *handler_quick_frame_; if (kDebugExceptionDelivery) { if (catch_method == NULL) { LOG(INFO) << "Handler is upcall"; @@ -1777,14 +1790,14 @@ class CatchBlockStackVisitor : public StackVisitor { private: Thread* self_; - Throwable* exception_; + mirror::Throwable* exception_; // The type of the exception catch block to find. - Class* to_find_; - AbstractMethod* throw_method_; + mirror::Class* to_find_; + mirror::AbstractMethod* throw_method_; JDWP::FrameId throw_frame_id_; uint32_t throw_dex_pc_; // Quick frame with found handler or last frame if no handler found. - AbstractMethod** handler_quick_frame_; + mirror::AbstractMethod** handler_quick_frame_; // PC to branch to for the handler. uintptr_t handler_quick_frame_pc_; // Associated dex PC. @@ -1798,13 +1811,13 @@ class CatchBlockStackVisitor : public StackVisitor { }; void Thread::QuickDeliverException() { - Throwable* exception = GetException(); // Get exception from thread + mirror::Throwable* exception = GetException(); // Get exception from thread CHECK(exception != NULL); // Don't leave exception visible while we try to find the handler, which may cause class // resolution. ClearException(); if (kDebugExceptionDelivery) { - String* msg = exception->GetDetailMessage(); + mirror::String* msg = exception->GetDetailMessage(); std::string str_msg(msg != NULL ? msg->ToModifiedUtf8() : ""); DumpStack(LOG(INFO) << "Delivering exception: " << PrettyTypeOf(exception) << ": " << str_msg << "\n"); @@ -1826,14 +1839,14 @@ Context* Thread::GetLongJumpContext() { return result; } -AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) const { +mirror::AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) const { struct CurrentMethodVisitor : public StackVisitor { CurrentMethodVisitor(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : StackVisitor(thread, NULL), method_(NULL), dex_pc_(0), frame_id_(0) {} virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (m->IsRuntimeMethod()) { // Continue if this is a runtime method. return true; @@ -1843,7 +1856,7 @@ AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) con frame_id_ = GetFrameId(); return false; } - AbstractMethod* method_; + mirror::AbstractMethod* method_; uint32_t dex_pc_; size_t frame_id_; }; @@ -1859,7 +1872,7 @@ AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) con return visitor.method_; } -bool Thread::HoldsLock(Object* object) { +bool Thread::HoldsLock(mirror::Object* object) { if (object == NULL) { return false; } @@ -1881,12 +1894,12 @@ class ReferenceMapVisitor : public StackVisitor { } ShadowFrame* shadow_frame = GetCurrentShadowFrame(); if (shadow_frame != NULL) { - AbstractMethod* m = shadow_frame->GetMethod(); + mirror::AbstractMethod* m = shadow_frame->GetMethod(); size_t num_regs = shadow_frame->NumberOfVRegs(); if (m->IsNative() || shadow_frame->HasReferenceArray()) { // SIRT for JNI or References for interpreter. for (size_t reg = 0; reg < num_regs; ++reg) { - Object* ref = shadow_frame->GetVRegReference(reg); + mirror::Object* ref = shadow_frame->GetVRegReference(reg); if (ref != NULL) { visitor_(ref, reg, this); } @@ -1907,7 +1920,7 @@ class ReferenceMapVisitor : public StackVisitor { num_regs = std::min(dex_gc_map.RegWidth() * 8, num_regs); for (size_t reg = 0; reg < num_regs; ++reg) { if (TestBitmap(reg, reg_bitmap)) { - Object* ref = shadow_frame->GetVRegReference(reg); + mirror::Object* ref = shadow_frame->GetVRegReference(reg); if (ref != NULL) { visitor_(ref, reg, this); } @@ -1915,7 +1928,7 @@ class ReferenceMapVisitor : public StackVisitor { } } } else { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); // Process register map (which native and runtime methods don't have) if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) { const uint8_t* native_gc_map = m->GetNativeGcMap(); @@ -1934,20 +1947,21 @@ class ReferenceMapVisitor : public StackVisitor { uint32_t fp_spills = m->GetFpSpillMask(); size_t frame_size = m->GetFrameSizeInBytes(); // For all dex registers in the bitmap - AbstractMethod** cur_quick_frame = GetCurrentQuickFrame(); + mirror::AbstractMethod** cur_quick_frame = GetCurrentQuickFrame(); DCHECK(cur_quick_frame != NULL); for (size_t reg = 0; reg < num_regs; ++reg) { // Does this register hold a reference? if (TestBitmap(reg, reg_bitmap)) { uint32_t vmap_offset; - Object* ref; + mirror::Object* ref; if (vmap_table.IsInContext(reg, vmap_offset, kReferenceVReg)) { uintptr_t val = GetGPR(vmap_table.ComputeRegister(core_spills, vmap_offset, kReferenceVReg)); - ref = reinterpret_cast<Object*>(val); + ref = reinterpret_cast<mirror::Object*>(val); } else { - ref = reinterpret_cast<Object*>(GetVReg(cur_quick_frame, code_item, core_spills, - fp_spills, frame_size, reg)); + ref = reinterpret_cast<mirror::Object*>(GetVReg(cur_quick_frame, code_item, + core_spills, fp_spills, frame_size, + reg)); } if (ref != NULL) { @@ -1975,46 +1989,46 @@ class ReferenceMapVisitor : public StackVisitor { class RootCallbackVisitor { public: - RootCallbackVisitor(Heap::RootVisitor* visitor, void* arg) : visitor_(visitor), arg_(arg) { + RootCallbackVisitor(RootVisitor* visitor, void* arg) : visitor_(visitor), arg_(arg) { } - void operator()(const Object* obj, size_t, const StackVisitor*) const { + void operator()(const mirror::Object* obj, size_t, const StackVisitor*) const { visitor_(obj, arg_); } private: - Heap::RootVisitor* visitor_; + RootVisitor* visitor_; void* arg_; }; class VerifyCallbackVisitor { public: - VerifyCallbackVisitor(Heap::VerifyRootVisitor* visitor, void* arg) + VerifyCallbackVisitor(VerifyRootVisitor* visitor, void* arg) : visitor_(visitor), arg_(arg) { } - void operator()(const Object* obj, size_t vreg, const StackVisitor* visitor) const { + void operator()(const mirror::Object* obj, size_t vreg, const StackVisitor* visitor) const { visitor_(obj, arg_, vreg, visitor); } private: - Heap::VerifyRootVisitor* const visitor_; + VerifyRootVisitor* const visitor_; void* const arg_; }; struct VerifyRootWrapperArg { - Heap::VerifyRootVisitor* visitor; + VerifyRootVisitor* visitor; void* arg; }; -static void VerifyRootWrapperCallback(const Object* root, void* arg) { +static void VerifyRootWrapperCallback(const mirror::Object* root, void* arg) { VerifyRootWrapperArg* wrapperArg = reinterpret_cast<VerifyRootWrapperArg*>(arg); wrapperArg->visitor(root, wrapperArg->arg, 0, NULL); } -void Thread::VerifyRoots(Heap::VerifyRootVisitor* visitor, void* arg) { +void Thread::VerifyRoots(VerifyRootVisitor* visitor, void* arg) { // We need to map from a RootVisitor to VerifyRootVisitor, so pass in nulls for arguments we // don't have. VerifyRootWrapperArg wrapperArg; @@ -2043,7 +2057,7 @@ void Thread::VerifyRoots(Heap::VerifyRootVisitor* visitor, void* arg) { ReleaseLongJumpContext(context); } -void Thread::VisitRoots(Heap::RootVisitor* visitor, void* arg) { +void Thread::VisitRoots(RootVisitor* visitor, void* arg) { if (opeer_ != NULL) { visitor(opeer_, arg); } diff --git a/src/thread.h b/src/thread.h index 13e1cab058..c63fddf3d1 100644 --- a/src/thread.h +++ b/src/thread.h @@ -31,19 +31,30 @@ #include "oat/runtime/oat_support_entrypoints.h" #include "locks.h" #include "offsets.h" +#include "root_visitor.h" #include "runtime_stats.h" #include "stack.h" #include "stack_indirect_reference_table.h" +#include "thread_state.h" #include "UniquePtr.h" namespace art { +namespace mirror { class AbstractMethod; class Array; -class BaseMutex; class Class; -class ClassLinker; class ClassLoader; +class Object; +template<class T> class ObjectArray; +template<class T> class PrimitiveArray; +typedef PrimitiveArray<int32_t> IntArray; +class StackTraceElement; +class StaticStorageBase; +class Throwable; +} // namespace mirror +class BaseMutex; +class ClassLinker; class Closure; class Context; struct DebugInvokeReq; @@ -51,20 +62,12 @@ class DexFile; struct JavaVMExt; struct JNIEnvExt; class Monitor; -class Object; class Runtime; class ScopedObjectAccess; class ScopedObjectAccessUnchecked; class ShadowFrame; -class StackTraceElement; -class StaticStorageBase; class Thread; class ThreadList; -class Throwable; - -template<class T> class ObjectArray; -template<class T> class PrimitiveArray; -typedef PrimitiveArray<int32_t> IntArray; // Thread priorities. These must match the Thread.MIN_PRIORITY, // Thread.NORM_PRIORITY, and Thread.MAX_PRIORITY constants. @@ -74,28 +77,6 @@ enum ThreadPriority { kMaxThreadPriority = 10, }; -enum ThreadState { - // Thread.State JDWP state - kTerminated, // TERMINATED TS_ZOMBIE Thread.run has returned, but Thread* still around - kRunnable, // RUNNABLE TS_RUNNING runnable - kTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeout - kSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep() - kBlocked, // BLOCKED TS_MONITOR blocked on a monitor - kWaiting, // WAITING TS_WAIT in Object.wait() - kWaitingForGcToComplete, // WAITING TS_WAIT blocked waiting for GC - kWaitingPerformingGc, // WAITING TS_WAIT performing GC - kWaitingForDebuggerSend, // WAITING TS_WAIT blocked waiting for events to be sent - kWaitingForDebuggerToAttach, // WAITING TS_WAIT blocked waiting for debugger to attach - kWaitingInMainDebuggerLoop, // WAITING TS_WAIT blocking/reading/processing debugger events - kWaitingForDebuggerSuspension, // WAITING TS_WAIT waiting for debugger suspend all - kWaitingForJniOnLoad, // WAITING TS_WAIT waiting for execution of dlopen and JNI on load code - kWaitingForSignalCatcherOutput, // WAITING TS_WAIT waiting for signal catcher IO to complete - kWaitingInMainSignalCatcherLoop, // WAITING TS_WAIT blocking/reading/processing signals - kStarting, // NEW TS_WAIT native thread started, not yet ready to run managed code - kNative, // RUNNABLE TS_RUNNING running in a JNI native method - kSuspended, // RUNNABLE TS_RUNNING suspended by GC or debugger -}; - enum ThreadFlag { kSuspendRequest = 1, // If set implies that suspend_count_ > 0 and the Thread should enter the // safepoint handler. @@ -127,7 +108,8 @@ class PACKED(4) Thread { return reinterpret_cast<Thread*>(thread); } - static Thread* FromManagedThread(const ScopedObjectAccessUnchecked& ts, Object* thread_peer) + static Thread* FromManagedThread(const ScopedObjectAccessUnchecked& ts, + mirror::Object* thread_peer) EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -245,7 +227,7 @@ class PACKED(4) Thread { return daemon_; } - bool HoldsLock(Object*); + bool HoldsLock(mirror::Object*); /* * Changes the priority of this thread to match that of the java.lang.Thread object. @@ -272,7 +254,7 @@ class PACKED(4) Thread { } // Returns the java.lang.Thread's name, or NULL if this Thread* doesn't have a peer. - String* GetThreadName(const ScopedObjectAccessUnchecked& ts) const + mirror::String* GetThreadName(const ScopedObjectAccessUnchecked& ts) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets 'name' to the java.lang.Thread's name. This requires no transition to managed code, @@ -282,7 +264,7 @@ class PACKED(4) Thread { // Sets the thread's name. void SetThreadName(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetPeer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Object* GetPeer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(jpeer_ == NULL); return opeer_; } @@ -301,13 +283,13 @@ class PACKED(4) Thread { return exception_ != NULL; } - Throwable* GetException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Throwable* GetException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return exception_; } void AssertNoPendingException() const; - void SetException(Throwable* new_exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void SetException(mirror::Throwable* new_exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(new_exception != NULL); // TODO: DCHECK(!IsExceptionPending()); exception_ = new_exception; @@ -317,7 +299,7 @@ class PACKED(4) Thread { exception_ = NULL; } - void DeliverException(Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void DeliverException(mirror::Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (exception == NULL) { ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); } else { @@ -334,11 +316,11 @@ class PACKED(4) Thread { long_jump_context_ = context; } - AbstractMethod* GetCurrentMethod(uint32_t* dex_pc = NULL, size_t* frame_id = NULL) const + mirror::AbstractMethod* GetCurrentMethod(uint32_t* dex_pc = NULL, size_t* frame_id = NULL) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void SetTopOfStack(void* stack, uintptr_t pc) { - AbstractMethod** top_method = reinterpret_cast<AbstractMethod**>(stack); + mirror::AbstractMethod** top_method = reinterpret_cast<mirror::AbstractMethod**>(stack); managed_stack_.SetTopQuickFrame(top_method); managed_stack_.SetTopQuickFramePc(pc); } @@ -369,7 +351,7 @@ class PACKED(4) Thread { //QuickFrameIterator FindExceptionHandler(void* throw_pc, void** handler_pc); - void* FindExceptionHandlerInMethod(const AbstractMethod* method, + void* FindExceptionHandlerInMethod(const mirror::AbstractMethod* method, void* throw_pc, const DexFile& dex_file, ClassLinker* class_linker); @@ -384,7 +366,7 @@ class PACKED(4) Thread { } // Convert a jobject into a Object* - Object* DecodeJObject(jobject obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Object* DecodeJObject(jobject obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Implements java.lang.Thread.interrupted. bool Interrupted(); @@ -393,11 +375,11 @@ class PACKED(4) Thread { void Interrupt(); void Notify(); - ClassLoader* GetClassLoaderOverride() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::ClassLoader* GetClassLoaderOverride() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return class_loader_override_; } - void SetClassLoaderOverride(ClassLoader* class_loader_override) { + void SetClassLoaderOverride(mirror::ClassLoader* class_loader_override) { class_loader_override_ = class_loader_override; } @@ -413,10 +395,10 @@ class PACKED(4) Thread { static jobjectArray InternalStackTraceToStackTraceElementArray(JNIEnv* env, jobject internal, jobjectArray output_array = NULL, int* stack_depth = NULL); - void VisitRoots(Heap::RootVisitor* visitor, void* arg) + void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void VerifyRoots(Heap::VerifyRootVisitor* visitor, void* arg) + void VerifyRoots(VerifyRootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); #if VERIFY_OBJECT_ENABLED @@ -535,7 +517,7 @@ class PACKED(4) Thread { // Is the given obj in this thread's stack indirect reference table? bool SirtContains(jobject obj) const; - void SirtVisitRoots(Heap::RootVisitor* visitor, void* arg); + void SirtVisitRoots(RootVisitor* visitor, void* arg); void PushSirt(StackIndirectReferenceTable* sirt) { sirt->SetLink(top_sirt_); @@ -692,7 +674,7 @@ class PACKED(4) Thread { byte* card_table_; // The pending exception or NULL. - Throwable* exception_; + mirror::Throwable* exception_; // The end of this thread's stack. This is the lowest safely-addressable address on the stack. // We leave extra space so there's room for the code that throws StackOverflowError. @@ -711,7 +693,7 @@ class PACKED(4) Thread { // Our managed peer (an instance of java.lang.Thread). The jobject version is used during thread // start up, until the thread is registered and the local opeer_ is used. - Object* opeer_; + mirror::Object* opeer_; jobject jpeer_; // The "lowest addressable byte" of the stack @@ -740,7 +722,7 @@ class PACKED(4) Thread { // The next thread in the wait set this thread is part of. Thread* wait_next_; // If we're blocked in MonitorEnter, this is the object we're trying to lock. - Object* monitor_enter_object_; + mirror::Object* monitor_enter_object_; friend class Monitor; friend class MonitorInfo; @@ -754,7 +736,7 @@ class PACKED(4) Thread { // Needed to get the right ClassLoader in JNI_OnLoad, but also // useful for testing. - ClassLoader* class_loader_override_; + mirror::ClassLoader* class_loader_override_; // Thread local, lazily allocated, long jump context. Used to deliver exceptions. Context* long_jump_context_; diff --git a/src/thread_list.cc b/src/thread_list.cc index 13c965cc18..ea8baacd30 100644 --- a/src/thread_list.cc +++ b/src/thread_list.cc @@ -22,6 +22,7 @@ #include "base/mutex.h" #include "debugger.h" +#include "thread.h" #include "timing_logger.h" #include "utils.h" @@ -579,14 +580,14 @@ void ThreadList::ForEach(void (*callback)(Thread*, void*), void* context) { } } -void ThreadList::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { +void ThreadList::VisitRoots(RootVisitor* visitor, void* arg) const { MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); for (It it = list_.begin(), end = list_.end(); it != end; ++it) { (*it)->VisitRoots(visitor, arg); } } -void ThreadList::VerifyRoots(Heap::VerifyRootVisitor* visitor, void* arg) const { +void ThreadList::VerifyRoots(VerifyRootVisitor* visitor, void* arg) const { MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); for (It it = list_.begin(), end = list_.end(); it != end; ++it) { (*it)->VerifyRoots(visitor, arg); diff --git a/src/thread_list.h b/src/thread_list.h index 7ded5e31a1..0470cfc3b9 100644 --- a/src/thread_list.h +++ b/src/thread_list.h @@ -18,10 +18,14 @@ #define ART_SRC_THREAD_LIST_H_ #include "base/mutex.h" -#include "thread.h" +#include "root_visitor.h" -namespace art { +#include <bitset> +#include <list> +namespace art { +class Closure; +class Thread; class TimingLogger; class ThreadList { @@ -84,10 +88,10 @@ class ThreadList { LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_); void Unregister(Thread* self) LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_); - void VisitRoots(Heap::RootVisitor* visitor, void* arg) const + void VisitRoots(RootVisitor* visitor, void* arg) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void VerifyRoots(Heap::VerifyRootVisitor* visitor, void* arg) const + void VerifyRoots(VerifyRootVisitor* visitor, void* arg) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Return a copy of the thread list. diff --git a/src/thread_state.h b/src/thread_state.h new file mode 100644 index 0000000000..7c4a16f914 --- /dev/null +++ b/src/thread_state.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_THREAD_STATE_H_ +#define ART_SRC_THREAD_STATE_H_ + +namespace art { + +enum ThreadState { + // Thread.State JDWP state + kTerminated, // TERMINATED TS_ZOMBIE Thread.run has returned, but Thread* still around + kRunnable, // RUNNABLE TS_RUNNING runnable + kTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeout + kSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep() + kBlocked, // BLOCKED TS_MONITOR blocked on a monitor + kWaiting, // WAITING TS_WAIT in Object.wait() + kWaitingForGcToComplete, // WAITING TS_WAIT blocked waiting for GC + kWaitingPerformingGc, // WAITING TS_WAIT performing GC + kWaitingForDebuggerSend, // WAITING TS_WAIT blocked waiting for events to be sent + kWaitingForDebuggerToAttach, // WAITING TS_WAIT blocked waiting for debugger to attach + kWaitingInMainDebuggerLoop, // WAITING TS_WAIT blocking/reading/processing debugger events + kWaitingForDebuggerSuspension, // WAITING TS_WAIT waiting for debugger suspend all + kWaitingForJniOnLoad, // WAITING TS_WAIT waiting for execution of dlopen and JNI on load code + kWaitingForSignalCatcherOutput, // WAITING TS_WAIT waiting for signal catcher IO to complete + kWaitingInMainSignalCatcherLoop, // WAITING TS_WAIT blocking/reading/processing signals + kStarting, // NEW TS_WAIT native thread started, not yet ready to run managed code + kNative, // RUNNABLE TS_RUNNING running in a JNI native method + kSuspended, // RUNNABLE TS_RUNNING suspended by GC or debugger +}; + +} // namespace art + +#endif // ART_SRC_THREAD_STATE_H_ diff --git a/src/timing_logger.cc b/src/timing_logger.cc new file mode 100644 index 0000000000..fee7a30579 --- /dev/null +++ b/src/timing_logger.cc @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "timing_logger.h" + +#include "base/logging.h" +#include "utils.h" + +#include <cmath> +#include <iomanip> + +namespace art { + +void TimingLogger::Dump() const { + Dump(LOG(INFO)); +} + +void TimingLogger::Dump(std::ostream& os) const { + uint64_t largest_time = 0; + os << name_ << ": begin\n"; + for (size_t i = 1; i < times_.size(); ++i) { + uint64_t delta_time = times_[i] - times_[i - 1]; + largest_time = std::max(largest_time, delta_time); + } + // Compute which type of unit we will use for printing the timings. + TimeUnit tu = GetAppropriateTimeUnit(largest_time); + uint64_t divisor = GetNsToTimeUnitDivisor(tu); + for (size_t i = 1; i < times_.size(); ++i) { + uint64_t delta_time = times_[i] - times_[i - 1]; + if (!precise_ && divisor >= 1000) { + // Make the fraction 0. + delta_time -= delta_time % (divisor / 1000); + } + os << name_ << ": " << std::setw(8) << FormatDuration(delta_time, tu) << " " << labels_[i] + << "\n"; + } + os << name_ << ": end, " << NsToMs(GetTotalNs()) << " ms\n"; +} + +void CumulativeLogger::Dump() const { + Dump(LOG(INFO)); +} + +void CumulativeLogger::Dump(std::ostream& os) const { + os << name_ << ": iterations " << iterations_ << " begin\n"; + //Find which unit we will use for the timing logger. + uint64_t largest_mean = 0; + for (size_t i = 0; i < times_.size(); ++i) { + // Convert back to nanoseconds from microseconds. + uint64_t mean = times_[i] / iterations_; + largest_mean = std::max(largest_mean, mean); + } + // Convert largest mean back to ns + TimeUnit tu = GetAppropriateTimeUnit(largest_mean * kAdjust); + uint64_t divisor = GetNsToTimeUnitDivisor(tu); + for (size_t i = 0; i < times_.size(); ++i) { + uint64_t mean_x2 = times_squared_[i] / iterations_; + uint64_t mean = times_[i] / iterations_; + uint64_t variance = mean_x2 - (mean * mean); + uint64_t std_dev = static_cast<uint64_t>(std::sqrt(static_cast<double>(variance))); + if (!precise_ && divisor >= 1000) { + // Make the fraction 0. + mean -= mean % (divisor / 1000); + std_dev -= std_dev % (divisor / 1000); + } + os << StringPrintf("%s: %10s (std_dev %8s) %s\n", + name_.c_str(), + FormatDuration(mean * kAdjust, tu).c_str(), + FormatDuration(std_dev * kAdjust, tu).c_str(), + labels_[i].c_str()); + } + uint64_t total_mean_x2 = total_time_squared_; + uint64_t mean_total_ns = GetTotalTime(); + if (iterations_ != 0) { + total_mean_x2 /= iterations_; + mean_total_ns /= iterations_; + } + uint64_t total_variance = total_mean_x2 - (mean_total_ns * mean_total_ns); + uint64_t total_std_dev = static_cast<uint64_t>( + std::sqrt(static_cast<double>(total_variance))); + os << name_ << ": end, mean " << PrettyDuration(mean_total_ns * kAdjust) + << " std_dev " << PrettyDuration(total_std_dev * kAdjust) << "\n"; +} + +} // namespace art diff --git a/src/timing_logger.h b/src/timing_logger.h index 3b3dcfc1aa..fc47028afe 100644 --- a/src/timing_logger.h +++ b/src/timing_logger.h @@ -17,10 +17,8 @@ #ifndef ART_SRC_TIMING_LOGGER_H_ #define ART_SRC_TIMING_LOGGER_H_ -#include "base/logging.h" -#include "utils.h" +#include "utils.h" // For NanoTime. -#include <cmath> #include <stdint.h> #include <string> #include <vector> @@ -47,31 +45,9 @@ class TimingLogger { labels_.push_back(label); } - void Dump() const { - Dump(LOG(INFO)); - } + void Dump() const; - void Dump(std::ostream& os) const { - uint64_t largest_time = 0; - os << name_ << ": begin\n"; - for (size_t i = 1; i < times_.size(); ++i) { - uint64_t delta_time = times_[i] - times_[i - 1]; - largest_time = std::max(largest_time, delta_time); - } - // Compute which type of unit we will use for printing the timings. - TimeUnit tu = GetAppropriateTimeUnit(largest_time); - uint64_t divisor = GetNsToTimeUnitDivisor(tu); - for (size_t i = 1; i < times_.size(); ++i) { - uint64_t delta_time = times_[i] - times_[i - 1]; - if (!precise_ && divisor >= 1000) { - // Make the fraction 0. - delta_time -= delta_time % (divisor / 1000); - } - os << name_ << ": " << std::setw(8) << FormatDuration(delta_time, tu) << " " << labels_[i] - << "\n"; - } - os << name_ << ": end, " << NsToMs(GetTotalNs()) << " ms\n"; - } + void Dump(std::ostream& os) const; uint64_t GetTotalNs() const { return times_.back() - times_.front(); @@ -149,50 +125,9 @@ class CumulativeLogger { total_time_squared_ += total_time * total_time; } - void Dump() const { - Dump(LOG(INFO)); - } + void Dump() const; - void Dump(std::ostream& os) const { - os << name_ << ": iterations " << iterations_ << " begin\n"; - //Find which unit we will use for the timing logger. - uint64_t largest_mean = 0; - for (size_t i = 0; i < times_.size(); ++i) { - // Convert back to nanoseconds from microseconds. - uint64_t mean = times_[i] / iterations_; - largest_mean = std::max(largest_mean, mean); - } - // Convert largest mean back to ns - TimeUnit tu = GetAppropriateTimeUnit(largest_mean * kAdjust); - uint64_t divisor = GetNsToTimeUnitDivisor(tu); - for (size_t i = 0; i < times_.size(); ++i) { - uint64_t mean_x2 = times_squared_[i] / iterations_; - uint64_t mean = times_[i] / iterations_; - uint64_t variance = mean_x2 - (mean * mean); - uint64_t std_dev = static_cast<uint64_t>(std::sqrt(static_cast<double>(variance))); - if (!precise_ && divisor >= 1000) { - // Make the fraction 0. - mean -= mean % (divisor / 1000); - std_dev -= std_dev % (divisor / 1000); - } - os << StringPrintf("%s: %10s (std_dev %8s) %s\n", - name_.c_str(), - FormatDuration(mean * kAdjust, tu).c_str(), - FormatDuration(std_dev * kAdjust, tu).c_str(), - labels_[i].c_str()); - } - uint64_t total_mean_x2 = total_time_squared_; - uint64_t mean_total_ns = GetTotalTime(); - if (iterations_ != 0) { - total_mean_x2 /= iterations_; - mean_total_ns /= iterations_; - } - uint64_t total_variance = total_mean_x2 - (mean_total_ns * mean_total_ns); - uint64_t total_std_dev = static_cast<uint64_t>( - std::sqrt(static_cast<double>(total_variance))); - os << name_ << ": end, mean " << PrettyDuration(mean_total_ns * kAdjust) - << " std_dev " << PrettyDuration(total_std_dev * kAdjust) << "\n"; - } + void Dump(std::ostream& os) const; uint64_t GetTotalNs() const { return GetTotalTime() * kAdjust; diff --git a/src/trace.cc b/src/trace.cc index 7b3cea8e3d..a23d202663 100644 --- a/src/trace.cc +++ b/src/trace.cc @@ -21,8 +21,10 @@ #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "debugger.h" -#include "dex_cache.h" #include "instrumentation.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/object_array-inl.h" #if !defined(ART_USE_LLVM_COMPILER) #include "oat/runtime/oat_support_entrypoints.h" #endif @@ -322,7 +324,8 @@ void Trace::FinishTracing() { } } -void Trace::LogMethodTraceEvent(Thread* self, const AbstractMethod* method, Trace::TraceEvent event) { +void Trace::LogMethodTraceEvent(Thread* self, const mirror::AbstractMethod* method, + Trace::TraceEvent event) { if (thread_clock_base_map_.find(self) == thread_clock_base_map_.end()) { uint64_t time = ThreadCpuMicroTime(); thread_clock_base_map_.Put(self, time); @@ -367,16 +370,17 @@ void Trace::GetVisitedMethods(size_t end_offset) { while (ptr < end) { uint32_t method_value = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24); - AbstractMethod* method = reinterpret_cast<AbstractMethod*>(TraceMethodId(method_value)); + mirror::AbstractMethod* method = + reinterpret_cast<mirror::AbstractMethod*>(TraceMethodId(method_value)); visited_methods_.insert(method); ptr += record_size_; } } void Trace::DumpMethodList(std::ostream& os) { - typedef std::set<const AbstractMethod*>::const_iterator It; // TODO: C++0x auto + typedef std::set<const mirror::AbstractMethod*>::const_iterator It; // TODO: C++0x auto for (It it = visited_methods_.begin(); it != visited_methods_.end(); ++it) { - const AbstractMethod* method = *it; + const mirror::AbstractMethod* method = *it; MethodHelper mh(method); os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method, PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(), diff --git a/src/trace.h b/src/trace.h index e3f254ee7a..1be1cc4142 100644 --- a/src/trace.h +++ b/src/trace.h @@ -29,7 +29,9 @@ namespace art { +namespace mirror { class AbstractMethod; +} // namespace mirror class Thread; enum ProfilerClockSource { @@ -59,7 +61,7 @@ class Trace { bool UseWallClock(); bool UseThreadCpuClock(); - void LogMethodTraceEvent(Thread* self, const AbstractMethod* method, TraceEvent event); + void LogMethodTraceEvent(Thread* self, const mirror::AbstractMethod* method, TraceEvent event); private: explicit Trace(File* trace_file, int buffer_size, int flags); @@ -73,7 +75,7 @@ class Trace { void DumpThreadList(std::ostream& os) LOCKS_EXCLUDED(Locks::thread_list_lock_); // Set of methods visited by the profiler. - std::set<const AbstractMethod*> visited_methods_; + std::set<const mirror::AbstractMethod*> visited_methods_; // Maps a thread to its clock base. SafeMap<Thread*, uint64_t> thread_clock_base_map_; diff --git a/src/utf.cc b/src/utf.cc index 174fe22f4f..cc7e2629db 100644 --- a/src/utf.cc +++ b/src/utf.cc @@ -17,7 +17,7 @@ #include "utf.h" #include "base/logging.h" -#include "object.h" +#include "mirror/array.h" namespace art { @@ -66,7 +66,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t } } -int32_t ComputeUtf16Hash(const CharArray* chars, int32_t offset, +int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset, size_t char_count) { int32_t hash = 0; for (size_t i = 0; i < char_count; i++) { @@ -29,9 +29,10 @@ * See http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 for the details. */ namespace art { - +namespace mirror { template<class T> class PrimitiveArray; typedef PrimitiveArray<uint16_t> CharArray; +} // namespace mirror /* * Returns the number of UTF-16 characters in the given modified UTF-8 string. @@ -65,7 +66,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t /* * The java.lang.String hashCode() algorithm. */ -int32_t ComputeUtf16Hash(const CharArray* chars, int32_t offset, size_t char_count) +int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset, size_t char_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count); diff --git a/src/utils.cc b/src/utils.cc index e2231c2154..6b93da835d 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -25,10 +25,17 @@ #include "UniquePtr.h" #include "base/unix_file/fd_file.h" -#include "class_loader.h" -#include "object.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class.h" +#include "mirror/class_loader.h" +#include "mirror/field.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/string.h" #include "object_utils.h" #include "os.h" +#include "utf.h" #if !defined(HAVE_POSIX_CLOCKS) #include <sys/time.h> @@ -220,14 +227,14 @@ void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts } } -std::string PrettyDescriptor(const String* java_descriptor) { +std::string PrettyDescriptor(const mirror::String* java_descriptor) { if (java_descriptor == NULL) { return "null"; } return PrettyDescriptor(java_descriptor->ToModifiedUtf8()); } -std::string PrettyDescriptor(const Class* klass) { +std::string PrettyDescriptor(const mirror::Class* klass) { if (klass == NULL) { return "null"; } @@ -288,7 +295,7 @@ std::string PrettyDescriptor(Primitive::Type type) { return PrettyDescriptor(descriptor_string); } -std::string PrettyField(const Field* f, bool with_type) { +std::string PrettyField(const mirror::Field* f, bool with_type) { if (f == NULL) { return "null"; } @@ -357,7 +364,7 @@ std::string PrettyReturnType(const char* signature) { return PrettyDescriptor(return_type); } -std::string PrettyMethod(const AbstractMethod* m, bool with_signature) { +std::string PrettyMethod(const mirror::AbstractMethod* m, bool with_signature) { if (m == NULL) { return "null"; } @@ -390,7 +397,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with return result; } -std::string PrettyTypeOf(const Object* obj) { +std::string PrettyTypeOf(const mirror::Object* obj) { if (obj == NULL) { return "null"; } @@ -406,7 +413,7 @@ std::string PrettyTypeOf(const Object* obj) { return result; } -std::string PrettyClass(const Class* c) { +std::string PrettyClass(const mirror::Class* c) { if (c == NULL) { return "null"; } @@ -417,7 +424,7 @@ std::string PrettyClass(const Class* c) { return result; } -std::string PrettyClassAndClassLoader(const Class* c) { +std::string PrettyClassAndClassLoader(const mirror::Class* c) { if (c == NULL) { return "null"; } @@ -613,7 +620,7 @@ std::string DescriptorToName(const char* descriptor) { return descriptor; } -std::string JniShortName(const AbstractMethod* m) { +std::string JniShortName(const mirror::AbstractMethod* m) { MethodHelper mh(m); std::string class_name(mh.GetDeclaringClassDescriptor()); // Remove the leading 'L' and trailing ';'... @@ -632,7 +639,7 @@ std::string JniShortName(const AbstractMethod* m) { return short_name; } -std::string JniLongName(const AbstractMethod* m) { +std::string JniLongName(const mirror::AbstractMethod* m) { std::string long_name; long_name += JniShortName(m); long_name += "__"; diff --git a/src/utils.h b/src/utils.h index 640743ccf8..f3c9b7a10a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -30,12 +30,15 @@ namespace art { -class Class; class DexFile; + +namespace mirror { +class Class; class Field; class AbstractMethod; class Object; class String; +} // namespace mirror enum TimeUnit { kTimeUnitNanosecond, @@ -172,21 +175,21 @@ bool EndsWith(const std::string& s, const char* suffix); // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int", // "[[I" would be "int[][]", "[Ljava/lang/String;" would be // "java.lang.String[]", and so forth. -std::string PrettyDescriptor(const String* descriptor); +std::string PrettyDescriptor(const mirror::String* descriptor); std::string PrettyDescriptor(const std::string& descriptor); std::string PrettyDescriptor(Primitive::Type type); -std::string PrettyDescriptor(const Class* klass) +std::string PrettyDescriptor(const mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or // "int a.b.C.f" (depending on the value of 'with_type'). -std::string PrettyField(const Field* f, bool with_type = true) +std::string PrettyField(const mirror::Field* f, bool with_type = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true); // Returns a human-readable signature for 'm'. Something like "a.b.C.m" or // "a.b.C.m(II)V" (depending on the value of 'with_signature'). -std::string PrettyMethod(const AbstractMethod* m, bool with_signature = true) +std::string PrettyMethod(const mirror::AbstractMethod* m, bool with_signature = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true); @@ -194,7 +197,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with // So given an instance of java.lang.String, the output would // be "java.lang.String". Given an array of int, the output would be "int[]". // Given String.class, the output would be "java.lang.Class<java.lang.String>". -std::string PrettyTypeOf(const Object* obj) +std::string PrettyTypeOf(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns a human-readable form of the type at an index in the specified dex file. @@ -203,11 +206,11 @@ std::string PrettyType(uint32_t type_idx, const DexFile& dex_file); // Returns a human-readable form of the name of the given class. // Given String.class, the output would be "java.lang.Class<java.lang.String>". -std::string PrettyClass(const Class* c) +std::string PrettyClass(const mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns a human-readable form of the name of the given class with its class loader. -std::string PrettyClassAndClassLoader(const Class* c) +std::string PrettyClassAndClassLoader(const mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns a human-readable size string such as "1MB". @@ -250,10 +253,10 @@ bool IsValidDescriptor(const char* s); // "Ljava/lang/String;" bool IsValidMemberName(const char* s); // Returns the JNI native function name for the non-overloaded method 'm'. -std::string JniShortName(const AbstractMethod* m) +std::string JniShortName(const mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the JNI native function name for the overloaded method 'm'. -std::string JniLongName(const AbstractMethod* m) +std::string JniLongName(const mirror::AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool ReadFileToString(const std::string& file_name, std::string* result); diff --git a/src/utils_test.cc b/src/utils_test.cc index f1983be08d..0966e717ca 100644 --- a/src/utils_test.cc +++ b/src/utils_test.cc @@ -14,8 +14,12 @@ * limitations under the License. */ -#include "object.h" #include "common_test.h" +#include "mirror/array.h" +#include "mirror/array-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/string.h" #include "scoped_thread_state_change.h" #include "sirt_ref.h" #include "utils.h" @@ -89,15 +93,15 @@ TEST_F(UtilsTest, PrettyTypeOf) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyTypeOf(NULL)); - SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "")); + SirtRef<mirror::String> s(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "")); EXPECT_EQ("java.lang.String", PrettyTypeOf(s.get())); - SirtRef<ShortArray> a(soa.Self(), ShortArray::Alloc(soa.Self(), 2)); + SirtRef<mirror::ShortArray> a(soa.Self(), mirror::ShortArray::Alloc(soa.Self(), 2)); EXPECT_EQ("short[]", PrettyTypeOf(a.get())); - Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); + mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.String[]", PrettyTypeOf(o)); EXPECT_EQ("java.lang.Class<java.lang.String[]>", PrettyTypeOf(o->GetClass())); } @@ -105,18 +109,18 @@ TEST_F(UtilsTest, PrettyTypeOf) { TEST_F(UtilsTest, PrettyClass) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyClass(NULL)); - Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); + mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class<java.lang.String[]>", PrettyClass(o->GetClass())); } TEST_F(UtilsTest, PrettyClassAndClassLoader) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyClassAndClassLoader(NULL)); - Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); + mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class<java.lang.String[],null>", PrettyClassAndClassLoader(o->GetClass())); } @@ -124,9 +128,9 @@ TEST_F(UtilsTest, PrettyField) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyField(NULL)); - Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;"); + mirror::Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;"); - Field* f; + mirror::Field* f; f = java_lang_String->FindDeclaredInstanceField("count", "I"); EXPECT_EQ("int java.lang.String.count", PrettyField(f)); EXPECT_EQ("java.lang.String.count", PrettyField(f, false)); @@ -193,9 +197,9 @@ TEST_F(UtilsTest, MangleForJni) { TEST_F(UtilsTest, JniShortName_JniLongName) { ScopedObjectAccess soa(Thread::Current()); - Class* c = class_linker_->FindSystemClass("Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - AbstractMethod* m; + mirror::AbstractMethod* m; m = c->FindVirtualMethod("charAt", "(I)C"); ASSERT_TRUE(m != NULL); diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc index 7afa6d475e..bcac374d46 100644 --- a/src/verifier/method_verifier.cc +++ b/src/verifier/method_verifier.cc @@ -22,13 +22,20 @@ #include "base/stringpiece.h" #include "class_linker.h" #include "compiler.h" -#include "dex_cache.h" #include "dex_file.h" #include "dex_instruction.h" #include "dex_instruction_visitor.h" +#include "gc/card_table-inl.h" #include "indenter.h" #include "intern_table.h" #include "leb128.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/field-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "runtime.h" #include "verifier/dex_gc_map.h" @@ -167,11 +174,12 @@ void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InsnFlags* flags, } } -MethodVerifier::FailureKind MethodVerifier::VerifyClass(const Class* klass, std::string& error) { +MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* klass, + std::string& error) { if (klass->IsVerified()) { return kNoFailure; } - Class* super = klass->GetSuperClass(); + mirror::Class* super = klass->GetSuperClass(); if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") { error = "Verifier rejected class "; error += PrettyDescriptor(klass); @@ -199,7 +207,10 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const Class* klass, std: } MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, - DexCache* dex_cache, ClassLoader* class_loader, uint32_t class_def_idx, std::string& error) { + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + uint32_t class_def_idx, + std::string& error) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx); const byte* class_data = dex_file->GetClassData(class_def); if (class_data == NULL) { @@ -224,7 +235,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, } previous_direct_method_idx = method_idx; InvokeType type = it.GetMethodInvokeType(class_def); - AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type); + mirror::AbstractMethod* method = + linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type); if (method == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); // We couldn't resolve the method, but continue regardless. @@ -258,7 +270,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, } previous_virtual_method_idx = method_idx; InvokeType type = it.GetMethodInvokeType(class_def); - AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type); + mirror::AbstractMethod* method = + linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type); if (method == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); // We couldn't resolve the method, but continue regardless. @@ -288,9 +301,14 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, } } -MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file, - DexCache* dex_cache, ClassLoader* class_loader, uint32_t class_def_idx, - const DexFile::CodeItem* code_item, AbstractMethod* method, uint32_t method_access_flags) { +MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, + const DexFile* dex_file, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, + uint32_t class_def_idx, + const DexFile::CodeItem* code_item, + mirror::AbstractMethod* method, + uint32_t method_access_flags) { MethodVerifier::FailureKind result = kNoFailure; uint64_t start_ns = NanoTime(); @@ -326,9 +344,10 @@ MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, co } void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_idx, - const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, uint32_t class_def_idx, - const DexFile::CodeItem* code_item, AbstractMethod* method, + const DexFile* dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, + const DexFile::CodeItem* code_item, + mirror::AbstractMethod* method, uint32_t method_access_flags) { MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item, dex_method_idx, method, method_access_flags, true); @@ -339,11 +358,12 @@ void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_i } std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_method_idx, - const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, + const DexFile* dex_file, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - AbstractMethod* method, + mirror::AbstractMethod* method, uint32_t method_access_flags, uint32_t dex_pc) { MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item, dex_method_idx, method, method_access_flags, true); @@ -351,9 +371,11 @@ std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_method_idx, return verifier.DescribeVRegs(dex_pc); } -MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - uint32_t dex_method_idx, AbstractMethod* method, uint32_t method_access_flags, +MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, + const DexFile::CodeItem* code_item, + uint32_t dex_method_idx, mirror::AbstractMethod* method, + uint32_t method_access_flags, bool can_load_classes) : reg_types_(can_load_classes), work_insn_idx_(-1), @@ -374,7 +396,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache, can_load_classes_(can_load_classes) { } -void MethodVerifier::FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc, +void MethodVerifier::FindLocksAtDexPc(mirror::AbstractMethod* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs) { MethodHelper mh(m); MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(), @@ -569,8 +591,9 @@ bool MethodVerifier::ScanTryCatchBlocks() { // Ensure exception types are resolved so that they don't need resolution to be delivered, // unresolved exception types will be ignored by exception delivery if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) { - Class* exception_type = linker->ResolveType(*dex_file_, iterator.GetHandlerTypeIndex(), - dex_cache_, class_loader_); + mirror::Class* exception_type = linker->ResolveType(*dex_file_, + iterator.GetHandlerTypeIndex(), + dex_cache_, class_loader_); if (exception_type == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); Thread::Current()->ClearException(); @@ -1960,7 +1983,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { dec_insn.opcode == Instruction::INVOKE_SUPER_RANGE); bool is_super = (dec_insn.opcode == Instruction::INVOKE_SUPER || dec_insn.opcode == Instruction::INVOKE_SUPER_RANGE); - AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, is_range, is_super); + mirror::AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, + is_range, is_super); const char* descriptor; if (called_method == NULL) { uint32_t method_idx = dec_insn.vB; @@ -1982,7 +2006,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::INVOKE_DIRECT: case Instruction::INVOKE_DIRECT_RANGE: { bool is_range = (dec_insn.opcode == Instruction::INVOKE_DIRECT_RANGE); - AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_DIRECT, is_range, false); + mirror::AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_DIRECT, + is_range, false); const char* return_type_descriptor; bool is_constructor; if (called_method == NULL) { @@ -2048,7 +2073,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::INVOKE_STATIC: case Instruction::INVOKE_STATIC_RANGE: { bool is_range = (dec_insn.opcode == Instruction::INVOKE_STATIC_RANGE); - AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false); + mirror::AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false); const char* descriptor; if (called_method == NULL) { uint32_t method_idx = dec_insn.vB; @@ -2070,9 +2095,9 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::INVOKE_INTERFACE: case Instruction::INVOKE_INTERFACE_RANGE: { bool is_range = (dec_insn.opcode == Instruction::INVOKE_INTERFACE_RANGE); - AbstractMethod* abs_method = VerifyInvocationArgs(dec_insn, METHOD_INTERFACE, is_range, false); + mirror::AbstractMethod* abs_method = VerifyInvocationArgs(dec_insn, METHOD_INTERFACE, is_range, false); if (abs_method != NULL) { - Class* called_interface = abs_method->GetDeclaringClass(); + mirror::Class* called_interface = abs_method->GetDeclaringClass(); if (!called_interface->IsInterface() && !called_interface->IsObjectClass()) { Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected interface class in invoke-interface '" << PrettyMethod(abs_method) << "'"; @@ -2558,7 +2583,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) { const char* descriptor = dex_file_->StringByTypeIdx(class_idx); const RegType& referrer = GetDeclaringClass(); - Class* klass = dex_cache_->GetResolvedType(class_idx); + mirror::Class* klass = dex_cache_->GetResolvedType(class_idx); const RegType& result = klass != NULL ? reg_types_.FromClass(klass, klass->IsFinal()) : reg_types_.FromDescriptor(class_loader_, descriptor, false); @@ -2621,7 +2646,8 @@ const RegType& MethodVerifier::GetCaughtExceptionType() { return *common_super; } -AbstractMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx, MethodType method_type) { +mirror::AbstractMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx, + MethodType method_type) { const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx); const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_); if (klass_type.IsConflict()) { @@ -2633,9 +2659,9 @@ AbstractMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_ if (klass_type.IsUnresolvedTypes()) { return NULL; // Can't resolve Class so no more to do here } - Class* klass = klass_type.GetClass(); + mirror::Class* klass = klass_type.GetClass(); const RegType& referrer = GetDeclaringClass(); - AbstractMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx); + mirror::AbstractMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx); if (res_method == NULL) { const char* name = dex_file_->GetMethodName(method_id); std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL)); @@ -2712,11 +2738,12 @@ AbstractMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_ return res_method; } -AbstractMethod* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn, - MethodType method_type, bool is_range, bool is_super) { +mirror::AbstractMethod* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn, + MethodType method_type, bool is_range, + bool is_super) { // Resolve the method. This could be an abstract or concrete method depending on what sort of call // we're making. - AbstractMethod* res_method = ResolveMethodAndCheckAccess(dec_insn.vB, method_type); + mirror::AbstractMethod* res_method = ResolveMethodAndCheckAccess(dec_insn.vB, method_type); if (res_method == NULL) { // error or class is unresolved return NULL; } @@ -2732,7 +2759,7 @@ AbstractMethod* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& d << " to super " << PrettyMethod(res_method); return NULL; } - Class* super_klass = super.GetClass(); + mirror::Class* super_klass = super.GetClass(); if (res_method->GetMethodIndex() >= super_klass->GetVTable()->GetLength()) { MethodHelper mh(res_method); Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from " @@ -2771,7 +2798,7 @@ AbstractMethod* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& d return NULL; } if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) { - Class* klass = res_method->GetDeclaringClass(); + mirror::Class* klass = res_method->GetDeclaringClass(); const RegType& res_method_class = reg_types_.FromClass(klass, klass->IsFinal()); if (!res_method_class.IsAssignableFrom(actual_arg_type)) { Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type @@ -2935,7 +2962,7 @@ void MethodVerifier::VerifyAPut(const DecodedInstruction& dec_insn, } } -Field* MethodVerifier::GetStaticField(int field_idx) { +mirror::Field* MethodVerifier::GetStaticField(int field_idx) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); // Check access to class const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_); @@ -2948,7 +2975,7 @@ Field* MethodVerifier::GetStaticField(int field_idx) { if (klass_type.IsUnresolvedTypes()) { return NULL; // Can't resolve Class so no more to do here, will do checking at runtime. } - Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx, + mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, class_loader_); if (field == NULL) { LOG(INFO) << "unable to resolve static field " << field_idx << " (" @@ -2970,7 +2997,7 @@ Field* MethodVerifier::GetStaticField(int field_idx) { } } -Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) { +mirror::Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); // Check access to class const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_); @@ -2983,7 +3010,7 @@ Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) if (klass_type.IsUnresolvedTypes()) { return NULL; // Can't resolve Class so no more to do here } - Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx, + mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, class_loader_); if (field == NULL) { LOG(INFO) << "unable to resolve instance field " << field_idx << " (" @@ -3005,7 +3032,7 @@ Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) // Cannot infer and check type, however, access will cause null pointer exception return field; } else { - Class* klass = field->GetDeclaringClass(); + mirror::Class* klass = field->GetDeclaringClass(); const RegType& field_klass = reg_types_.FromClass(klass, klass->IsFinal()); if (obj_type.IsUninitializedTypes() && (!IsConstructor() || GetDeclaringClass().Equals(obj_type) || @@ -3032,7 +3059,7 @@ Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) void MethodVerifier::VerifyISGet(const DecodedInstruction& dec_insn, const RegType& insn_type, bool is_primitive, bool is_static) { uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC; - Field* field; + mirror::Field* field; if (is_static) { field = GetStaticField(field_idx); } else { @@ -3040,7 +3067,7 @@ void MethodVerifier::VerifyISGet(const DecodedInstruction& dec_insn, field = GetInstanceField(object_type, field_idx); } const char* descriptor; - ClassLoader* loader; + mirror::ClassLoader* loader; if (field != NULL) { descriptor = FieldHelper(field).GetTypeDescriptor(); loader = field->GetDeclaringClass()->GetClassLoader(); @@ -3085,7 +3112,7 @@ void MethodVerifier::VerifyISGet(const DecodedInstruction& dec_insn, void MethodVerifier::VerifyISPut(const DecodedInstruction& dec_insn, const RegType& insn_type, bool is_primitive, bool is_static) { uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC; - Field* field; + mirror::Field* field; if (is_static) { field = GetStaticField(field_idx); } else { @@ -3093,7 +3120,7 @@ void MethodVerifier::VerifyISPut(const DecodedInstruction& dec_insn, field = GetInstanceField(object_type, field_idx); } const char* descriptor; - ClassLoader* loader; + mirror::ClassLoader* loader; if (field != NULL) { descriptor = FieldHelper(field).GetTypeDescriptor(); loader = field->GetDeclaringClass()->GetClassLoader(); @@ -3215,7 +3242,7 @@ const RegType& MethodVerifier::GetMethodReturnType() { const RegType& MethodVerifier::GetDeclaringClass() { if (foo_method_ != NULL) { - Class* klass = foo_method_->GetDeclaringClass(); + mirror::Class* klass = foo_method_->GetDeclaringClass(); return reg_types_.FromClass(klass, klass->IsFinal()); } else { const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h index 7779efe0d2..a36a1f93dd 100644 --- a/src/verifier/method_verifier.h +++ b/src/verifier/method_verifier.h @@ -28,7 +28,7 @@ #include "compiler.h" #include "dex_file.h" #include "dex_instruction.h" -#include "object.h" +#include "mirror/object.h" #include "reg_type.h" #include "reg_type_cache.h" #include "register_line.h" @@ -156,25 +156,25 @@ class MethodVerifier { }; /* Verify a class. Returns "kNoFailure" on success. */ - static FailureKind VerifyClass(const Class* klass, std::string& error) + static FailureKind VerifyClass(const mirror::Class* klass, std::string& error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static FailureKind VerifyClass(const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, uint32_t class_def_idx, + static FailureKind VerifyClass(const DexFile* dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, std::string& error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void VerifyMethodAndDump(std::ostream& os, uint32_t method_idx, const DexFile* dex_file, - DexCache* dex_cache, ClassLoader* class_loader, + mirror::DexCache* dex_cache, mirror::ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - AbstractMethod* method, uint32_t method_access_flags) + mirror::AbstractMethod* method, uint32_t method_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx, - const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, + const DexFile* dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - AbstractMethod* method, + mirror::AbstractMethod* method, uint32_t method_access_flags, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -209,7 +209,7 @@ class MethodVerifier { // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding // to the locks held at 'dex_pc' in 'm'. - static void FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc, + static void FindLocksAtDexPc(mirror::AbstractMethod* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -229,9 +229,11 @@ class MethodVerifier { } private: - explicit MethodVerifier(const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - uint32_t method_idx, AbstractMethod* method, uint32_t access_flags, bool can_load_classes) + explicit MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, + const DexFile::CodeItem* code_item, + uint32_t method_idx, mirror::AbstractMethod* method, uint32_t access_flags, + bool can_load_classes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Adds the given string to the beginning of the last failure message. @@ -251,9 +253,11 @@ class MethodVerifier { * (3) Iterate through the method, checking type safety and looking * for code flow problems. */ - static FailureKind VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache, - ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item, - AbstractMethod* method, uint32_t method_access_flags) + static FailureKind VerifyMethod(uint32_t method_idx, const DexFile* dex_file, + mirror::DexCache* dex_cache, + mirror::ClassLoader* class_loader, uint32_t class_def_idx, + const DexFile::CodeItem* code_item, + mirror::AbstractMethod* method, uint32_t method_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Run verification on the method. Returns true if verification completes and false if the input @@ -477,11 +481,11 @@ class MethodVerifier { bool is_primitive) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Lookup instance field and fail for resolution violations - Field* GetInstanceField(const RegType& obj_type, int field_idx) + mirror::Field* GetInstanceField(const RegType& obj_type, int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Lookup static field and fail for resolution violations - Field* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Field* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Perform verification of an iget or sget instruction. void VerifyISGet(const DecodedInstruction& insn, const RegType& insn_type, @@ -511,7 +515,7 @@ class MethodVerifier { * the referrer can access the resolved method. * Does not throw exceptions. */ - AbstractMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type) + mirror::AbstractMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /* @@ -536,7 +540,7 @@ class MethodVerifier { * Returns the resolved method on success, NULL on failure (with *failure * set appropriately). */ - AbstractMethod* VerifyInvocationArgs(const DecodedInstruction& dec_insn, + mirror::AbstractMethod* VerifyInvocationArgs(const DecodedInstruction& dec_insn, MethodType method_type, bool is_range, bool is_super) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -594,7 +598,7 @@ class MethodVerifier { void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc); // Describe VRegs at the given dex pc. - std::vector<int32_t> DescribeVRegs(uint32_t dex_pc); + std::vector<int32_t> DescribeVRegs(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); InsnFlags* CurrentInsnFlags(); @@ -639,13 +643,13 @@ class MethodVerifier { uint32_t dex_method_idx_; // The method we're working on. // Its object representation if known. - AbstractMethod* foo_method_ GUARDED_BY(Locks::mutator_lock_); + mirror::AbstractMethod* foo_method_ GUARDED_BY(Locks::mutator_lock_); uint32_t method_access_flags_; // Method's access flags. const DexFile* dex_file_; // The dex file containing the method. // The dex_cache for the declaring class of the method. - DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_); + mirror::DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_); // The class loader for the declaring class of the method. - ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_); + mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_); uint32_t class_def_idx_; // The class def index of the declaring class of the method. const DexFile::CodeItem* code_item_; // The code item containing the code for the method. UniquePtr<InsnFlags[]> insn_flags_; // Instruction widths and flags, one entry per code unit. diff --git a/src/verifier/method_verifier_test.cc b/src/verifier/method_verifier_test.cc index 8d4c5134dc..5cb39749ed 100644 --- a/src/verifier/method_verifier_test.cc +++ b/src/verifier/method_verifier_test.cc @@ -30,7 +30,7 @@ class MethodVerifierTest : public CommonTest { void VerifyClass(const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ASSERT_TRUE(descriptor != NULL); - Class* klass = class_linker_->FindSystemClass(descriptor.c_str()); + mirror::Class* klass = class_linker_->FindSystemClass(descriptor.c_str()); // Verify the class std::string error_msg; diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc index ab1da1e2c3..56de1795b1 100644 --- a/src/verifier/reg_type.cc +++ b/src/verifier/reg_type.cc @@ -16,9 +16,14 @@ #include "reg_type.h" +#include "mirror/class.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" #include "object_utils.h" #include "reg_type_cache.h" +#include <limits> + namespace art { namespace verifier { @@ -165,7 +170,7 @@ std::set<uint16_t> RegType::GetMergedTypes(const RegTypeCache* cache) const { const RegType& RegType::GetSuperClass(RegTypeCache* cache) const { if (!IsUnresolvedTypes()) { - Class* super_klass = GetClass()->GetSuperClass(); + mirror::Class* super_klass = GetClass()->GetSuperClass(); if (super_klass != NULL) { return cache->FromClass(super_klass, IsPreciseReference()); } else { @@ -198,7 +203,7 @@ bool RegType::CanAccess(const RegType& other) const { } } -bool RegType::CanAccessMember(Class* klass, uint32_t access_flags) const { +bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const { if (access_flags & kAccPublic) { return true; } @@ -209,6 +214,62 @@ bool RegType::CanAccessMember(Class* klass, uint32_t access_flags) const { } } +bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) { + // Primitive arrays will always resolve + DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '['); + return descriptor_[0] == '['; + } else if (HasClass()) { + mirror::Class* type = GetClass(); + return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive(); + } else { + return false; + } +} + +bool RegType::IsConstantByte() const { + return IsConstant() && + ConstantValue() >= std::numeric_limits<jbyte>::min() && + ConstantValue() <= std::numeric_limits<jbyte>::max(); +} + +bool RegType::IsConstantShort() const { + return IsConstant() && + ConstantValue() >= std::numeric_limits<jshort>::min() && + ConstantValue() <= std::numeric_limits<jshort>::max(); +} + +bool RegType::IsConstantChar() const { + return IsConstant() && ConstantValue() >= 0 && + ConstantValue() <= std::numeric_limits<jchar>::max(); +} + +bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return IsReference() && GetClass()->IsObjectClass(); +} + +bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) { + return descriptor_[0] == '['; + } else if (HasClass()) { + return GetClass()->IsArrayClass(); + } else { + return false; + } +} + +bool RegType::IsJavaLangObjectArray() const { + if (HasClass()) { + mirror::Class* type = GetClass(); + return type->IsArrayClass() && type->GetComponentType()->IsObjectClass(); + } + return false; +} + +bool RegType::IsInstantiableTypes() const { + return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable()); +} + bool RegType::IsAssignableFrom(const RegType& src) const { if (Equals(src)) { return true; @@ -363,11 +424,11 @@ const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_ty // with itself, 0 or Object are handled above. return reg_types->Conflict(); } else { // Two reference types, compute Join - Class* c1 = GetClass(); - Class* c2 = incoming_type.GetClass(); + mirror::Class* c1 = GetClass(); + mirror::Class* c2 = incoming_type.GetClass(); DCHECK(c1 != NULL && !c1->IsPrimitive()); DCHECK(c2 != NULL && !c2->IsPrimitive()); - Class* join_class = ClassJoin(c1, c2); + mirror::Class* join_class = ClassJoin(c1, c2); if (c1 == join_class && !IsPreciseReference()) { return *this; } else if (c2 == join_class && !incoming_type.IsPreciseReference()) { @@ -382,7 +443,7 @@ const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_ty } // See comment in reg_type.h -Class* RegType::ClassJoin(Class* s, Class* t) { +mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) { DCHECK(!s->IsPrimitive()) << PrettyClass(s); DCHECK(!t->IsPrimitive()) << PrettyClass(t); if (s == t) { @@ -392,21 +453,21 @@ Class* RegType::ClassJoin(Class* s, Class* t) { } else if (t->IsAssignableFrom(s)) { return t; } else if (s->IsArrayClass() && t->IsArrayClass()) { - Class* s_ct = s->GetComponentType(); - Class* t_ct = t->GetComponentType(); + mirror::Class* s_ct = s->GetComponentType(); + mirror::Class* t_ct = t->GetComponentType(); if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) { // Given the types aren't the same, if either array is of primitive types then the only // common parent is java.lang.Object - Class* result = s->GetSuperClass(); // short-cut to java.lang.Object + mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object DCHECK(result->IsObjectClass()); return result; } - Class* common_elem = ClassJoin(s_ct, t_ct); + mirror::Class* common_elem = ClassJoin(s_ct, t_ct); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ClassLoader* class_loader = s->GetClassLoader(); + mirror::ClassLoader* class_loader = s->GetClassLoader(); std::string descriptor("["); descriptor += ClassHelper(common_elem).GetDescriptor(); - Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); + mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); DCHECK(array_class != NULL); return array_class; } else { @@ -433,8 +494,44 @@ Class* RegType::ClassJoin(Class* s, Class* t) { } } -std::ostream& operator<<(std::ostream& os, const RegType& rhs) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +void RegType::CheckInvariants() const { + bool checked = false; + if (IsConstant() || IsConstantLo() || IsConstantHi()) { + // Constants: allocation_pc_or_constant_or_merged_types_ will hold the constant value, nothing + // else should be defined. + CHECK(descriptor_.empty()) << *this; + CHECK(klass_ == NULL) << *this; + checked = true; + } + if (IsUnresolvedTypes()) { + if (IsUnresolvedMergedReference()) { + // Unresolved merged types: allocation pc/merged types should be defined. + CHECK(descriptor_.empty()) << *this; + CHECK(klass_ == NULL) << *this; + CHECK_NE(allocation_pc_or_constant_or_merged_types_, 0U) << *this; + } else { + // Unresolved types: have a descriptor and no allocation pc/merged types. + CHECK(!descriptor_.empty()) << *this; + CHECK(klass_ == NULL) << *this; + if (!IsUnresolvedAndUninitializedReference()) { + CHECK_EQ(allocation_pc_or_constant_or_merged_types_, 0U) << *this; + } + } + checked = true; + } + if (IsReferenceTypes() && !checked) { + // A resolved reference type. + CHECK(descriptor_.empty()) << *this; + CHECK(klass_ != NULL) << *this; + CHECK(klass_->IsClass()) << *this; + if (!IsUninitializedReference()) { + CHECK_EQ(allocation_pc_or_constant_or_merged_types_, 0U) << *this; + } + } + CHECK(checked = true); +} + +std::ostream& operator<<(std::ostream& os, const RegType& rhs) { os << rhs.Dump(); return os; } diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h index 65ee88a639..dc9a33a691 100644 --- a/src/verifier/reg_type.h +++ b/src/verifier/reg_type.h @@ -18,11 +18,18 @@ #define ART_SRC_VERIFIER_REG_TYPE_H_ #include "base/macros.h" -#include "object.h" +#include "primitive.h" + +#include "jni.h" #include <stdint.h> +#include <set> +#include <string> namespace art { +namespace mirror { +class Class; +} // namespace mirror namespace verifier { class RegTypeCache; @@ -189,20 +196,9 @@ class RegType { bool IsConstantBoolean() const { return IsConstant() && ConstantValue() >= 0 && ConstantValue() <= 1; } - bool IsConstantByte() const { - return IsConstant() && - ConstantValue() >= std::numeric_limits<jbyte>::min() && - ConstantValue() <= std::numeric_limits<jbyte>::max(); - } - bool IsConstantShort() const { - return IsConstant() && - ConstantValue() >= std::numeric_limits<jshort>::min() && - ConstantValue() <= std::numeric_limits<jshort>::max(); - } - bool IsConstantChar() const { - return IsConstant() && ConstantValue() >= 0 && - ConstantValue() <= std::numeric_limits<jchar>::max(); - } + bool IsConstantByte() const; + bool IsConstantShort() const; + bool IsConstantChar() const; bool IsReferenceTypes() const { return IsNonZeroReferenceTypes() || IsZero(); @@ -261,38 +257,17 @@ class RegType { return IsReference() || IsPreciseReference(); } - Class* GetClass() const { + mirror::Class* GetClass() const { DCHECK(!IsUnresolvedReference()); DCHECK(klass_ != NULL); return klass_; } - bool IsJavaLangObject() const { - return IsReference() && GetClass()->IsObjectClass(); - } + bool IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) { - return descriptor_[0] == '['; - } else if (HasClass()) { - return GetClass()->IsArrayClass(); - } else { - return false; - } - } + bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) { - // Primitive arrays will always resolve - DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '['); - return descriptor_[0] == '['; - } else if (HasClass()) { - Class* type = GetClass(); - return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive(); - } else { - return false; - } - } + bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); Primitive::Type GetPrimitiveType() const { if (IsNonZeroReferenceTypes()) { @@ -317,17 +292,9 @@ class RegType { } } - bool IsJavaLangObjectArray() const { - if (HasClass()) { - Class* type = GetClass(); - return type->IsArrayClass() && type->GetComponentType()->IsObjectClass(); - } - return false; - } + bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsInstantiableTypes() const { - return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable()); - } + bool IsInstantiableTypes() const; std::string GetDescriptor() const { DCHECK(IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()); @@ -364,7 +331,7 @@ class RegType { bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Can this type access a member with the given properties? - bool CanAccessMember(Class* klass, uint32_t access_flags) const + bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Can this type be assigned by src? @@ -393,47 +360,48 @@ class RegType { * * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy */ - static Class* ClassJoin(Class* s, Class* t) + static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: friend class RegTypeCache; - RegType(Type type, Class* klass, + RegType(Type type, mirror::Class* klass, uint32_t allocation_pc_or_constant_or_merged_types, uint16_t cache_id) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : type_(type), klass_(klass), allocation_pc_or_constant_or_merged_types_(allocation_pc_or_constant_or_merged_types), cache_id_(cache_id) { - DCHECK(IsConstant() || IsConstantLo() || IsConstantHi() || - IsUninitializedTypes() || IsUnresolvedMergedReference() || IsUnresolvedSuperClass() || - allocation_pc_or_constant_or_merged_types == 0); - if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUndefined() && - !IsConflict() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) { - DCHECK(klass_ != NULL); - DCHECK(klass_->IsClass()); - DCHECK(!IsUnresolvedTypes()); - } +#ifndef NDEBUG + CheckInvariants(); +#endif } RegType(Type type, const std::string& descriptor, uint32_t allocation_pc, uint16_t cache_id) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : type_(type), klass_(NULL), descriptor_(descriptor), allocation_pc_or_constant_or_merged_types_(allocation_pc), cache_id_(cache_id) { +#ifndef NDEBUG + CheckInvariants(); +#endif } + void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const Type type_; // The current type of the register - // If known the type of the register... - Class* klass_; + // For reference types, if known the type of the register... + mirror::Class* klass_; // ...else a String for the descriptor. std::string descriptor_; // Overloaded field that: // - if IsConstant() holds a 32bit constant value - // - is IsReference() holds the allocation_pc or kInitArgAddr for an initialized reference or - // kUninitThisArgAddr for an uninitialized this ptr + // - is IsUninitializedReference()/IsUnresolvedAndUninitializedReference() holds the pc the + // instance in the register was being allocated. const uint32_t allocation_pc_or_constant_or_merged_types_; // A RegType cache densely encodes types, this is the location in the cache for this type @@ -441,7 +409,8 @@ class RegType { DISALLOW_COPY_AND_ASSIGN(RegType); }; -std::ostream& operator<<(std::ostream& os, const RegType& rhs); +std::ostream& operator<<(std::ostream& os, const RegType& rhs) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } // namespace verifier } // namespace art diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc index 3bf5ad886a..6ca54dea9a 100644 --- a/src/verifier/reg_type_cache.cc +++ b/src/verifier/reg_type_cache.cc @@ -16,6 +16,8 @@ #include "reg_type_cache.h" +#include "mirror/class-inl.h" +#include "mirror/object-inl.h" #include "object_utils.h" namespace art { @@ -57,7 +59,7 @@ static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) { } } -const RegType& RegTypeCache::FromDescriptor(ClassLoader* loader, const char* descriptor, +const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise) { return From(RegTypeFromDescriptor(descriptor), loader, descriptor, precise); } @@ -67,14 +69,14 @@ static bool MatchingPrecisionForClass(RegType* entry, bool precise) return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise); } -const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const char* descriptor, - bool precise) { +const RegType& RegTypeCache::From(RegType::Type type, mirror::ClassLoader* loader, + const char* descriptor, bool precise) { if (type <= RegType::kRegTypeLastFixedLocation) { // entries should be sized greater than primitive types DCHECK_GT(entries_.size(), static_cast<size_t>(type)); RegType* entry = entries_[type]; if (entry == NULL) { - Class* c = NULL; + mirror::Class* c = NULL; if (strlen(descriptor) != 0) { c = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor); } @@ -100,7 +102,7 @@ const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const } } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Class* c; + mirror::Class* c; if (can_load_classes_) { c = class_linker->FindClass(descriptor, loader); } else { @@ -125,7 +127,8 @@ const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const DCHECK(!Thread::Current()->IsExceptionPending()); } if (IsValidDescriptor(descriptor)) { - RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size()); + RegType* entry = + new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size()); entries_.push_back(entry); return *entry; } else { @@ -137,7 +140,7 @@ const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const } } -const RegType& RegTypeCache::FromClass(Class* klass, bool precise) { +const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) { if (klass->IsPrimitive()) { RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType()); // entries should be sized greater than primitive types @@ -233,7 +236,7 @@ const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocat entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference, descriptor, allocation_pc, entries_.size()); } else { - Class* klass = type.GetClass(); + mirror::Class* klass = type.GetClass(); for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->IsUninitializedReference() && @@ -261,7 +264,7 @@ const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) { } entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size()); } else { - Class* klass = uninit_type.GetClass(); + mirror::Class* klass = uninit_type.GetClass(); for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) { @@ -274,6 +277,18 @@ const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) { return *entry; } +const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return FromCat1Const(std::numeric_limits<jbyte>::min(), false); +} + +const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return FromCat1Const(std::numeric_limits<jshort>::min(), false); +} + +const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return FromCat1Const(std::numeric_limits<jint>::max(), false); +} + const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) { // TODO: implement descriptor version. RegType* entry; @@ -289,7 +304,7 @@ const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) { entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0, entries_.size()); } else { - Class* klass = type.GetClass(); + mirror::Class* klass = type.GetClass(); for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) { @@ -320,7 +335,8 @@ const RegType& RegTypeCache::FromType(RegType::Type type) { } const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) { - RegType::Type wanted_type = precise ? RegType::kRegTypePreciseConst : RegType::kRegTypeImpreciseConst; + RegType::Type wanted_type = + precise ? RegType::kRegTypePreciseConst : RegType::kRegTypeImpreciseConst; for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValue() == value) { @@ -333,7 +349,8 @@ const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) { } const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) { - RegType::Type wanted_type = precise ? RegType::kRegTypePreciseConstLo : RegType::kRegTypeImpreciseConstLo; + RegType::Type wanted_type = + precise ? RegType::kRegTypePreciseConstLo : RegType::kRegTypeImpreciseConstLo; for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueLo() == value) { @@ -346,7 +363,8 @@ const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) { } const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) { - RegType::Type wanted_type = precise ? RegType::kRegTypePreciseConstHi : RegType::kRegTypeImpreciseConstHi; + RegType::Type wanted_type = + precise ? RegType::kRegTypePreciseConstHi : RegType::kRegTypeImpreciseConstHi; for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) { RegType* cur_entry = entries_[i]; if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueHi() == value) { @@ -358,14 +376,14 @@ const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) { return *entry; } -const RegType& RegTypeCache::GetComponentType(const RegType& array, ClassLoader* loader) { +const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) { CHECK(array.IsArrayTypes()); if (array.IsUnresolvedTypes()) { std::string descriptor(array.GetDescriptor()); std::string component(descriptor.substr(1, descriptor.size() - 1)); return FromDescriptor(loader, component.c_str(), false); } else { - Class* klass = array.GetClass()->GetComponentType(); + mirror::Class* klass = array.GetClass()->GetComponentType(); return FromClass(klass, klass->IsFinal()); } } diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h index 54f42fd857..adab18c9bd 100644 --- a/src/verifier/reg_type_cache.h +++ b/src/verifier/reg_type_cache.h @@ -21,7 +21,13 @@ #include "base/stl_util.h" #include "reg_type.h" +#include <vector> + namespace art { +namespace mirror { +class Class; +class ClassLoader; +} // namespace mirror namespace verifier { class RegTypeCache { @@ -41,20 +47,25 @@ class RegTypeCache { return *result; } - const RegType& From(RegType::Type type, ClassLoader* loader, const char* descriptor, bool precise) + const RegType& From(RegType::Type type, mirror::ClassLoader* loader, const char* descriptor, + bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - const RegType& FromClass(Class* klass, bool precise) + const RegType& FromClass(mirror::Class* klass, bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const RegType& FromCat1Const(int32_t value, bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - const RegType& FromCat2ConstLo(int32_t value, bool precise); - const RegType& FromCat2ConstHi(int32_t value, bool precise); - const RegType& FromDescriptor(ClassLoader* loader, const char* descriptor, bool precise) + const RegType& FromCat2ConstLo(int32_t value, bool precise) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& FromCat2ConstHi(int32_t value, bool precise) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const RegType& FromType(RegType::Type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right); - const RegType& FromUnresolvedSuperClass(const RegType& child); + const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& FromUnresolvedSuperClass(const RegType& child) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return FromType(RegType::kRegTypeBoolean); @@ -117,25 +128,22 @@ class RegTypeCache { return FromCat1Const(0, true); } - const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc); + const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Create an uninitialized 'this' argument for the given type. - const RegType& UninitializedThisArgument(const RegType& type); - const RegType& FromUninitialized(const RegType& uninit_type); + const RegType& UninitializedThisArgument(const RegType& type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& FromUninitialized(const RegType& uninit_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Representatives of various constant types. When merging constants we can't infer a type, // (an int may later be used as a float) so we select these representative values meaning future // merges won't know the exact constant value but have some notion of its size. - const RegType& ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return FromCat1Const(std::numeric_limits<jbyte>::min(), false); - } - const RegType& ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return FromCat1Const(std::numeric_limits<jshort>::min(), false); - } - const RegType& IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return FromCat1Const(std::numeric_limits<jint>::max(), false); - } + const RegType& ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const RegType& IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - const RegType& GetComponentType(const RegType& array, ClassLoader* loader) + const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/src/verifier/register_line.h b/src/verifier/register_line.h index c6c19f8ded..8253f516c2 100644 --- a/src/verifier/register_line.h +++ b/src/verifier/register_line.h @@ -23,6 +23,7 @@ #include "dex_instruction.h" #include "reg_type.h" #include "safe_map.h" +#include "UniquePtr.h" namespace art { namespace verifier { @@ -135,7 +136,8 @@ class RegisterLine { * reference type. This is called when an appropriate constructor is invoked -- all copies of * the reference must be marked as initialized. */ - void MarkRefsAsInitialized(const RegType& uninit_type); + void MarkRefsAsInitialized(const RegType& uninit_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /* * Check constraints on constructor return. Specifically, make sure that the "this" argument got @@ -245,10 +247,10 @@ class RegisterLine { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Verify/push monitor onto the monitor stack, locking the value in reg_idx at location insn_idx. - void PushMonitor(uint32_t reg_idx, int32_t insn_idx); + void PushMonitor(uint32_t reg_idx, int32_t insn_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Verify/pop monitor from monitor stack ensuring that we believe the monitor is locked - void PopMonitor(uint32_t reg_idx); + void PopMonitor(uint32_t reg_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Stack of currently held monitors and where they were locked size_t MonitorStackDepth() const { diff --git a/src/well_known_classes.cc b/src/well_known_classes.cc index 9752c749d0..5012f1b9c9 100644 --- a/src/well_known_classes.cc +++ b/src/well_known_classes.cc @@ -19,6 +19,7 @@ #include <stdlib.h> #include "base/logging.h" +#include "mirror/class.h" #include "ScopedLocalRef.h" #include "thread.h" @@ -198,8 +199,8 @@ void WellKnownClasses::LateInit(JNIEnv* env) { java_lang_Runtime_nativeLoad = CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad", "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"); } -Class* WellKnownClasses::ToClass(jclass global_jclass) { - return reinterpret_cast<Class*>(Thread::Current()->DecodeJObject(global_jclass)); +mirror::Class* WellKnownClasses::ToClass(jclass global_jclass) { + return reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(global_jclass)); } } // namespace art diff --git a/src/well_known_classes.h b/src/well_known_classes.h index 10afca91fd..92a207a4c2 100644 --- a/src/well_known_classes.h +++ b/src/well_known_classes.h @@ -21,8 +21,9 @@ #include "jni.h" namespace art { - +namespace mirror { class Class; +} // namespace mirror // Various classes used in JNI. We cache them so we don't have to keep looking // them up. Similar to libcore's JniConstants (except there's no overlap, so @@ -33,7 +34,7 @@ struct WellKnownClasses { static void Init(JNIEnv* env); // Run before native methods are registered. static void LateInit(JNIEnv* env); // Run after native methods are registered. - static Class* ToClass(jclass global_jclass) + static mirror::Class* ToClass(jclass global_jclass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static jclass com_android_dex_Dex; diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc index 60182e2fae..5109b82c8d 100644 --- a/test/ReferenceMap/stack_walk_refmap_jni.cc +++ b/test/ReferenceMap/stack_walk_refmap_jni.cc @@ -19,7 +19,9 @@ #include "UniquePtr.h" #include "class_linker.h" #include "gc_map.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "thread.h" @@ -48,7 +50,7 @@ struct ReferenceMap2Visitor : public StackVisitor { } bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); if (!m || m->IsNative() || m->IsRuntimeMethod() || IsShadowFrame()) { return true; } diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc index dccd69fe0d..a16d89615e 100644 --- a/test/StackWalk/stack_walk_jni.cc +++ b/test/StackWalk/stack_walk_jni.cc @@ -19,7 +19,9 @@ #include "UniquePtr.h" #include "class_linker.h" #include "gc_map.h" -#include "object.h" +#include "mirror/abstract_method.h" +#include "mirror/abstract_method-inl.h" +#include "mirror/object_array-inl.h" #include "object_utils.h" #include "jni.h" #include "scoped_thread_state_change.h" @@ -46,7 +48,7 @@ struct TestReferenceMapVisitor : public StackVisitor { } bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AbstractMethod* m = GetMethod(); + mirror::AbstractMethod* m = GetMethod(); CHECK(m != NULL); LOG(INFO) << "At " << PrettyMethod(m, false); |