diff options
author | Ian Rogers <irogers@google.com> | 2014-05-02 17:17:18 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-05-02 23:30:03 -0700 |
commit | 5d27fafdf03f259e92eaee9f6319b9349cc8d62e (patch) | |
tree | 53afb1174be2ae235e41c5ac9eeb1e8d67e3c4e1 /runtime | |
parent | a54c22c0041306f6881694f4c305e655b10e37be (diff) | |
download | android_art-5d27fafdf03f259e92eaee9f6319b9349cc8d62e.tar.gz android_art-5d27fafdf03f259e92eaee9f6319b9349cc8d62e.tar.bz2 android_art-5d27fafdf03f259e92eaee9f6319b9349cc8d62e.zip |
Allow ArtMethod::Invoke in unstarted runtimes.
Change-Id: I0141f4daef4751589d03d27484eb65c811b14f27
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 8 | ||||
-rw-r--r-- | runtime/interpreter/interpreter.cc | 29 | ||||
-rw-r--r-- | runtime/jni_internal_test.cc | 6 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 8 |
4 files changed, 29 insertions, 22 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 703229c44b..db46224c96 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3215,12 +3215,8 @@ bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_ mirror::ArtMethod* clinit = klass->FindClassInitializer(); if (clinit != NULL) { CHECK(can_init_statics); - if (LIKELY(Runtime::Current()->IsStarted())) { - JValue result; - clinit->Invoke(self, NULL, 0, &result, "V"); - } else { - art::interpreter::EnterInterpreterFromInvoke(self, clinit, NULL, NULL, NULL); - } + JValue result; + clinit->Invoke(self, NULL, 0, &result, "V"); } uint64_t t1 = NanoTime(); diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 1e1a8c19a3..7232e54944 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -27,10 +27,6 @@ namespace interpreter { static void UnstartedRuntimeJni(Thread* self, ArtMethod* method, Object* receiver, uint32_t* args, JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(Runtime::Current()->IsActiveTransaction()) << "Calling native method " - << PrettyMethod(method) - << " in unstarted runtime should only happen" - << " in a transaction"; std::string name(PrettyMethod(method)); if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") { result->SetL(NULL); @@ -71,7 +67,11 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method, result->SetL(Array::CreateMultiArray(self, sirt_class, sirt_dimensions)); } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") { ScopedObjectAccessUnchecked soa(self); - result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<true>(soa))); + if (Runtime::Current()->IsActiveTransaction()) { + result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<true>(soa))); + } else { + result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<false>(soa))); + } } else if (name == "int java.lang.System.identityHashCode(java.lang.Object)") { mirror::Object* obj = reinterpret_cast<Object*>(args[0]); result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0); @@ -82,13 +82,22 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method, jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1]; jint expectedValue = args[3]; jint newValue = args[4]; - bool success = obj->CasField32<true>(MemberOffset(offset), expectedValue, newValue); + bool success; + if (Runtime::Current()->IsActiveTransaction()) { + success = obj->CasField32<true>(MemberOffset(offset), expectedValue, newValue); + } else { + success = obj->CasField32<false>(MemberOffset(offset), expectedValue, newValue); + } result->SetZ(success ? JNI_TRUE : JNI_FALSE); } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") { Object* obj = reinterpret_cast<Object*>(args[0]); jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1]; Object* newValue = reinterpret_cast<Object*>(args[3]); - obj->SetFieldObject<true>(MemberOffset(offset), newValue); + if (Runtime::Current()->IsActiveTransaction()) { + obj->SetFieldObject<true>(MemberOffset(offset), newValue); + } else { + obj->SetFieldObject<false>(MemberOffset(offset), newValue); + } } else if (name == "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)") { mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass(); Primitive::Type primitive_type = component->GetPrimitiveType(); @@ -97,9 +106,13 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method, mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass(); Primitive::Type primitive_type = component->GetPrimitiveType(); result->SetI(Primitive::ComponentSize(primitive_type)); - } else { + } else if (Runtime::Current()->IsActiveTransaction()) { AbortTransaction(self, "Attempt to invoke native method in non-started runtime: %s", name.c_str()); + + } else { + LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted " + "non-transactional runtime"; } } diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 071b658fb9..14fc25c302 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -322,11 +322,7 @@ TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) { ASSERT_TRUE(mid2 != NULL); // Make sure we can actually use it. jstring s = env_->NewStringUTF("poop"); - // TODO: this should return 4, but the runtime skips the method - // invoke because the runtime isn't started. In the future it would - // be nice to use interpretter for things like this. This still does - // validate that we have a sane jmethodID value. - ASSERT_EQ(0, env_->CallIntMethod(s, mid2)); + ASSERT_EQ(4, env_->CallIntMethod(s, mid2)); } void BogusMethod() { diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 7453d4d3fe..4275f25b05 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -287,9 +287,11 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* Runtime* runtime = Runtime::Current(); // Call the invoke stub, passing everything as arguments. if (UNLIKELY(!runtime->IsStarted())) { - LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started"; - if (result != NULL) { - result->SetJ(0); + if (IsStatic()) { + art::interpreter::EnterInterpreterFromInvoke(self, this, nullptr, args, result); + } else { + Object* receiver = reinterpret_cast<StackReference<Object>*>(&args[0])->AsMirrorPtr(); + art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args + 1, result); } } else { const bool kLogInvocationStartAndReturn = false; |