summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_common.cc
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-03-09 12:57:41 -0700
committerAndreas Gampe <agampe@google.com>2015-03-11 09:27:03 -0700
commit2969bcdcd80624e4a4fef696b54c2c76b44b6853 (patch)
treea097d139d5525ec2af6682f3e37bda94dead8cc9 /runtime/interpreter/interpreter_common.cc
parentf719fdd20e6282f3579cb99529bb65e852612647 (diff)
downloadart-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.cc278
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_) \