Merge branch 'readonly-p4-master'
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
index ee0847d..fffcec0 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -260,6 +260,13 @@
*/
public static native void dumpHprofData(String fileName) throws IOException;
+ /**
+ * Primes the register map cache.
+ *
+ * @hide
+ */
+ public static native boolean cacheRegisterMap(String classAndMethodDesc);
+
/* don't ask */
static native void printThis(Object thisThing, int count, int thing);
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index 5718507..3075530 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -998,7 +998,8 @@
* immediately. Otherwise, we expand the map and replace method's register
* map pointer, freeing it if it was allocated on the heap.
*
- * NOTE: this function is not synchronized; external locking is mandatory.
+ * NOTE: this function is not synchronized; external locking is mandatory
+ * (unless we're in the zygote, where single-threaded access is guaranteed).
*/
const RegisterMap* dvmGetExpandedRegisterMap0(Method* method)
{
@@ -1009,9 +1010,9 @@
return NULL;
/* sanity check to ensure this isn't called w/o external locking */
- /* (if we use it somewhere other than the GC, fix it) */
+ /* (if we use this at a time other than during GC, fix/remove this test) */
if (true) {
- if (pthread_mutex_trylock(&gDvm.gcHeapLock) == 0) {
+ if (!gDvm.zygote && pthread_mutex_trylock(&gDvm.gcHeapLock) == 0) {
LOGE("GLITCH: dvmGetExpandedRegisterMap not called at GC time\n");
dvmAbort();
}
@@ -1058,6 +1059,13 @@
}
#endif
+ IF_LOGV() {
+ char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+ LOGV("Expanding map -> %s.%s:%s\n",
+ method->clazz->descriptor, method->name, desc);
+ free(desc);
+ }
+
/*
* Update method, and free compressed map if it was sitting on the heap.
*/
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 },
};
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 39bd2c8..4ee0b37 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -4337,7 +4337,7 @@
if (method->registerMap != NULL) {
/* unexpected during class loading, okay on first use (uncompress) */
- LOGD("NOTE: registerMap already set for %s.%s\n",
+ LOGV("NOTE: registerMap already set for %s.%s\n",
method->clazz->descriptor, method->name);
/* keep going */
}