diff options
author | Kenny Root <kroot@google.com> | 2015-05-14 15:58:17 -0700 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2015-05-15 15:10:52 -0700 |
commit | a02e391bdea875b3b6035ca27a5da414a0f93dae (patch) | |
tree | 1a56b93896e425697b037f02896ff937b2673b17 /runtime/interpreter | |
parent | 577d24cc9e330afb21ab7a5f0d95f84b88745e55 (diff) | |
download | art-a02e391bdea875b3b6035ca27a5da414a0f93dae.zip art-a02e391bdea875b3b6035ca27a5da414a0f93dae.tar.gz art-a02e391bdea875b3b6035ca27a5da414a0f93dae.tar.bz2 |
Add new style String operations during compilation init, part 2
This allows some class initializers that deal with Strings to run during
compilation. However, java.lang.Character.toUpperCase() is blocking
initialization for some parts.
(cherry picked from commit 57f91e8956f4496391bff028a1b990540cc91c22)
Bug: 21036900
Change-Id: Ia969c6a643f510bc798f94fb10bca1a68fe2ae67
Diffstat (limited to 'runtime/interpreter')
-rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 9006257..317106b 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -767,8 +767,12 @@ static void UnstartedStringGetCharsNoCheck( AbortTransactionOrFail(self, "String.getCharsNoCheck with null object"); return; } + DCHECK_GE(start, 0); + DCHECK_GE(end, string->GetLength()); StackHandleScope<1> hs(self); Handle<mirror::CharArray> h_char_array(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray())); + DCHECK_LE(index, h_char_array->GetLength()); + DCHECK_LE(end - start, h_char_array->GetLength() - index); string->GetChars(start, end, h_char_array, index); } @@ -785,6 +789,20 @@ static void UnstartedStringCharAt( result->SetC(string->CharAt(index)); } +// This allows setting chars from the new style of String objects during compilation. +static void UnstartedStringSetCharAt( + Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + jint index = shadow_frame->GetVReg(arg_offset + 1); + jchar c = shadow_frame->GetVReg(arg_offset + 2); + mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString(); + if (string == nullptr) { + AbortTransactionOrFail(self, "String.setCharAt with null object"); + return; + } + string->SetCharAt(index, c); +} + // This allows creating the new style of String objects during compilation. static void UnstartedStringFactoryNewStringFromChars( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) @@ -800,19 +818,51 @@ static void UnstartedStringFactoryNewStringFromChars( } // This allows creating the new style of String objects during compilation. +static void UnstartedStringFactoryNewStringFromString( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString(); + if (to_copy == nullptr) { + AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object"); + return; + } + StackHandleScope<1> hs(self); + Handle<mirror::String> h_string(hs.NewHandle(to_copy)); + Runtime* runtime = Runtime::Current(); + gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator(); + result->SetL(mirror::String::AllocFromString<true>(self, h_string->GetLength(), h_string, 0, + allocator)); +} + +// This allows creating the new style of String objects during compilation. static void UnstartedStringFastSubstring( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { jint start = shadow_frame->GetVReg(arg_offset + 1); jint length = shadow_frame->GetVReg(arg_offset + 2); + DCHECK_GE(start, 0); DCHECK_GE(length, 0); StackHandleScope<1> hs(self); Handle<mirror::String> h_string(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString())); + DCHECK_LE(start, h_string->GetLength()); + DCHECK_LE(start + length, h_string->GetLength()); Runtime* runtime = Runtime::Current(); gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator(); result->SetL(mirror::String::AllocFromString<true>(self, length, h_string, start, allocator)); } +// This allows getting the char array for new style of String objects during compilation. +static void UnstartedStringToCharArray( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString(); + if (string == nullptr) { + AbortTransactionOrFail(self, "String.charAt with null object"); + return; + } + result->SetL(string->ToCharArray(self)); +} + static void UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self, mirror::ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED, @@ -1141,10 +1191,16 @@ static void UnstartedRuntimeInitializeInvokeHandlers() { &UnstartedStringGetCharsNoCheck }, { "char java.lang.String.charAt(int)", &UnstartedStringCharAt }, + { "void java.lang.String.setCharAt(int, char)", + &UnstartedStringSetCharAt }, { "java.lang.String java.lang.StringFactory.newStringFromChars(int, int, char[])", &UnstartedStringFactoryNewStringFromChars }, + { "java.lang.String java.lang.StringFactory.newStringFromString(java.lang.String)", + &UnstartedStringFactoryNewStringFromString }, { "java.lang.String java.lang.String.fastSubstring(int, int)", &UnstartedStringFastSubstring }, + { "char[] java.lang.String.toCharArray()", + &UnstartedStringToCharArray }, }; for (auto& def : defs) { @@ -1228,6 +1284,8 @@ void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item, std::string name(PrettyMethod(shadow_frame->GetMethod())); const auto& iter = invoke_handlers_.find(name); if (iter != invoke_handlers_.end()) { + // Clear out the result in case it's not zeroed out. + result->SetL(0); (*iter->second)(self, shadow_frame, result, arg_offset); } else { // Not special, continue with regular interpreter execution. @@ -1241,6 +1299,8 @@ void UnstartedRuntimeJni(Thread* self, mirror::ArtMethod* method, mirror::Object std::string name(PrettyMethod(method)); const auto& iter = jni_handlers_.find(name); if (iter != jni_handlers_.end()) { + // Clear out the result in case it's not zeroed out. + result->SetL(0); (*iter->second)(self, method, receiver, args, result); } else if (Runtime::Current()->IsActiveTransaction()) { AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s", |