diff options
author | Sebastien Hertz <shertz@google.com> | 2014-07-11 14:52:06 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-07-10 20:09:49 +0000 |
commit | 3641ac7de8b51c0853eaaa2ba3a3ab7e65a837c5 (patch) | |
tree | 425daeee0978d1a551ede86422643da09fbe1f43 /runtime/interpreter | |
parent | eab674a87b32794ae2c5e7d238292e56804de09d (diff) | |
parent | 4e99b3d8955131f3fc71aa113f0fa71f0092cb6f (diff) | |
download | art-3641ac7de8b51c0853eaaa2ba3a3ab7e65a837c5.tar.gz art-3641ac7de8b51c0853eaaa2ba3a3ab7e65a837c5.tar.bz2 art-3641ac7de8b51c0853eaaa2ba3a3ab7e65a837c5.zip |
Merge "Add missing class initialization during compilation and tests"
Diffstat (limited to 'runtime/interpreter')
-rw-r--r-- | runtime/interpreter/interpreter.cc | 1 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 78 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_goto_table_impl.cc | 1 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl.cc | 1 |
4 files changed, 55 insertions, 26 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 729444e4f..2db62f8ea 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -356,6 +356,7 @@ static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::Code shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass()); DCHECK(!shadow_frame.GetMethod()->IsAbstract()); DCHECK(!shadow_frame.GetMethod()->IsNative()); + shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); bool transaction_active = Runtime::Current()->IsActiveTransaction(); if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) { diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 9f04b90c5..5a03601bc 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -35,6 +35,7 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst CHECK(self->IsExceptionPending()); return false; } + f->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); Object* obj; if (is_static) { obj = f->GetDeclaringClass(); @@ -210,6 +211,7 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction CHECK(self->IsExceptionPending()); return false; } + f->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); Object* obj; if (is_static) { obj = f->GetDeclaringClass(); @@ -757,40 +759,64 @@ void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count) } } +// Helper function to deal with class loading in an unstarted runtime. +static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className, + Handle<mirror::ClassLoader> class_loader, JValue* result, + const std::string& method_name, bool initialize_class, + bool abort_if_not_found) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + CHECK(className.Get() != nullptr); + std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str())); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + + Class* found = class_linker->FindClass(self, descriptor.c_str(), class_loader); + if (found == nullptr && abort_if_not_found) { + if (!self->IsExceptionPending()) { + AbortTransaction(self, "%s failed in un-started runtime for class: %s", + method_name.c_str(), PrettyDescriptor(descriptor).c_str()); + } + return; + } + if (found != nullptr && initialize_class) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> h_class(hs.NewHandle(found)); + if (!class_linker->EnsureInitialized(h_class, true, true)) { + CHECK(self->IsExceptionPending()); + return; + } + } + result->SetL(found); +} + static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { // In a runtime that's not started we intercept certain methods to avoid complicated dependency // problems in core libraries. std::string name(PrettyMethod(shadow_frame->GetMethod())); - if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)" - || name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") { - // TODO Class#forName should actually call Class::EnsureInitialized always. Support for the - // other variants that take more arguments should also be added. - std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str())); - - // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader(); - Class* found = Runtime::Current()->GetClassLinker()->FindClass( - self, descriptor.c_str(), NullHandle<mirror::ClassLoader>()); - if (found == NULL) { - if (!self->IsExceptionPending()) { - AbortTransaction(self, "Class.forName failed in un-started runtime for class: %s", - PrettyDescriptor(descriptor).c_str()); - } - return; - } - result->SetL(found); + if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") { + // TODO: Support for the other variants that take more arguments should also be added. + mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString(); + StackHandleScope<1> hs(self); + Handle<mirror::String> h_class_name(hs.NewHandle(class_name)); + UnstartedRuntimeFindClass(self, h_class_name, NullHandle<mirror::ClassLoader>(), result, name, + true, true); + } else if (name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") { + mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString(); + StackHandleScope<1> hs(self); + Handle<mirror::String> h_class_name(hs.NewHandle(class_name)); + UnstartedRuntimeFindClass(self, h_class_name, NullHandle<mirror::ClassLoader>(), result, name, + false, true); + } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") { + mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString(); + mirror::ClassLoader* class_loader = + down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset)); + StackHandleScope<2> hs(self); + Handle<mirror::String> h_class_name(hs.NewHandle(class_name)); + Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader)); + UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, name, false, false); } else if (name == "java.lang.Class java.lang.Void.lookupType()") { result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V')); - } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") { - StackHandleScope<1> hs(self); - Handle<ClassLoader> class_loader( - hs.NewHandle(down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset)))); - std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str())); - - Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(), - class_loader); - result->SetL(found); } else if (name == "java.lang.Object java.lang.Class.newInstance()") { Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V"); diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc index cb4868c95..abd4b44d3 100644 --- a/runtime/interpreter/interpreter_goto_table_impl.cc +++ b/runtime/interpreter/interpreter_goto_table_impl.cc @@ -536,6 +536,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* if (UNLIKELY(obj == NULL)) { HANDLE_PENDING_EXCEPTION(); } else { + obj->GetClass()->AssertInitializedOrInitializingInThread(self); // Don't allow finalizable objects to be allocated during a transaction since these can't be // finalized without a started runtime. if (transaction_active && obj->GetClass()->IsFinalizable()) { diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index bdf2a2019..c6356485a 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -449,6 +449,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem if (UNLIKELY(obj == NULL)) { HANDLE_PENDING_EXCEPTION(); } else { + obj->GetClass()->AssertInitializedOrInitializingInThread(self); // Don't allow finalizable objects to be allocated during a transaction since these can't // be finalized without a started runtime. if (transaction_active && obj->GetClass()->IsFinalizable()) { |