ART: Refactor UnstartedRuntime for testing

Expose the UnstartedRuntime implementation functions as private static
methods of a class. Add a gtest that can invoke these functions. Add
sample tests for String and Memory.

Bug: 21173514
Change-Id: Ib5bde6347fafaf7607c642542ea7d5938ff4b1df
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 317106b..738e52b 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -120,7 +120,7 @@
   return param->AsString();
 }
 
-static void UnstartedClassForName(
+void UnstartedRuntime::UnstartedClassForName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
@@ -134,7 +134,7 @@
   CheckExceptionGenerateClassNotFound(self);
 }
 
-static void UnstartedClassForNameLong(
+void UnstartedRuntime::UnstartedClassForNameLong(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
@@ -152,7 +152,7 @@
   CheckExceptionGenerateClassNotFound(self);
 }
 
-static void UnstartedClassClassForName(
+void UnstartedRuntime::UnstartedClassClassForName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
@@ -170,7 +170,7 @@
   CheckExceptionGenerateClassNotFound(self);
 }
 
-static void UnstartedClassNewInstance(
+void UnstartedRuntime::UnstartedClassNewInstance(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   StackHandleScope<3> hs(self);  // Class, constructor, object.
@@ -226,7 +226,7 @@
   }
 }
 
-static void UnstartedClassGetDeclaredField(
+void UnstartedRuntime::UnstartedClassGetDeclaredField(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
@@ -265,7 +265,7 @@
   }
 }
 
-static void UnstartedVmClassLoaderFindLoadedClass(
+void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
@@ -286,7 +286,7 @@
   }
 }
 
-static void UnstartedVoidLookupType(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedVoidLookupType(Thread* self ATTRIBUTE_UNUSED,
                                     ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
                                     JValue* result,
                                     size_t arg_offset ATTRIBUTE_UNUSED)
@@ -323,7 +323,7 @@
   }
 }
 
-static void UnstartedSystemArraycopy(
+void UnstartedRuntime::UnstartedSystemArraycopy(
     Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Special case array copying without initializing System.
@@ -409,7 +409,21 @@
   }
 }
 
-static void UnstartedThreadLocalGet(
+void UnstartedRuntime::UnstartedSystemArraycopyChar(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Just forward.
+  UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
+}
+
+void UnstartedRuntime::UnstartedSystemArraycopyInt(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Just forward.
+  UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
+}
+
+void UnstartedRuntime::UnstartedThreadLocalGet(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
@@ -459,7 +473,7 @@
   }
 }
 
-static void UnstartedMathCeil(
+void UnstartedRuntime::UnstartedMathCeil(
     Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   double in = shadow_frame->GetVRegDouble(arg_offset);
   double out;
@@ -474,21 +488,21 @@
   result->SetD(out);
 }
 
-static void UnstartedArtMethodGetMethodName(
+void UnstartedRuntime::UnstartedArtMethodGetMethodName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod();
   result->SetL(method->GetNameAsString(self));
 }
 
-static void UnstartedObjectHashCode(
+void UnstartedRuntime::UnstartedObjectHashCode(
     Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
   result->SetI(obj->IdentityHashCode());
 }
 
-static void UnstartedDoubleDoubleToRawLongBits(
+void UnstartedRuntime::UnstartedDoubleDoubleToRawLongBits(
     Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   double in = shadow_frame->GetVRegDouble(arg_offset);
   result->SetJ(bit_cast<int64_t, double>(in));
@@ -522,7 +536,7 @@
   return self->DecodeJObject(dex.get());
 }
 
-static void UnstartedDexCacheGetDexNative(
+void UnstartedRuntime::UnstartedDexCacheGetDexNative(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // We will create the Dex object, but the image writer will release it before creating the
@@ -555,17 +569,20 @@
     }
 
     case Primitive::kPrimShort: {
-      result->SetS(*reinterpret_cast<int16_t*>(static_cast<intptr_t>(address)));
+      typedef int16_t unaligned_short __attribute__ ((aligned (1)));
+      result->SetS(*reinterpret_cast<unaligned_short*>(static_cast<intptr_t>(address)));
       return;
     }
 
     case Primitive::kPrimInt: {
-      result->SetI(*reinterpret_cast<int32_t*>(static_cast<intptr_t>(address)));
+      typedef int32_t unaligned_int __attribute__ ((aligned (1)));
+      result->SetI(*reinterpret_cast<unaligned_int*>(static_cast<intptr_t>(address)));
       return;
     }
 
     case Primitive::kPrimLong: {
-      result->SetJ(*reinterpret_cast<int64_t*>(static_cast<intptr_t>(address)));
+      typedef int64_t unaligned_long __attribute__ ((aligned (1)));
+      result->SetJ(*reinterpret_cast<unaligned_long*>(static_cast<intptr_t>(address)));
       return;
     }
 
@@ -582,22 +599,28 @@
   UNREACHABLE();
 }
 
-static void UnstartedMemoryPeekEntry(
+void UnstartedRuntime::UnstartedMemoryPeekByte(
     Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  std::string name(PrettyMethod(shadow_frame->GetMethod()));
-  if (name == "byte libcore.io.Memory.peekByte(long)") {
-    UnstartedMemoryPeek(Primitive::kPrimByte, shadow_frame, result, arg_offset);
-  } else if (name == "short libcore.io.Memory.peekShortNative(long)") {
-    UnstartedMemoryPeek(Primitive::kPrimShort, shadow_frame, result, arg_offset);
-  } else if (name == "int libcore.io.Memory.peekIntNative(long)") {
-    UnstartedMemoryPeek(Primitive::kPrimInt, shadow_frame, result, arg_offset);
-  } else if (name == "long libcore.io.Memory.peekLongNative(long)") {
-    UnstartedMemoryPeek(Primitive::kPrimLong, shadow_frame, result, arg_offset);
-  } else {
-    LOG(FATAL) << "Unsupported Memory.peek entry: " << name;
-    UNREACHABLE();
-  }
+  UnstartedMemoryPeek(Primitive::kPrimByte, shadow_frame, result, arg_offset);
+}
+
+void UnstartedRuntime::UnstartedMemoryPeekShort(
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  UnstartedMemoryPeek(Primitive::kPrimShort, shadow_frame, result, arg_offset);
+}
+
+void UnstartedRuntime::UnstartedMemoryPeekInt(
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  UnstartedMemoryPeek(Primitive::kPrimInt, shadow_frame, result, arg_offset);
+}
+
+void UnstartedRuntime::UnstartedMemoryPeekLong(
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  UnstartedMemoryPeek(Primitive::kPrimLong, shadow_frame, result, arg_offset);
 }
 
 static void UnstartedMemoryPeekArray(
@@ -649,20 +672,14 @@
   UNREACHABLE();
 }
 
-static void UnstartedMemoryPeekArrayEntry(
+void UnstartedRuntime::UnstartedMemoryPeekByteArray(
     Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  std::string name(PrettyMethod(shadow_frame->GetMethod()));
-  if (name == "void libcore.io.Memory.peekByteArray(long, byte[], int, int)") {
-    UnstartedMemoryPeekArray(Primitive::kPrimByte, self, shadow_frame, arg_offset);
-  } else {
-    LOG(FATAL) << "Unsupported Memory.peekArray entry: " << name;
-    UNREACHABLE();
-  }
+  UnstartedMemoryPeekArray(Primitive::kPrimByte, self, shadow_frame, arg_offset);
 }
 
 // This allows reading security.properties in an unstarted runtime and initialize Security.
-static void UnstartedSecurityGetSecurityPropertiesReader(
+void UnstartedRuntime::UnstartedSecurityGetSecurityPropertiesReader(
     Thread* self,
     ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
     JValue* result,
@@ -756,7 +773,7 @@
 }
 
 // This allows reading the new style of String objects during compilation.
-static void UnstartedStringGetCharsNoCheck(
+void UnstartedRuntime::UnstartedStringGetCharsNoCheck(
     Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   jint start = shadow_frame->GetVReg(arg_offset + 1);
@@ -777,7 +794,7 @@
 }
 
 // This allows reading chars from the new style of String objects during compilation.
-static void UnstartedStringCharAt(
+void UnstartedRuntime::UnstartedStringCharAt(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   jint index = shadow_frame->GetVReg(arg_offset + 1);
@@ -790,7 +807,7 @@
 }
 
 // This allows setting chars from the new style of String objects during compilation.
-static void UnstartedStringSetCharAt(
+void UnstartedRuntime::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);
@@ -804,7 +821,7 @@
 }
 
 // This allows creating the new style of String objects during compilation.
-static void UnstartedStringFactoryNewStringFromChars(
+void UnstartedRuntime::UnstartedStringFactoryNewStringFromChars(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   jint offset = shadow_frame->GetVReg(arg_offset);
@@ -818,7 +835,7 @@
 }
 
 // This allows creating the new style of String objects during compilation.
-static void UnstartedStringFactoryNewStringFromString(
+void UnstartedRuntime::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();
@@ -834,8 +851,7 @@
                                                      allocator));
 }
 
-// This allows creating the new style of String objects during compilation.
-static void UnstartedStringFastSubstring(
+void UnstartedRuntime::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);
@@ -852,7 +868,7 @@
 }
 
 // This allows getting the char array for new style of String objects during compilation.
-static void UnstartedStringToCharArray(
+void UnstartedRuntime::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();
@@ -863,7 +879,7 @@
   result->SetL(string->ToCharArray(self));
 }
 
-static void UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self,
+void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self,
                                                   mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                   mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                   uint32_t* args,
@@ -880,7 +896,7 @@
                                                 array_class->GetComponentSizeShift(), allocator));
 }
 
-static void UnstartedJNIVMStackGetCallingClassLoader(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(Thread* self ATTRIBUTE_UNUSED,
                                                      mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                      mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                      uint32_t* args ATTRIBUTE_UNUSED,
@@ -888,7 +904,7 @@
   result->SetL(nullptr);
 }
 
-static void UnstartedJNIVMStackGetStackClass2(Thread* self,
+void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(Thread* self,
                                               mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                               mirror::Object* receiver ATTRIBUTE_UNUSED,
                                               uint32_t* args ATTRIBUTE_UNUSED,
@@ -901,7 +917,7 @@
   }
 }
 
-static void UnstartedJNIMathLog(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIMathLog(Thread* self ATTRIBUTE_UNUSED,
                                 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                 mirror::Object* receiver ATTRIBUTE_UNUSED,
                                 uint32_t* args,
@@ -911,7 +927,7 @@
   result->SetD(log(value.GetD()));
 }
 
-static void UnstartedJNIMathExp(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIMathExp(Thread* self ATTRIBUTE_UNUSED,
                                 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                 mirror::Object* receiver ATTRIBUTE_UNUSED,
                                 uint32_t* args,
@@ -921,7 +937,7 @@
   result->SetD(exp(value.GetD()));
 }
 
-static void UnstartedJNIClassGetNameNative(Thread* self,
+void UnstartedRuntime::UnstartedJNIClassGetNameNative(Thread* self,
                                            mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                            mirror::Object* receiver,
                                            uint32_t* args ATTRIBUTE_UNUSED,
@@ -931,7 +947,7 @@
   result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
 }
 
-static void UnstartedJNIFloatFloatToRawIntBits(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(Thread* self ATTRIBUTE_UNUSED,
                                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                uint32_t* args,
@@ -939,7 +955,7 @@
   result->SetI(args[0]);
 }
 
-static void UnstartedJNIFloatIntBitsToFloat(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(Thread* self ATTRIBUTE_UNUSED,
                                             mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                             mirror::Object* receiver ATTRIBUTE_UNUSED,
                                             uint32_t* args,
@@ -947,7 +963,7 @@
   result->SetI(args[0]);
 }
 
-static void UnstartedJNIObjectInternalClone(Thread* self,
+void UnstartedRuntime::UnstartedJNIObjectInternalClone(Thread* self,
                                             mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                             mirror::Object* receiver,
                                             uint32_t* args ATTRIBUTE_UNUSED,
@@ -956,7 +972,7 @@
   result->SetL(receiver->Clone(self));
 }
 
-static void UnstartedJNIObjectNotifyAll(Thread* self,
+void UnstartedRuntime::UnstartedJNIObjectNotifyAll(Thread* self,
                                         mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                         mirror::Object* receiver,
                                         uint32_t* args ATTRIBUTE_UNUSED,
@@ -965,7 +981,7 @@
   receiver->NotifyAll(self);
 }
 
-static void UnstartedJNIStringCompareTo(Thread* self,
+void UnstartedRuntime::UnstartedJNIStringCompareTo(Thread* self,
                                         mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                         mirror::Object* receiver,
                                         uint32_t* args,
@@ -978,7 +994,7 @@
   result->SetI(receiver->AsString()->CompareTo(rhs));
 }
 
-static void UnstartedJNIStringIntern(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIStringIntern(Thread* self ATTRIBUTE_UNUSED,
                                      mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                      mirror::Object* receiver,
                                      uint32_t* args ATTRIBUTE_UNUSED,
@@ -987,7 +1003,7 @@
   result->SetL(receiver->AsString()->Intern());
 }
 
-static void UnstartedJNIStringFastIndexOf(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIStringFastIndexOf(Thread* self ATTRIBUTE_UNUSED,
                                           mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                           mirror::Object* receiver,
                                           uint32_t* args,
@@ -996,7 +1012,7 @@
   result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
 }
 
-static void UnstartedJNIArrayCreateMultiArray(Thread* self,
+void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(Thread* self,
                                               mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                               mirror::Object* receiver ATTRIBUTE_UNUSED,
                                               uint32_t* args,
@@ -1008,7 +1024,7 @@
   result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
 }
 
-static void UnstartedJNIArrayCreateObjectArray(Thread* self,
+void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(Thread* self,
                                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                uint32_t* args,
@@ -1033,7 +1049,7 @@
   result->SetL(new_array);
 }
 
-static void UnstartedJNIThrowableNativeFillInStackTrace(Thread* self,
+void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(Thread* self,
                                                         mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                         mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                         uint32_t* args ATTRIBUTE_UNUSED,
@@ -1047,7 +1063,7 @@
   }
 }
 
-static void UnstartedJNISystemIdentityHashCode(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(Thread* self ATTRIBUTE_UNUSED,
                                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                uint32_t* args,
@@ -1057,7 +1073,7 @@
   result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
 }
 
-static void UnstartedJNIByteOrderIsLittleEndian(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(Thread* self ATTRIBUTE_UNUSED,
                                                 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                 mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                 uint32_t* args ATTRIBUTE_UNUSED,
@@ -1065,7 +1081,7 @@
   result->SetZ(JNI_TRUE);
 }
 
-static void UnstartedJNIUnsafeCompareAndSwapInt(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(Thread* self ATTRIBUTE_UNUSED,
                                                 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                 mirror::Object* receiver ATTRIBUTE_UNUSED,
                                                 uint32_t* args,
@@ -1086,7 +1102,7 @@
   result->SetZ(success ? JNI_TRUE : JNI_FALSE);
 }
 
-static void UnstartedJNIUnsafePutObject(Thread* self ATTRIBUTE_UNUSED,
+void UnstartedRuntime::UnstartedJNIUnsafePutObject(Thread* self ATTRIBUTE_UNUSED,
                                         mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                         mirror::Object* receiver ATTRIBUTE_UNUSED,
                                         uint32_t* args,
@@ -1102,7 +1118,7 @@
   }
 }
 
-static void UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
+void UnstartedRuntime::UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
     Thread* self ATTRIBUTE_UNUSED,
     mirror::ArtMethod* method ATTRIBUTE_UNUSED,
     mirror::Object* receiver ATTRIBUTE_UNUSED,
@@ -1114,7 +1130,7 @@
   result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
 }
 
-static void UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
+void UnstartedRuntime::UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
     Thread* self ATTRIBUTE_UNUSED,
     mirror::ArtMethod* method ATTRIBUTE_UNUSED,
     mirror::Object* receiver ATTRIBUTE_UNUSED,
@@ -1136,147 +1152,37 @@
 static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
 static std::unordered_map<std::string, JNIHandler> jni_handlers_;
 
-static void UnstartedRuntimeInitializeInvokeHandlers() {
-  struct InvokeHandlerDef {
-    std::string name;
-    InvokeHandler function;
-  };
-
-  InvokeHandlerDef defs[] {
-      { "java.lang.Class java.lang.Class.forName(java.lang.String)",
-          &UnstartedClassForName },
-      { "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)",
-          &UnstartedClassForNameLong },
-      { "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)",
-          &UnstartedClassClassForName },
-      { "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)",
-          &UnstartedVmClassLoaderFindLoadedClass },
-      { "java.lang.Class java.lang.Void.lookupType()",
-          &UnstartedVoidLookupType },
-      { "java.lang.Object java.lang.Class.newInstance()",
-          &UnstartedClassNewInstance },
-      { "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)",
-          &UnstartedClassGetDeclaredField },
-      { "int java.lang.Object.hashCode()",
-          &UnstartedObjectHashCode },
-      { "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)",
-          &UnstartedArtMethodGetMethodName },
-      { "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)",
-          &UnstartedSystemArraycopy},
-      { "void java.lang.System.arraycopy(char[], int, char[], int, int)",
-          &UnstartedSystemArraycopy },
-      { "void java.lang.System.arraycopy(int[], int, int[], int, int)",
-          &UnstartedSystemArraycopy },
-      { "long java.lang.Double.doubleToRawLongBits(double)",
-          &UnstartedDoubleDoubleToRawLongBits },
-      { "double java.lang.Math.ceil(double)",
-          &UnstartedMathCeil },
-      { "java.lang.Object java.lang.ThreadLocal.get()",
-          &UnstartedThreadLocalGet },
-      { "com.android.dex.Dex java.lang.DexCache.getDexNative()",
-          &UnstartedDexCacheGetDexNative },
-      { "byte libcore.io.Memory.peekByte(long)",
-          &UnstartedMemoryPeekEntry },
-      { "short libcore.io.Memory.peekShortNative(long)",
-          &UnstartedMemoryPeekEntry },
-      { "int libcore.io.Memory.peekIntNative(long)",
-          &UnstartedMemoryPeekEntry },
-      { "long libcore.io.Memory.peekLongNative(long)",
-          &UnstartedMemoryPeekEntry },
-      { "void libcore.io.Memory.peekByteArray(long, byte[], int, int)",
-          &UnstartedMemoryPeekArrayEntry },
-      { "java.io.Reader java.security.Security.getSecurityPropertiesReader()",
-          &UnstartedSecurityGetSecurityPropertiesReader },
-      { "void java.lang.String.getCharsNoCheck(int, int, char[], int)",
-          &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) {
-    invoke_handlers_.insert(std::make_pair(def.name, def.function));
-  }
+void UnstartedRuntime::InitializeInvokeHandlers() {
+#define UNSTARTED_DIRECT(ShortName, Sig) \
+  invoke_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::Unstarted ## ShortName));
+#include "unstarted_runtime_list.h"
+  UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
+#undef UNSTARTED_RUNTIME_DIRECT_LIST
+#undef UNSTARTED_RUNTIME_JNI_LIST
+#undef UNSTARTED_DIRECT
 }
 
-static void UnstartedRuntimeInitializeJNIHandlers() {
-  struct JNIHandlerDef {
-    std::string name;
-    JNIHandler function;
-  };
-
-  JNIHandlerDef defs[] {
-      { "java.lang.Object dalvik.system.VMRuntime.newUnpaddedArray(java.lang.Class, int)",
-          &UnstartedJNIVMRuntimeNewUnpaddedArray },
-      { "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()",
-          &UnstartedJNIVMStackGetCallingClassLoader },
-      { "java.lang.Class dalvik.system.VMStack.getStackClass2()",
-          &UnstartedJNIVMStackGetStackClass2 },
-      { "double java.lang.Math.log(double)",
-          &UnstartedJNIMathLog },
-      { "java.lang.String java.lang.Class.getNameNative()",
-          &UnstartedJNIClassGetNameNative },
-      { "int java.lang.Float.floatToRawIntBits(float)",
-          &UnstartedJNIFloatFloatToRawIntBits },
-      { "float java.lang.Float.intBitsToFloat(int)",
-          &UnstartedJNIFloatIntBitsToFloat },
-      { "double java.lang.Math.exp(double)",
-          &UnstartedJNIMathExp },
-      { "java.lang.Object java.lang.Object.internalClone()",
-          &UnstartedJNIObjectInternalClone },
-      { "void java.lang.Object.notifyAll()",
-          &UnstartedJNIObjectNotifyAll},
-      { "int java.lang.String.compareTo(java.lang.String)",
-          &UnstartedJNIStringCompareTo },
-      { "java.lang.String java.lang.String.intern()",
-          &UnstartedJNIStringIntern },
-      { "int java.lang.String.fastIndexOf(int, int)",
-          &UnstartedJNIStringFastIndexOf },
-      { "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])",
-          &UnstartedJNIArrayCreateMultiArray },
-      { "java.lang.Object java.lang.reflect.Array.createObjectArray(java.lang.Class, int)",
-          &UnstartedJNIArrayCreateObjectArray },
-      { "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()",
-          &UnstartedJNIThrowableNativeFillInStackTrace },
-      { "int java.lang.System.identityHashCode(java.lang.Object)",
-          &UnstartedJNISystemIdentityHashCode },
-      { "boolean java.nio.ByteOrder.isLittleEndian()",
-          &UnstartedJNIByteOrderIsLittleEndian },
-      { "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)",
-          &UnstartedJNIUnsafeCompareAndSwapInt },
-      { "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)",
-          &UnstartedJNIUnsafePutObject },
-      { "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)",
-          &UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType },
-      { "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)",
-          &UnstartedJNIUnsafeGetArrayIndexScaleForComponentType },
-  };
-
-  for (auto& def : defs) {
-    jni_handlers_.insert(std::make_pair(def.name, def.function));
-  }
+void UnstartedRuntime::InitializeJNIHandlers() {
+#define UNSTARTED_JNI(ShortName, Sig) \
+  jni_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::UnstartedJNI ## ShortName));
+#include "unstarted_runtime_list.h"
+  UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
+#undef UNSTARTED_RUNTIME_DIRECT_LIST
+#undef UNSTARTED_RUNTIME_JNI_LIST
+#undef UNSTARTED_JNI
 }
 
-void UnstartedRuntimeInitialize() {
+void UnstartedRuntime::Initialize() {
   CHECK(!tables_initialized_);
 
-  UnstartedRuntimeInitializeInvokeHandlers();
-  UnstartedRuntimeInitializeJNIHandlers();
+  InitializeInvokeHandlers();
+  InitializeJNIHandlers();
 
   tables_initialized_ = true;
 }
 
-void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item,
-                            ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item,
+                              ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // In a runtime that's not started we intercept certain methods to avoid complicated dependency
   // problems in core libraries.
   CHECK(tables_initialized_);
@@ -1294,8 +1200,8 @@
 }
 
 // Hand select a number of methods to be run in a not yet started runtime without using JNI.
-void UnstartedRuntimeJni(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
-                         uint32_t* args, JValue* result) {
+void UnstartedRuntime::Jni(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
+                           uint32_t* args, JValue* result) {
   std::string name(PrettyMethod(method));
   const auto& iter = jni_handlers_.find(name);
   if (iter != jni_handlers_.end()) {