diff options
| author | 2017-02-09 23:37:23 +0000 | |
|---|---|---|
| committer | 2017-02-09 23:37:24 +0000 | |
| commit | 74b50042180c6d85e32b6479ba3fe36ce84144ae (patch) | |
| tree | 1d6947d2ca2e039d1e2f1dbf12ffb31b791d862a | |
| parent | d6209af0b79f7819cc17d5ad1c0a0af5605f747d (diff) | |
| parent | 3d2fcaae4145a50e4d7460d8ce3caf97eb825a08 (diff) | |
Merge "ART: Update unstarted runtime for changed libcore"
| -rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 104 | ||||
| -rw-r--r-- | runtime/interpreter/unstarted_runtime_test.cc | 95 |
2 files changed, 163 insertions, 36 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 371e2f1e65..545cc1ad42 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -21,6 +21,7 @@ #include <stdlib.h> #include <cmath> +#include <initializer_list> #include <limits> #include <locale> #include <unordered_map> @@ -883,43 +884,74 @@ void UnstartedRuntime::UnstartedSystemGetPropertyWithDefault( GetSystemProperty(self, shadow_frame, result, arg_offset, true); } -void UnstartedRuntime::UnstartedThreadLocalGet( - Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) { - std::string caller(ArtMethod::PrettyMethod(shadow_frame->GetLink()->GetMethod())); - bool ok = false; - if (caller == "void java.lang.FloatingDecimal.developLongDigits(int, long, long)" || - caller == "java.lang.String java.lang.FloatingDecimal.toJavaFormatString()") { - // Allocate non-threadlocal buffer. - result->SetL(mirror::CharArray::Alloc(self, 26)); - ok = true; - } else if (caller == - "java.lang.FloatingDecimal java.lang.FloatingDecimal.getThreadLocalInstance()") { - // Allocate new object. - StackHandleScope<2> hs(self); - Handle<mirror::Class> h_real_to_string_class(hs.NewHandle( - shadow_frame->GetLink()->GetMethod()->GetDeclaringClass())); - Handle<mirror::Object> h_real_to_string_obj(hs.NewHandle( - h_real_to_string_class->AllocObject(self))); - if (h_real_to_string_obj.Get() != nullptr) { - auto* cl = Runtime::Current()->GetClassLinker(); - ArtMethod* init_method = h_real_to_string_class->FindDirectMethod( - "<init>", "()V", cl->GetImagePointerSize()); - if (init_method == nullptr) { - h_real_to_string_class->DumpClass(LOG_STREAM(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; - } +static std::string GetImmediateCaller(ShadowFrame* shadow_frame) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (shadow_frame->GetLink() == nullptr) { + return "<no caller>"; + } + return ArtMethod::PrettyMethod(shadow_frame->GetLink()->GetMethod()); +} + +static bool CheckCallers(ShadowFrame* shadow_frame, + std::initializer_list<std::string> allowed_call_stack) + REQUIRES_SHARED(Locks::mutator_lock_) { + for (const std::string& allowed_caller : allowed_call_stack) { + if (shadow_frame->GetLink() == nullptr) { + return false; + } + + std::string found_caller = ArtMethod::PrettyMethod(shadow_frame->GetLink()->GetMethod()); + if (allowed_caller != found_caller) { + return false; + } + + shadow_frame = shadow_frame->GetLink(); + } + return true; +} + +static ObjPtr<mirror::Object> CreateInstanceOf(Thread* self, const char* class_descriptor) + REQUIRES_SHARED(Locks::mutator_lock_) { + // Find the requested class. + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ObjPtr<mirror::Class> klass = + class_linker->FindClass(self, class_descriptor, ScopedNullHandle<mirror::ClassLoader>()); + if (klass == nullptr) { + AbortTransactionOrFail(self, "Could not load class %s", class_descriptor); + return nullptr; + } + + StackHandleScope<2> hs(self); + Handle<mirror::Class> h_class(hs.NewHandle(klass)); + Handle<mirror::Object> h_obj(hs.NewHandle(h_class->AllocObject(self))); + if (h_obj.Get() != nullptr) { + ArtMethod* init_method = h_class->FindDirectMethod( + "<init>", "()V", class_linker->GetImagePointerSize()); + if (init_method == nullptr) { + AbortTransactionOrFail(self, "Could not find <init> for %s", class_descriptor); + return nullptr; + } else { + JValue invoke_result; + EnterInterpreterFromInvoke(self, init_method, h_obj.Get(), nullptr, nullptr); + if (!self->IsExceptionPending()) { + return h_obj.Get(); } + AbortTransactionOrFail(self, "Could not run <init> for %s", class_descriptor); } } + AbortTransactionOrFail(self, "Could not allocate instance of %s", class_descriptor); + return nullptr; +} - if (!ok) { - AbortTransactionOrFail(self, "Could not create RealToString object"); +void UnstartedRuntime::UnstartedThreadLocalGet( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) { + if (CheckCallers(shadow_frame, { "sun.misc.FloatingDecimal$BinaryToASCIIBuffer " + "sun.misc.FloatingDecimal.getBinaryToASCIIBuffer()" })) { + result->SetL(CreateInstanceOf(self, "Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;")); + } else { + AbortTransactionOrFail(self, + "ThreadLocal.get() does not support %s", + GetImmediateCaller(shadow_frame).c_str()); } } @@ -1252,12 +1284,12 @@ void UnstartedRuntime::UnstartedReferenceGetReferent( // initialization of other classes, so will *use* the value. void UnstartedRuntime::UnstartedRuntimeAvailableProcessors( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) { - std::string caller(ArtMethod::PrettyMethod(shadow_frame->GetLink()->GetMethod())); - if (caller == "void java.util.concurrent.SynchronousQueue.<clinit>()") { + if (CheckCallers(shadow_frame, { "void java.util.concurrent.SynchronousQueue.<clinit>()" })) { // SynchronousQueue really only separates between single- and multiprocessor case. Return // 8 as a conservative upper approximation. result->SetI(8); - } else if (caller == "void java.util.concurrent.ConcurrentHashMap.<clinit>()") { + } else if (CheckCallers(shadow_frame, + { "void java.util.concurrent.ConcurrentHashMap.<clinit>()" })) { // ConcurrentHashMap uses it for striding. 8 still seems an OK general value, as it's likely // a good upper bound. // TODO: Consider resetting in the zygote? diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index ae55f4c2ef..31be587e9c 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -944,5 +944,100 @@ TEST_F(UnstartedRuntimeTest, GetDeclaringClass) { ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); } +TEST_F(UnstartedRuntimeTest, ThreadLocalGet) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + JValue result; + ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); + + StackHandleScope<1> hs(self); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + + // Positive test. See that We get something for float conversion. + { + Handle<mirror::Class> floating_decimal = hs.NewHandle( + class_linker->FindClass(self, + "Lsun/misc/FloatingDecimal;", + ScopedNullHandle<mirror::ClassLoader>())); + ASSERT_TRUE(floating_decimal.Get() != nullptr); + ASSERT_TRUE(class_linker->EnsureInitialized(self, floating_decimal, true, true)); + + ArtMethod* caller_method = floating_decimal->FindDeclaredDirectMethod( + "getBinaryToASCIIBuffer", + "()Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;", + class_linker->GetImagePointerSize()); + // floating_decimal->DumpClass(LOG_STREAM(ERROR), mirror::Class::kDumpClassFullDetail); + ASSERT_TRUE(caller_method != nullptr); + ShadowFrame* caller_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, caller_method, 0); + shadow_frame->SetLink(caller_frame); + + UnstartedThreadLocalGet(self, shadow_frame, &result, 0); + EXPECT_TRUE(result.GetL() != nullptr); + EXPECT_FALSE(self->IsExceptionPending()); + + ShadowFrame::DeleteDeoptimizedFrame(caller_frame); + } + + // Negative test. + PrepareForAborts(); + + { + // Just use a method in Class. + ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass(); + ArtMethod* caller_method = + &*class_class->GetDeclaredMethods(class_linker->GetImagePointerSize()).begin(); + ShadowFrame* caller_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, caller_method, 0); + shadow_frame->SetLink(caller_frame); + + Transaction transaction; + Runtime::Current()->EnterTransactionMode(&transaction); + UnstartedThreadLocalGet(self, shadow_frame, &result, 0); + Runtime::Current()->ExitTransactionMode(); + ASSERT_TRUE(self->IsExceptionPending()); + ASSERT_TRUE(transaction.IsAborted()); + self->ClearException(); + + ShadowFrame::DeleteDeoptimizedFrame(caller_frame); + } + + ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); +} + +TEST_F(UnstartedRuntimeTest, FloatConversion) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + StackHandleScope<1> hs(self); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::Class> double_class = hs.NewHandle( + class_linker->FindClass(self, + "Ljava/lang/Double;", + ScopedNullHandle<mirror::ClassLoader>())); + ASSERT_TRUE(double_class.Get() != nullptr); + ASSERT_TRUE(class_linker->EnsureInitialized(self, double_class, true, true)); + + ArtMethod* method = double_class->FindDeclaredDirectMethod("toString", + "(D)Ljava/lang/String;", + class_linker->GetImagePointerSize()); + ASSERT_TRUE(method != nullptr); + + // create instruction data for invoke-direct {v0, v1} of method with fake index + uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; + const Instruction* inst = Instruction::At(inst_data); + + JValue result; + ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0); + shadow_frame->SetVRegDouble(0, 1.23); + interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result); + ObjPtr<mirror::String> string_result = reinterpret_cast<mirror::String*>(result.GetL()); + ASSERT_TRUE(string_result != nullptr); + + std::string mod_utf = string_result->ToModifiedUtf8(); + EXPECT_EQ("1.23", mod_utf); + + ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); +} + } // namespace interpreter } // namespace art |