From b8a00f95e93eb0225e86dad582387f1cc69e7df6 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 18 Apr 2016 20:51:13 -0700 Subject: [PATCH] ART: Add Math cutouts Add sin, cos and pow to unstarted runtime. Add tests for some very specific values that are seen. Allows to compile-time initialize: * android.graphics.drawable.RippleForeground * android.widget.EdgeEffect Bug: 27265238 (cherry picked from commit 8c5889a3bdefd7dc84494ec824d495913f2362a9) Change-Id: I0360a078e7dc9d2a176ec1cf2d8dbb242da1c83e --- runtime/interpreter/unstarted_runtime.cc | 16 +++++++ runtime/interpreter/unstarted_runtime_list.h | 3 ++ runtime/interpreter/unstarted_runtime_test.cc | 60 +++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 6d00ce1c5..1f473e404 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -834,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); diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index 379d76012..b8553b577 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -43,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()") \ diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index 100a44626..b26635c85 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(lvalue)); + + JValue result; + UnstartedMathSin(self, tmp, &result, 0); + + const uint64_t lresult = static_cast(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(lvalue)); + + JValue result; + UnstartedMathCos(self, tmp, &result, 0); + + const uint64_t lresult = static_cast(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(lvalue1)); + tmp->SetVRegLong(2, static_cast(lvalue2)); + + JValue result; + UnstartedMathPow(self, tmp, &result, 0); + + const uint64_t lresult = static_cast(result.GetJ()); + EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult); + + ShadowFrame::DeleteDeoptimizedFrame(tmp); +} + } // namespace interpreter } // namespace art -- 2.11.0