diff options
author | Elliott Hughes <enh@google.com> | 2011-08-25 18:09:09 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2011-08-25 18:48:47 -0700 |
commit | c1674ed06662420213441ff2b818f2f71f9098dc (patch) | |
tree | 2799982a5059feab2a680ce5d91c276e5852983c | |
parent | bafc342a37e423a19ac05f14800006ea9d67a941 (diff) | |
download | art-c1674ed06662420213441ff2b818f2f71f9098dc.zip art-c1674ed06662420213441ff2b818f2f71f9098dc.tar.gz art-c1674ed06662420213441ff2b818f2f71f9098dc.tar.bz2 |
Make valgrind happier and stop us leaking so much we can can't run the tests on a device.
Change-Id: Id8f45dde788fd84c10b0b5807b2d12eae529ba5e
-rw-r--r-- | src/assembler.cc | 1 | ||||
-rw-r--r-- | src/class_linker.cc | 21 | ||||
-rw-r--r-- | src/image_writer.cc | 2 | ||||
-rw-r--r-- | src/jni_internal.cc | 3 | ||||
-rw-r--r-- | src/jni_internal.h | 1 | ||||
-rw-r--r-- | src/main.cc | 50 | ||||
-rw-r--r-- | src/object.cc | 1 | ||||
-rw-r--r-- | src/object.h | 2 | ||||
-rw-r--r-- | src/reference_table.cc | 3 | ||||
-rw-r--r-- | src/reference_table.h | 1 | ||||
-rw-r--r-- | src/runtime.cc | 30 | ||||
-rw-r--r-- | src/runtime.h | 3 | ||||
-rw-r--r-- | src/thread.cc | 39 | ||||
-rw-r--r-- | src/thread.h | 10 |
14 files changed, 105 insertions, 62 deletions
diff --git a/src/assembler.cc b/src/assembler.cc index 193d73f..9e67f12 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -67,6 +67,7 @@ AssemblerBuffer::AssemblerBuffer() { AssemblerBuffer::~AssemblerBuffer() { + delete[] contents_; } diff --git a/src/class_linker.cc b/src/class_linker.cc index f37df3f..2f1a5d7 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -84,10 +84,13 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { // mark as non-primitive for object_array_class java_lang_Object->primitive_type_ = Class::kPrimNot; - // object_array_class is for root_classes to provide the storage for these classes + // Object[] is for DexCache and int[] is for various Class members. Class* object_array_class = AllocClass(java_lang_Class, sizeof(Class)); CHECK(object_array_class != NULL); object_array_class->component_type_ = java_lang_Object; + Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class)); + CHECK(int_array_class != NULL); + IntArray::SetArrayClass(int_array_class); // String and char[] are necessary so that FindClass can assign names to members Class* java_lang_String = AllocClass(java_lang_Class, sizeof(StringClass)); @@ -106,6 +109,7 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { object_array_class->descriptor_ = String::AllocFromModifiedUtf8("[Ljava/lang/Object;"); java_lang_String->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/String;"); char_array_class->descriptor_ = String::AllocFromModifiedUtf8("[C"); + int_array_class->descriptor_ = String::AllocFromModifiedUtf8("[I"); // Field and Method are necessary so that FindClass can link members Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass)); @@ -126,6 +130,7 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { SetClassRoot(kObjectArrayClass, object_array_class); SetClassRoot(kJavaLangString, java_lang_String); SetClassRoot(kCharArrayClass, char_array_class); + SetClassRoot(kIntArrayClass, int_array_class); SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field); SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method); // now that these are registered, we can use AllocClass() and AllocObjectArray @@ -218,9 +223,11 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V")); // now we can use FindSystemClass for anything, including for "[C" - // run char[], int[] and long[] through FindClass to complete initialization + // run char[] and int[] through FindClass to complete initialization Class* found_char_array_class = FindSystemClass("[C"); CHECK_EQ(char_array_class, found_char_array_class); + Class* found_int_array_class = FindSystemClass("[I"); + CHECK_EQ(int_array_class, found_int_array_class); // Initialize all the other primitive array types for PrimitiveArray::Alloc. // These are easy because everything we need has already been set up. @@ -228,14 +235,12 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { SetClassRoot(kByteArrayClass, FindSystemClass("[B")); SetClassRoot(kDoubleArrayClass, FindSystemClass("[D")); SetClassRoot(kFloatArrayClass, FindSystemClass("[F")); - SetClassRoot(kIntArrayClass, FindSystemClass("[I")); SetClassRoot(kLongArrayClass, FindSystemClass("[J")); SetClassRoot(kShortArrayClass, FindSystemClass("[S")); BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); - IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); @@ -702,10 +707,10 @@ void ClassLinker::LoadInterfaces(const DexFile& dex_file, DCHECK(klass->interfaces_ == NULL); klass->interfaces_ = AllocObjectArray<Class>(list->Size()); DCHECK(klass->interfaces_type_idx_ == NULL); - klass->interfaces_type_idx_ = new uint32_t[list->Size()]; + klass->interfaces_type_idx_ = IntArray::Alloc(list->Size()); for (size_t i = 0; i < list->Size(); ++i) { const DexFile::TypeItem& type_item = list->GetTypeItem(i); - klass->interfaces_type_idx_[i] = type_item.type_idx_; + klass->interfaces_type_idx_->Set(i, type_item.type_idx_); } } } @@ -902,6 +907,8 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor, new_class = GetClassRoot(kObjectArrayClass); } else if (descriptor == "[C") { new_class = GetClassRoot(kCharArrayClass); + } else if (descriptor == "[I") { + new_class = GetClassRoot(kIntArrayClass); } } if (new_class == NULL) { @@ -1343,7 +1350,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file) } if (klass->NumInterfaces() > 0) { for (size_t i = 0; i < klass->NumInterfaces(); ++i) { - uint32_t type_idx = klass->interfaces_type_idx_[i]; + uint32_t type_idx = klass->interfaces_type_idx_->Get(i); klass->SetInterface(i, ResolveType(dex_file, type_idx, klass)); if (klass->GetInterface(i) == NULL) { LG << "Failed to resolve interface"; diff --git a/src/image_writer.cc b/src/image_writer.cc index 3998140..f31586d 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -163,9 +163,11 @@ void ImageWriter::FixupClass(const Class* orig, Class* copy) { copy->virtual_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->virtual_methods_)); copy->vtable_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->vtable_)); // TODO: convert iftable_ to heap allocated storage + // TODO: convert ifvi_pool_ to heap allocated storage copy->ifields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->ifields_)); // TODO: convert source_file_ to heap allocated storage copy->sfields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->sfields_)); + copy->interfaces_type_idx_ = down_cast<IntArray*>(GetImageAddress(orig->interfaces_type_idx_)); FixupStaticFields(orig, copy); } diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 1746cc3..89519c4 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -2580,6 +2580,9 @@ JNIEnvExt::JNIEnvExt(Thread* self, JavaVMExt* vm) functions = &gNativeInterface; } +JNIEnvExt::~JNIEnvExt() { +} + // JNI Invocation interface. extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) { diff --git a/src/jni_internal.h b/src/jni_internal.h index fec84ea..c8a5a39 100644 --- a/src/jni_internal.h +++ b/src/jni_internal.h @@ -61,6 +61,7 @@ struct JavaVMExt : public JavaVM { struct JNIEnvExt : public JNIEnv { JNIEnvExt(Thread* self, JavaVMExt* vm); + ~JNIEnvExt(); Thread* self; JavaVMExt* vm; diff --git a/src/main.cc b/src/main.cc index 0330d0d..2056b0b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -11,25 +11,7 @@ #include "toStringArray.h" #include "ScopedLocalRef.h" -// TODO: move this into the runtime. -static void BlockSigpipe() { - sigset_t sigset; - if (sigemptyset(&sigset) == -1) { - PLOG(ERROR) << "sigemptyset failed"; - return; - } - if (sigaddset(&sigset, SIGPIPE) == -1) { - PLOG(ERROR) << "sigaddset failed"; - return; - } - if (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1) { - PLOG(ERROR) << "sigprocmask failed"; - } -} - // Determine whether or not the specified method is public. -// -// Returns JNI_TRUE on success, JNI_FALSE on failure. static bool IsMethodPublic(JNIEnv* env, jclass clazz, jmethodID method_id) { ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(clazz, method_id, JNI_FALSE)); @@ -54,7 +36,7 @@ static bool IsMethodPublic(JNIEnv* env, jclass clazz, jmethodID method_id) { } static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC #if 0 // CallIntMethod not yet implemented - int modifiers = env->CallIntMethod(method.get(), get_modifiers); + int modifiers = env->CallIntMethod(reflected.get(), get_modifiers); #else int modifiers = PUBLIC; UNIMPLEMENTED(WARNING) << "assuming main is public..."; @@ -65,13 +47,13 @@ static bool IsMethodPublic(JNIEnv* env, jclass clazz, jmethodID method_id) { return true; } -static bool InvokeMain(JNIEnv* env, int argc, char** argv) { +static void InvokeMain(JNIEnv* env, int argc, char** argv) { // We want to call main() with a String array with our arguments in // it. Create an array and populate it. Note argv[0] is not // included. ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1)); if (args.get() == NULL) { - return false; + return; } // Find [class].main(String[]). @@ -83,7 +65,7 @@ static bool InvokeMain(JNIEnv* env, int argc, char** argv) { ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str())); if (klass.get() == NULL) { fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str()); - return false; + return; } jmethodID method = env->GetStaticMethodID(klass.get(), @@ -92,24 +74,18 @@ static bool InvokeMain(JNIEnv* env, int argc, char** argv) { if (method == NULL) { fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str()); - return false; + return; } // Make sure the method is public. JNI doesn't prevent us from // calling a private method, so we have to check it explicitly. if (!IsMethodPublic(env, klass.get(), method)) { fprintf(stderr, "Sorry, main() is not public\n"); - return false; + return; } // Invoke main(). - env->CallStaticVoidMethod(klass.get(), method, args.get()); - if (env->ExceptionCheck()) { - return false; - } else { - return true; - } } // Parse arguments. Most of it just gets passed through to the VM. @@ -173,8 +149,6 @@ int main(int argc, char** argv) { init_args.nOptions = curr_opt; init_args.ignoreUnrecognized = JNI_FALSE; - BlockSigpipe(); - // Start VM. The current thread becomes the main thread of the VM. JavaVM* vm = NULL; JNIEnv* env = NULL; @@ -183,17 +157,21 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - bool success = InvokeMain(env, argc - arg_idx, &argv[arg_idx]); + InvokeMain(env, argc - arg_idx, &argv[arg_idx]); + int rc = env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS; + if (rc == EXIT_FAILURE) { + env->ExceptionDescribe(); + } if (vm->DetachCurrentThread() != JNI_OK) { fprintf(stderr, "Warning: unable to detach main thread\n"); - success = false; + rc = EXIT_FAILURE; } if (vm->DestroyJavaVM() != 0) { fprintf(stderr, "Warning: VM did not shut down cleanly\n"); - success = false; + rc = EXIT_FAILURE; } - return success ? EXIT_SUCCESS : EXIT_FAILURE; + return rc; } diff --git a/src/object.cc b/src/object.cc index bb60dc1..d06c3e3 100644 --- a/src/object.cc +++ b/src/object.cc @@ -538,6 +538,7 @@ Field* Class::FindStaticField(const StringPiece& name, const StringPiece& descri template<typename T> PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) { + DCHECK(array_class_ != NULL); Array* raw_array = Array::Alloc(array_class_, length, sizeof(T)); return down_cast<PrimitiveArray<T>*>(raw_array); } diff --git a/src/object.h b/src/object.h index f3cd0fd..2657872 100644 --- a/src/object.h +++ b/src/object.h @@ -1276,7 +1276,7 @@ class Class : public Object { // array of interfaces this class implements directly ObjectArray<Class>* interfaces_; - uint32_t* interfaces_type_idx_; + IntArray* interfaces_type_idx_; // static, private, and <init> methods ObjectArray<Method>* direct_methods_; diff --git a/src/reference_table.cc b/src/reference_table.cc index b5c988a..ebdb7bc 100644 --- a/src/reference_table.cc +++ b/src/reference_table.cc @@ -29,6 +29,9 @@ ReferenceTable::ReferenceTable(const char* name, entries_.reserve(initial_size); } +ReferenceTable::~ReferenceTable() { +} + void ReferenceTable::Add(const Object* obj) { DCHECK(obj != NULL); if (entries_.size() == max_size_) { diff --git a/src/reference_table.h b/src/reference_table.h index 15a2e11..13317ea 100644 --- a/src/reference_table.h +++ b/src/reference_table.h @@ -33,6 +33,7 @@ class Object; class ReferenceTable { public: ReferenceTable(const char* name, size_t initial_size, size_t max_size); + ~ReferenceTable(); void Add(const Object* obj); diff --git a/src/runtime.cc b/src/runtime.cc index 30395e1..80914db 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -24,6 +24,7 @@ Runtime::~Runtime() { Heap::Destroy(); delete thread_list_; delete java_vm_; + Thread::Shutdown(); // TODO: acquire a static mutex on Runtime to avoid racing. CHECK(instance_ == NULL || instance_ == this); instance_ = NULL; @@ -324,7 +325,7 @@ Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) { } bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { - CHECK_EQ(kPageSize, sysconf(_SC_PAGE_SIZE)); + CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); scoped_ptr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized)); if (options == NULL) { @@ -343,10 +344,12 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { return false; } + BlockSignals(); + bool verbose_jni = options->verbose_.find("jni") != options->verbose_.end(); java_vm_ = new JavaVMExt(this, options->check_jni_, verbose_jni); - if (!Thread::Init()) { + if (!Thread::Startup()) { return false; } Thread* current_thread = Thread::Attach(this); @@ -357,6 +360,25 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { return true; } +void Runtime::BlockSignals() { + sigset_t sigset; + if (sigemptyset(&sigset) == -1) { + PLOG(FATAL) << "sigemptyset failed"; + } + if (sigaddset(&sigset, SIGPIPE) == -1) { + PLOG(ERROR) << "sigaddset SIGPIPE failed"; + } + // SIGQUIT is used to dump the runtime's state (including stack traces). + if (sigaddset(&sigset, SIGQUIT) == -1) { + PLOG(ERROR) << "sigaddset SIGQUIT failed"; + } + // SIGUSR1 is used to initiate a heap dump. + if (sigaddset(&sigset, SIGUSR1) == -1) { + PLOG(ERROR) << "sigaddset SIGUSR1 failed"; + } + CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0); +} + bool Runtime::AttachCurrentThread(const char* name, JNIEnv** penv, bool as_daemon) { if (as_daemon) { UNIMPLEMENTED(WARNING) << "TODO: do something different for daemon threads"; @@ -365,7 +387,9 @@ bool Runtime::AttachCurrentThread(const char* name, JNIEnv** penv, bool as_daemo } bool Runtime::DetachCurrentThread() { - UNIMPLEMENTED(WARNING); + Thread* self = Thread::Current(); + thread_list_->Unregister(self); + delete self; return true; } diff --git a/src/runtime.h b/src/runtime.h index 323c6c8..b6873e3 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -95,7 +95,8 @@ class Runtime { Runtime() : stack_size_(0), thread_list_(NULL), class_linker_(NULL) {} - // Initializes a new uninitialized runtime. + void BlockSignals(); + bool Init(const Options& options, bool ignore_unrecognized); // The default stack size for managed threads created by the runtime. diff --git a/src/thread.cc b/src/thread.cc index ef8501a..40aaa7d 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -172,7 +172,7 @@ Thread* Thread::Attach(const Runtime* runtime) { errno = pthread_setspecific(Thread::pthread_key_self_, thread); if (errno != 0) { - PLOG(FATAL) << "pthread_setspecific failed"; + PLOG(FATAL) << "pthread_setspecific failed"; } thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM()); @@ -184,9 +184,10 @@ static void ThreadExitCheck(void* arg) { LG << "Thread exit check"; } -bool Thread::Init() { +bool Thread::Startup() { // Allocate a TLS slot. - if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) { + errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck); + if (errno != 0) { PLOG(WARNING) << "pthread_key_create failed"; return false; } @@ -202,6 +203,17 @@ bool Thread::Init() { return true; } +void Thread::Shutdown() { + errno = pthread_key_delete(Thread::pthread_key_self_); + if (errno != 0) { + PLOG(WARNING) << "pthread_key_delete failed"; + } +} + +Thread::~Thread() { + delete jni_env_; +} + size_t Thread::NumSirtReferences() { size_t count = 0; for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { @@ -404,26 +416,33 @@ ThreadList::ThreadList() { } ThreadList::~ThreadList() { - // Make sure that all threads have exited and unregistered when we + if (Contains(Thread::Current())) { + Runtime::Current()->DetachCurrentThread(); + } + + // All threads should have exited and unregistered when we // reach this point. This means that all daemon threads had been // shutdown cleanly. - CHECK_LE(list_.size(), 1U); - // TODO: wait for all other threads to unregister - CHECK(list_.size() == 0 || list_.front() == Thread::Current()); - // TODO: detach the current thread + // TODO: dump ThreadList if non-empty. + CHECK_EQ(list_.size(), 0U); + delete lock_; lock_ = NULL; } +bool ThreadList::Contains(Thread* thread) { + return find(list_.begin(), list_.end(), thread) != list_.end(); +} + void ThreadList::Register(Thread* thread) { MutexLock mu(lock_); - CHECK(find(list_.begin(), list_.end(), thread) == list_.end()); + CHECK(!Contains(thread)); list_.push_front(thread); } void ThreadList::Unregister(Thread* thread) { MutexLock mu(lock_); - CHECK(find(list_.begin(), list_.end(), thread) != list_.end()); + CHECK(Contains(thread)); list_.remove(thread); } diff --git a/src/thread.h b/src/thread.h index 7609b40..ac1d7e3 100644 --- a/src/thread.h +++ b/src/thread.h @@ -293,7 +293,8 @@ class Thread { void Resume(); - static bool Init(); + static bool Startup(); + static void Shutdown(); State GetState() const { return state_; @@ -398,9 +399,8 @@ class Thread { InitFunctionPointers(); } - ~Thread() { - delete jni_env_; - } + ~Thread(); + friend class Runtime; // For ~Thread. void InitCpu(); void InitFunctionPointers(); @@ -489,6 +489,8 @@ class ThreadList { void Unregister(Thread* thread); + bool Contains(Thread* thread); + void Lock() { lock_->Lock(); } |