AI 144931: Added a (hidden) way to "pre-cache" register maps.
  The 50 methods that appeared on the GC stacks of the most applications
  require 13KB of native heap for their uncompressed register maps, and
  the full set took 5ms to uncompress.  Pre-computation doesn't represent
  a significant improvement in space or time, at the cost of a big pile
  of strings in ZygoteInit.
  I'm leaving the method in ZygoteInit, but it's not called, and the
  static final String[] of method descriptors is empty.  We may want to
  revisit this later.
  BUG=1729570

Automated import of CL 144931
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index ec6d92e..d3d0d42 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -574,6 +574,118 @@
     RETURN_VOID();
 }
 
+/*
+ * static boolean cacheRegisterMap(String classAndMethodDescr)
+ *
+ * If the specified class is loaded, and the named method exists, ensure
+ * that the method's register map is ready for use.  If the class/method
+ * cannot be found, nothing happens.
+ *
+ * This can improve the zygote's sharing of compressed register maps.  Do
+ * this after class preloading.
+ *
+ * Returns true if the register map is cached and ready, either as a result
+ * of this call or earlier activity.  Returns false if the class isn't loaded,
+ * if the method couldn't be found, or if the method has no register map.
+ *
+ * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.)
+ */
+static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args,
+    JValue* pResult)
+{
+    StringObject* classAndMethodDescStr = (StringObject*) args[0];
+    ClassObject* clazz;
+    bool result = false;
+
+    if (classAndMethodDescStr == NULL) {
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        RETURN_VOID();
+    }
+
+    char* classAndMethodDesc = NULL;
+
+    /*
+     * Pick the string apart.  We have a local copy, so just modify it
+     * in place.
+     */
+    classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr);
+
+    char* methodName = strchr(classAndMethodDesc, '.');
+    if (methodName == NULL) {
+        dvmThrowException("Ljava/lang/RuntimeException;",
+            "method name not found in string");
+        RETURN_VOID();
+    }
+    *methodName++ = '\0';
+
+    char* methodDescr = strchr(methodName, ':');
+    if (methodDescr == NULL) {
+        dvmThrowException("Ljava/lang/RuntimeException;",
+            "method descriptor not found in string");
+        RETURN_VOID();
+    }
+    *methodDescr++ = '\0';
+
+    //LOGD("GOT: %s %s %s\n", classAndMethodDesc, methodName, methodDescr);
+
+    /*
+     * Find the class, but only if it's already loaded.
+     */
+    clazz = dvmLookupClass(classAndMethodDesc, NULL, false);
+    if (clazz == NULL) {
+        LOGD("Class %s not found in bootstrap loader\n", classAndMethodDesc);
+        goto bail;
+    }
+
+    Method* method;
+
+    /*
+     * Find the method, which could be virtual or direct, defined directly
+     * or inherited.
+     */
+    if (methodName[0] == '<') {
+        /*
+         * Constructor or class initializer.  Only need to examine the
+         * "direct" list, and don't need to search up the class hierarchy.
+         */
+        method = dvmFindDirectMethodByDescriptor(clazz, methodName,
+                    methodDescr);
+    } else {
+        /*
+         * Try both lists, and scan up the tree.
+         */
+        method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName,
+                    methodDescr);
+        if (method == NULL) {
+            method = dvmFindDirectMethodHierByDescriptor(clazz, methodName,
+                        methodDescr);
+        }
+    }
+
+    if (method != NULL) {
+        /*
+         * Got it.  See if there's a register map here.
+         */
+        const RegisterMap* pMap;
+        pMap = dvmGetExpandedRegisterMap(method);
+        if (pMap == NULL) {
+            LOGV("No map for %s.%s %s\n",
+                classAndMethodDesc, methodName, methodDescr);
+        } else {
+            LOGV("Found map %s.%s %s\n",
+                classAndMethodDesc, methodName, methodDescr);
+            result = true;
+        }
+    } else {
+        LOGV("Unable to find %s.%s %s\n",
+            classAndMethodDesc, methodName, methodDescr);
+    }
+
+bail:
+    free(classAndMethodDesc);
+    RETURN_BOOLEAN(result);
+}
+
 const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = {
     { "getAllocCount",              "(I)I",
         Dalvik_dalvik_system_VMDebug_getAllocCount },
@@ -621,6 +733,8 @@
         Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos },
     { "dumpHprofData",              "(Ljava/lang/String;)V",
         Dalvik_dalvik_system_VMDebug_dumpHprofData },
+    { "cacheRegisterMap",           "(Ljava/lang/String;)Z",
+        Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
     { NULL, NULL, NULL },
 };