diff options
| author | 2014-07-11 14:52:06 +0000 | |
|---|---|---|
| committer | 2014-07-10 20:09:49 +0000 | |
| commit | 3641ac7de8b51c0853eaaa2ba3a3ab7e65a837c5 (patch) | |
| tree | 425daeee0978d1a551ede86422643da09fbe1f43 /runtime/interpreter | |
| parent | eab674a87b32794ae2c5e7d238292e56804de09d (diff) | |
| parent | 4e99b3d8955131f3fc71aa113f0fa71f0092cb6f (diff) | |
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 729444e4f6..2db62f8ead 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 9f04b90c55..5a03601bce 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 cb4868c957..abd4b44d38 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 bdf2a20192..c6356485a9 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()) {  |