summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2015-05-14 15:58:17 -0700
committerKenny Root <kroot@google.com>2015-05-15 15:10:52 -0700
commita02e391bdea875b3b6035ca27a5da414a0f93dae (patch)
tree1a56b93896e425697b037f02896ff937b2673b17 /runtime/interpreter
parent577d24cc9e330afb21ab7a5f0d95f84b88745e55 (diff)
downloadart-a02e391bdea875b3b6035ca27a5da414a0f93dae.tar.gz
art-a02e391bdea875b3b6035ca27a5da414a0f93dae.tar.bz2
art-a02e391bdea875b3b6035ca27a5da414a0f93dae.zip
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.cc60
1 files changed, 60 insertions, 0 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 9006257d00..317106bb16 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",