From: Andreas Gampe Date: Wed, 13 Apr 2016 21:53:23 +0000 (-0700) Subject: ART: Add a System.getProperty cutout X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d4fa9f4ddc1c1f193b623c8da80384b4c510a1b4;p=android-x86%2Fart.git ART: Add a System.getProperty cutout Add support for certain keys of System.getProperty, derived from AndroidHardcodedSystemProperties. Allows to compile-time initialize: * android.icu.impl.Utility * java.net.URLDecoder * java.net.URLEncoder * java.util.regex.PatternSyntaxException Bug: 27265238 Bug: 28174137 (cherry picked from commit 7107be612db6b15921b602ac9a3f24e9c2e7d414) Change-Id: Ib919fb05f0459be19331ac356af34a968bf685cd --- diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 02e05c542..fe388cd16 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -484,6 +484,101 @@ void UnstartedRuntime::UnstartedSystemGetSecurityManager( result->SetL(nullptr); } +static constexpr const char* kAndroidHardcodedSystemPropertiesFieldName = "STATIC_PROPERTIES"; + +static void GetSystemProperty(Thread* self, + ShadowFrame* shadow_frame, + JValue* result, + size_t arg_offset, + bool is_default_version) + SHARED_REQUIRES(Locks::mutator_lock_) { + StackHandleScope<4> hs(self); + Handle h_key( + hs.NewHandle(reinterpret_cast(shadow_frame->GetVRegReference(arg_offset)))); + if (h_key.Get() == nullptr) { + AbortTransactionOrFail(self, "getProperty key was null"); + return; + } + + // This is overall inefficient, but reflecting the values here is not great, either. So + // for simplicity, and with the assumption that the number of getProperty calls is not + // too great, just iterate each time. + + // Get the storage class. + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle h_props_class(hs.NewHandle( + class_linker->FindClass(self, + "Ljava/lang/AndroidHardcodedSystemProperties;", + ScopedNullHandle()))); + if (h_props_class.Get() == nullptr) { + AbortTransactionOrFail(self, "Could not find AndroidHardcodedSystemProperties"); + return; + } + if (!class_linker->EnsureInitialized(self, h_props_class, true, true)) { + AbortTransactionOrFail(self, "Could not initialize AndroidHardcodedSystemProperties"); + return; + } + + // Get the storage array. + ArtField* static_properties = + h_props_class->FindDeclaredStaticField(kAndroidHardcodedSystemPropertiesFieldName, + "[[Ljava/lang/String;"); + if (static_properties == nullptr) { + AbortTransactionOrFail(self, + "Could not find %s field", + kAndroidHardcodedSystemPropertiesFieldName); + return; + } + Handle>> h_2string_array( + hs.NewHandle(reinterpret_cast>*>( + static_properties->GetObject(h_props_class.Get())))); + if (h_2string_array.Get() == nullptr) { + AbortTransactionOrFail(self, "Field %s is null", kAndroidHardcodedSystemPropertiesFieldName); + return; + } + + // Iterate over it. + const int32_t prop_count = h_2string_array->GetLength(); + // Use the third handle as mutable. + MutableHandle> h_string_array( + hs.NewHandle>(nullptr)); + for (int32_t i = 0; i < prop_count; ++i) { + h_string_array.Assign(h_2string_array->Get(i)); + if (h_string_array.Get() == nullptr || + h_string_array->GetLength() != 2 || + h_string_array->Get(0) == nullptr) { + AbortTransactionOrFail(self, + "Unexpected content of %s", + kAndroidHardcodedSystemPropertiesFieldName); + return; + } + if (h_key->Equals(h_string_array->Get(0))) { + // Found a value. + if (h_string_array->Get(1) == nullptr && is_default_version) { + // Null is being delegated to the default map, and then resolved to the given default value. + // As there's no default map, return the given value. + result->SetL(shadow_frame->GetVRegReference(arg_offset + 1)); + } else { + result->SetL(h_string_array->Get(1)); + } + return; + } + } + + // Key is not supported. + AbortTransactionOrFail(self, "getProperty key %s not supported", h_key->ToModifiedUtf8().c_str()); +} + +void UnstartedRuntime::UnstartedSystemGetProperty( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + GetSystemProperty(self, shadow_frame, result, arg_offset, false); +} + +void UnstartedRuntime::UnstartedSystemGetPropertyWithDefault( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + 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(PrettyMethod(shadow_frame->GetLink()->GetMethod())); diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index 331270113..3b5bee829 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -34,6 +34,8 @@ V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \ V(SystemArraycopyInt, "void java.lang.System.arraycopy(int[], int, int[], int, int)") \ V(SystemGetSecurityManager, "java.lang.SecurityManager java.lang.System.getSecurityManager()") \ + V(SystemGetProperty, "java.lang.String java.lang.System.getProperty(java.lang.String)") \ + V(SystemGetPropertyWithDefault, "java.lang.String java.lang.System.getProperty(java.lang.String, java.lang.String)") \ 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)") \