diff options
author | Andreas Gampe <agampe@google.com> | 2015-03-09 12:57:41 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-03-11 09:27:03 -0700 |
commit | 2969bcdcd80624e4a4fef696b54c2c76b44b6853 (patch) | |
tree | a097d139d5525ec2af6682f3e37bda94dead8cc9 /runtime/interpreter/interpreter_common.cc | |
parent | f719fdd20e6282f3579cb99529bb65e852612647 (diff) | |
download | art-2969bcdcd80624e4a4fef696b54c2c76b44b6853.zip art-2969bcdcd80624e4a4fef696b54c2c76b44b6853.tar.gz art-2969bcdcd80624e4a4fef696b54c2c76b44b6853.tar.bz2 |
ART: Refactor unstarted runtime
Refactor and clean up unstarted runtime.
Bug: 19542228
Change-Id: Ib3e4b3517e06e8242d4fed32ca59419fef553a47
Diffstat (limited to 'runtime/interpreter/interpreter_common.cc')
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 278 |
1 files changed, 1 insertions, 277 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 2a9c0d4..26ab602 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -19,6 +19,7 @@ #include <cmath> #include "mirror/array-inl.h" +#include "unstarted_runtime.h" namespace art { namespace interpreter { @@ -450,10 +451,6 @@ void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) UNREACHABLE(); } -static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item, - ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame. static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame, size_t dest_reg, size_t src_reg) @@ -733,279 +730,6 @@ 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()).c_str()); - } - return; - } - if (found != nullptr && initialize_class) { - StackHandleScope<1> hs(self); - Handle<mirror::Class> h_class(hs.NewHandle(found)); - if (!class_linker->EnsureInitialized(self, h_class, true, true)) { - CHECK(self->IsExceptionPending()); - return; - } - } - result->SetL(found); -} - -// Common helper for class-loading cutouts in an unstarted runtime. We call Runtime methods that -// rely on Java code to wrap errors in the correct exception class (i.e., NoClassDefFoundError into -// ClassNotFoundException), so need to do the same. The only exception is if the exception is -// actually InternalError. This must not be wrapped, as it signals an initialization abort. -static void CheckExceptionGenerateClassNotFound(Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (self->IsExceptionPending()) { - // If it is not an InternalError, wrap it. - std::string type(PrettyTypeOf(self->GetException())); - if (type != "java.lang.InternalError") { - self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;", - "ClassNotFoundException"); - } - } -} - -static void UnstartedRuntimeInvoke(Thread* self, 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)") { - 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, false); - CheckExceptionGenerateClassNotFound(self); - } else if (name == "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)") { - mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString(); - bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0; - mirror::ClassLoader* class_loader = - down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2)); - 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, initialize_class, - false); - CheckExceptionGenerateClassNotFound(self); - } else if (name == "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)") { - mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString(); - bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0; - mirror::ClassLoader* class_loader = - down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2)); - 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, initialize_class, - false); - CheckExceptionGenerateClassNotFound(self); - } 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); - // This might have an error pending. But semantics are to just return null. - if (self->IsExceptionPending()) { - // If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound. - std::string type(PrettyTypeOf(self->GetException())); - if (type != "java.lang.InternalError") { - self->ClearException(); - } - } - } else if (name == "java.lang.Class java.lang.Void.lookupType()") { - result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V')); - } else if (name == "java.lang.Object java.lang.Class.newInstance()") { - StackHandleScope<3> hs(self); // Class, constructor, object. - Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); - Handle<Class> h_klass(hs.NewHandle(klass)); - // There are two situations in which we'll abort this run. - // 1) If the class isn't yet initialized and initialization fails. - // 2) If we can't find the default constructor. We'll postpone the exception to runtime. - // Note that 2) could likely be handled here, but for safety abort the transaction. - bool ok = false; - if (Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_klass, true, true)) { - Handle<ArtMethod> h_cons(hs.NewHandle(h_klass->FindDeclaredDirectMethod("<init>", "()V"))); - if (h_cons.Get() != nullptr) { - Handle<Object> h_obj(hs.NewHandle(klass->AllocObject(self))); - CHECK(h_obj.Get() != nullptr); // We don't expect OOM at compile-time. - EnterInterpreterFromInvoke(self, h_cons.Get(), h_obj.Get(), nullptr, nullptr); - if (!self->IsExceptionPending()) { - result->SetL(h_obj.Get()); - ok = true; - } - } else { - self->ThrowNewExceptionF("Ljava/lang/InternalError;", - "Could not find default constructor for '%s'", - PrettyClass(h_klass.Get()).c_str()); - } - } - if (!ok) { - std::string error_msg = StringPrintf("Failed in Class.newInstance for '%s' with %s", - PrettyClass(h_klass.Get()).c_str(), - PrettyTypeOf(self->GetException()).c_str()); - self->ThrowNewWrappedException("Ljava/lang/InternalError;", error_msg.c_str()); - } - } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") { - // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail - // going the reflective Dex way. - Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); - String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString(); - ArtField* found = NULL; - ObjectArray<ArtField>* fields = klass->GetIFields(); - for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) { - ArtField* f = fields->Get(i); - if (name2->Equals(f->GetName())) { - found = f; - } - } - if (found == NULL) { - fields = klass->GetSFields(); - for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) { - ArtField* f = fields->Get(i); - if (name2->Equals(f->GetName())) { - found = f; - } - } - } - CHECK(found != NULL) - << "Failed to find field in Class.getDeclaredField in un-started runtime. name=" - << name2->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass); - // TODO: getDeclaredField calls GetType once the field is found to ensure a - // NoClassDefFoundError is thrown if the field's type cannot be resolved. - Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass(); - StackHandleScope<1> hs(self); - Handle<Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self))); - CHECK(field.Get() != NULL); - ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V"); - uint32_t args[1]; - args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue(); - EnterInterpreterFromInvoke(self, c, field.Get(), args, NULL); - result->SetL(field.Get()); - } else if (name == "int java.lang.Object.hashCode()") { - Object* obj = shadow_frame->GetVRegReference(arg_offset); - result->SetI(obj->IdentityHashCode()); - } else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") { - mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod(); - result->SetL(method->GetNameAsString(self)); - } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" || - name == "void java.lang.System.arraycopy(char[], int, char[], int, int)" || - name == "void java.lang.System.arraycopy(int[], int, int[], int, int)") { - // Special case array copying without initializing System. - Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType(); - jint srcPos = shadow_frame->GetVReg(arg_offset + 1); - jint dstPos = shadow_frame->GetVReg(arg_offset + 3); - jint length = shadow_frame->GetVReg(arg_offset + 4); - if (!ctype->IsPrimitive()) { - ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>(); - ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>(); - for (jint i = 0; i < length; ++i) { - dst->Set(dstPos + i, src->Get(srcPos + i)); - } - } else if (ctype->IsPrimitiveChar()) { - CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray(); - CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray(); - for (jint i = 0; i < length; ++i) { - dst->Set(dstPos + i, src->Get(srcPos + i)); - } - } else if (ctype->IsPrimitiveInt()) { - IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray(); - IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray(); - for (jint i = 0; i < length; ++i) { - dst->Set(dstPos + i, src->Get(srcPos + i)); - } - } else { - self->ThrowNewExceptionF("Ljava/lang/InternalError;", - "Unimplemented System.arraycopy for type '%s'", - PrettyDescriptor(ctype).c_str()); - } - } else if (name == "long java.lang.Double.doubleToRawLongBits(double)") { - double in = shadow_frame->GetVRegDouble(arg_offset); - result->SetJ(bit_cast<int64_t>(in)); - } else if (name == "double java.lang.Math.ceil(double)") { - double in = shadow_frame->GetVRegDouble(arg_offset); - double out; - // Special cases: - // 1) NaN, infinity, +0, -0 -> out := in. All are guaranteed by cmath. - // -1 < in < 0 -> out := -0. - if (-1.0 < in && in < 0) { - out = -0.0; - } else { - out = ceil(in); - } - result->SetD(out); - } else if (name == "java.lang.Object java.lang.ThreadLocal.get()") { - std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod())); - bool ok = false; - if (caller == "java.lang.String java.lang.IntegralToString.convertInt(java.lang.AbstractStringBuilder, int)") { - // Allocate non-threadlocal buffer. - result->SetL(mirror::CharArray::Alloc(self, 11)); - ok = true; - } else if (caller == "java.lang.RealToString java.lang.RealToString.getInstance()") { - // Note: RealToString is implemented and used in a different fashion than IntegralToString. - // Conversion is done over an actual object of RealToString (the conversion method is an - // instance method). This means it is not as clear whether it is correct to return a new - // object each time. The caller needs to be inspected by hand to see whether it (incorrectly) - // stores the object for later use. - // See also b/19548084 for a possible rewrite and bringing it in line with IntegralToString. - if (shadow_frame->GetLink()->GetLink() != nullptr) { - std::string caller2(PrettyMethod(shadow_frame->GetLink()->GetLink()->GetMethod())); - if (caller2 == "java.lang.String java.lang.Double.toString(double)") { - // Allocate new object. - StackHandleScope<2> hs(self); - Handle<Class> h_real_to_string_class(hs.NewHandle( - shadow_frame->GetLink()->GetMethod()->GetDeclaringClass())); - Handle<Object> h_real_to_string_obj(hs.NewHandle( - h_real_to_string_class->AllocObject(self))); - if (h_real_to_string_obj.Get() != nullptr) { - mirror::ArtMethod* init_method = - h_real_to_string_class->FindDirectMethod("<init>", "()V"); - if (init_method == nullptr) { - h_real_to_string_class->DumpClass(LOG(FATAL), mirror::Class::kDumpClassFullDetail); - } else { - JValue invoke_result; - EnterInterpreterFromInvoke(self, init_method, h_real_to_string_obj.Get(), nullptr, - nullptr); - if (!self->IsExceptionPending()) { - result->SetL(h_real_to_string_obj.Get()); - ok = true; - } - } - } - - if (!ok) { - // We'll abort, so clear exception. - self->ClearException(); - } - } - } - } - - if (!ok) { - self->ThrowNewException("Ljava/lang/InternalError;", "Unimplemented ThreadLocal.get"); - } - } else { - // Not special, continue with regular interpreter execution. - artInterpreterToInterpreterBridge(self, code_item, shadow_frame, result); - } -} - // Explicit DoCall template function declarations. #define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \ template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \ |