diff options
| -rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 62 | ||||
| -rw-r--r-- | runtime/interpreter/unstarted_runtime_list.h | 5 | ||||
| -rw-r--r-- | runtime/interpreter/unstarted_runtime_test.cc | 60 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 11 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 3 | ||||
| -rw-r--r-- | runtime/native/java_lang_Class.cc | 9 |
6 files changed, 142 insertions, 8 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 5de0863d15..1f473e404c 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -44,6 +44,7 @@ #include "mirror/object_array-inl.h" #include "mirror/string-inl.h" #include "nth_caller_visitor.h" +#include "reflection.h" #include "thread.h" #include "transaction.h" #include "well_known_classes.h" @@ -352,6 +353,15 @@ void UnstartedRuntime::UnstartedClassGetEnclosingClass( result->SetL(klass->GetDexFile().GetEnclosingClass(klass)); } +void UnstartedRuntime::UnstartedClassGetInnerClassFlags( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> klass(hs.NewHandle( + reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset)))); + const int32_t default_value = shadow_frame->GetVReg(arg_offset + 1); + result->SetI(mirror::Class::GetInnerClassFlags(klass, default_value)); +} + static std::unique_ptr<MemMap> FindAndExtractEntry(const std::string& jar_file, const char* entry_name, size_t* size, @@ -824,6 +834,22 @@ void UnstartedRuntime::UnstartedMathFloor( result->SetD(floor(shadow_frame->GetVRegDouble(arg_offset))); } +void UnstartedRuntime::UnstartedMathSin( + Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + result->SetD(sin(shadow_frame->GetVRegDouble(arg_offset))); +} + +void UnstartedRuntime::UnstartedMathCos( + Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + result->SetD(cos(shadow_frame->GetVRegDouble(arg_offset))); +} + +void UnstartedRuntime::UnstartedMathPow( + Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + result->SetD(pow(shadow_frame->GetVRegDouble(arg_offset), + shadow_frame->GetVRegDouble(arg_offset + 2))); +} + void UnstartedRuntime::UnstartedObjectHashCode( Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset); @@ -1357,6 +1383,36 @@ void UnstartedRuntime::UnstartedLongParseLong( result->SetJ(l); } +void UnstartedRuntime::UnstartedMethodInvoke( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) + SHARED_REQUIRES(Locks::mutator_lock_) { + JNIEnvExt* env = self->GetJniEnv(); + ScopedObjectAccessUnchecked soa(self); + + mirror::Object* java_method_obj = shadow_frame->GetVRegReference(arg_offset); + ScopedLocalRef<jobject> java_method(env, + java_method_obj == nullptr ? nullptr :env->AddLocalReference<jobject>(java_method_obj)); + + mirror::Object* java_receiver_obj = shadow_frame->GetVRegReference(arg_offset + 1); + ScopedLocalRef<jobject> java_receiver(env, + java_receiver_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_receiver_obj)); + + mirror::Object* java_args_obj = shadow_frame->GetVRegReference(arg_offset + 2); + ScopedLocalRef<jobject> java_args(env, + java_args_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_args_obj)); + + ScopedLocalRef<jobject> result_jobj(env, + InvokeMethod(soa, java_method.get(), java_receiver.get(), java_args.get())); + + result->SetL(self->DecodeJObject(result_jobj.get())); + + // Conservatively flag all exceptions as transaction aborts. This way we don't need to unwrap + // InvocationTargetExceptions. + if (self->IsExceptionPending()) { + AbortTransactionOrFail(self, "Failed Method.invoke"); + } +} + void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray( Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED, @@ -1640,7 +1696,13 @@ void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item, if (iter != invoke_handlers_.end()) { // Clear out the result in case it's not zeroed out. result->SetL(0); + + // Push the shadow frame. This is so the failing method can be seen in abort dumps. + self->PushShadowFrame(shadow_frame); + (*iter->second)(self, shadow_frame, result, arg_offset); + + self->PopShadowFrame(); } else { // Not special, continue with regular interpreter execution. ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result); diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index 63425c055a..b8553b5771 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -29,6 +29,7 @@ V(ClassGetDeclaredMethod, "java.lang.reflect.Method java.lang.Class.getDeclaredMethodInternal(java.lang.String, java.lang.Class[])") \ V(ClassGetDeclaredConstructor, "java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructorInternal(java.lang.Class[])") \ V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \ + V(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \ V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \ V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \ V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \ @@ -42,6 +43,9 @@ V(ThreadLocalGet, "java.lang.Object java.lang.ThreadLocal.get()") \ V(MathCeil, "double java.lang.Math.ceil(double)") \ V(MathFloor, "double java.lang.Math.floor(double)") \ + V(MathSin, "double java.lang.Math.sin(double)") \ + V(MathCos, "double java.lang.Math.cos(double)") \ + V(MathPow, "double java.lang.Math.pow(double, double)") \ V(ObjectHashCode, "int java.lang.Object.hashCode()") \ V(DoubleDoubleToRawLongBits, "long java.lang.Double.doubleToRawLongBits(double)") \ V(DexCacheGetDexNative, "com.android.dex.Dex java.lang.DexCache.getDexNative()") \ @@ -50,6 +54,7 @@ V(MemoryPeekInt, "int libcore.io.Memory.peekIntNative(long)") \ V(MemoryPeekLong, "long libcore.io.Memory.peekLongNative(long)") \ V(MemoryPeekByteArray, "void libcore.io.Memory.peekByteArray(long, byte[], int, int)") \ + V(MethodInvoke, "java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])") \ V(ReferenceGetReferent, "java.lang.Object java.lang.ref.Reference.getReferent()") \ V(RuntimeAvailableProcessors, "int java.lang.Runtime.availableProcessors()") \ V(StringGetCharsNoCheck, "void java.lang.String.getCharsNoCheck(int, int, char[], int)") \ diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index 100a44626b..b26635c854 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -802,5 +802,65 @@ TEST_F(UnstartedRuntimeTest, ToLowerUpper) { ShadowFrame::DeleteDeoptimizedFrame(tmp); } +TEST_F(UnstartedRuntimeTest, Sin) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + // Test an important value, PI/6. That's the one we see in practice. + constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365); + tmp->SetVRegLong(0, static_cast<int64_t>(lvalue)); + + JValue result; + UnstartedMathSin(self, tmp, &result, 0); + + const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); + EXPECT_EQ(UINT64_C(0x3fdfffffffffffff), lresult); + + ShadowFrame::DeleteDeoptimizedFrame(tmp); +} + +TEST_F(UnstartedRuntimeTest, Cos) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + // Test an important value, PI/6. That's the one we see in practice. + constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365); + tmp->SetVRegLong(0, static_cast<int64_t>(lvalue)); + + JValue result; + UnstartedMathCos(self, tmp, &result, 0); + + const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); + EXPECT_EQ(UINT64_C(0x3febb67ae8584cab), lresult); + + ShadowFrame::DeleteDeoptimizedFrame(tmp); +} + +TEST_F(UnstartedRuntimeTest, Pow) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + // Test an important pair. + constexpr uint64_t lvalue1 = UINT64_C(0x4079000000000000); + constexpr uint64_t lvalue2 = UINT64_C(0xbfe6db6dc0000000); + + tmp->SetVRegLong(0, static_cast<int64_t>(lvalue1)); + tmp->SetVRegLong(2, static_cast<int64_t>(lvalue2)); + + JValue result; + UnstartedMathPow(self, tmp, &result, 0); + + const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); + EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult); + + ShadowFrame::DeleteDeoptimizedFrame(tmp); +} + } // namespace interpreter } // namespace art diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 42f003dc84..b4a23badba 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1165,5 +1165,16 @@ template mirror::Constructor* Class::GetDeclaredConstructorInternal<true>( mirror::Class* klass, mirror::ObjectArray<mirror::Class>* args); +int32_t Class::GetInnerClassFlags(Handle<Class> h_this, int32_t default_value) { + if (h_this->IsProxyClass() || h_this->GetDexCache() == nullptr) { + return default_value; + } + uint32_t flags; + if (!h_this->GetDexFile().GetInnerClassFlags(h_this, &flags)) { + return default_value; + } + return flags; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 57c3590a2e..5b6ded162b 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1223,6 +1223,9 @@ class MANAGED Class FINAL : public Object { Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args, size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); + static int32_t GetInnerClassFlags(Handle<Class> h_this, int32_t default_value) + SHARED_REQUIRES(Locks::mutator_lock_); + // Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore // fence. class InitializeClassVisitor { diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index c1899afc49..6b7ca40bee 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -517,14 +517,7 @@ static jint Class_getInnerClassFlags(JNIEnv* env, jobject javaThis, jint default ScopedFastNativeObjectAccess soa(env); StackHandleScope<1> hs(soa.Self()); Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis))); - if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { - return defaultValue; - } - uint32_t flags; - if (!klass->GetDexFile().GetInnerClassFlags(klass, &flags)) { - return defaultValue; - } - return flags; + return mirror::Class::GetInnerClassFlags(klass, defaultValue); } static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) { |