auto import //branches/master/...@140412
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index c7ab763..6dd2e8c 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -1721,7 +1721,39 @@
dvmLinearReadOnly(classLoader, newClass->ifields);
}
- /* load method definitions */
+ /*
+ * Load method definitions. We do this in two batches, direct then
+ * virtual.
+ *
+ * If register maps have already been generated for this class, and
+ * precise GC is enabled, we pull out pointers to them. We know that
+ * they were streamed to the DEX file in the same order in which the
+ * methods appear.
+ *
+ * If the class wasn't pre-verified, the maps will be generated when
+ * the class is verified during class initialization.
+ */
+ u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
+ const void* classMapData;
+ u4 numMethods;
+
+ if (gDvm.preciseGc) {
+ classMapData =
+ dvmGetRegisterMapClassData(pDexFile, classDefIdx, &numMethods);
+
+ /* sanity check */
+ if (classMapData != NULL &&
+ pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
+ {
+ LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
+ newClass->descriptor, pHeader->directMethodsSize,
+ pHeader->virtualMethodsSize, numMethods);
+ assert(false);
+ classMapData = NULL; /* abandon */
+ }
+ } else {
+ classMapData = NULL;
+ }
if (pHeader->directMethodsSize != 0) {
int count = (int) pHeader->directMethodsSize;
@@ -1734,6 +1766,15 @@
for (i = 0; i < count; i++) {
dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
+ if (classMapData != NULL) {
+ const RegisterMap* pMap = dvmGetNextRegisterMap(&classMapData);
+ if (dvmGetRegisterMapFormat(pMap) != kRegMapFormatNone) {
+ newClass->directMethods[i].registerMap = pMap;
+ /* TODO: add rigorous checks */
+ assert((newClass->directMethods[i].registersSize+7) / 8 ==
+ newClass->directMethods[i].registerMap->regWidth);
+ }
+ }
}
dvmLinearReadOnly(classLoader, newClass->directMethods);
}
@@ -1749,6 +1790,15 @@
for (i = 0; i < count; i++) {
dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
+ if (classMapData != NULL) {
+ const RegisterMap* pMap = dvmGetNextRegisterMap(&classMapData);
+ if (dvmGetRegisterMapFormat(pMap) != kRegMapFormatNone) {
+ newClass->virtualMethods[i].registerMap = pMap;
+ /* TODO: add rigorous checks */
+ assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
+ newClass->virtualMethods[i].registerMap->regWidth);
+ }
+ }
}
dvmLinearReadOnly(classLoader, newClass->virtualMethods);
}
@@ -1913,6 +1963,8 @@
/*
* Free anything in a Method that was allocated on the system heap.
+ *
+ * The containing class is largely torn down by this point.
*/
static void freeMethodInnards(Method* meth)
{
@@ -1920,26 +1972,31 @@
free(meth->exceptions);
free(meth->lines);
free(meth->locals);
-#else
- // TODO: call dvmFreeRegisterMap() if meth->registerMap was allocated
- // on the system heap
- UNUSED_PARAMETER(meth);
#endif
+
+ /*
+ * Some register maps are allocated on the heap, either because of late
+ * verification or because we're caching an uncompressed form.
+ */
+ const RegisterMap* pMap = meth->registerMap;
+ if (pMap != NULL && dvmGetRegisterMapOnHeap(pMap)) {
+ dvmFreeRegisterMap((RegisterMap*) pMap);
+ meth->registerMap = NULL;
+ }
}
/*
* Clone a Method, making new copies of anything that will be freed up
- * by freeMethodInnards().
+ * by freeMethodInnards(). This is used for "miranda" methods.
*/
static void cloneMethod(Method* dst, const Method* src)
{
+ if (src->registerMap != NULL) {
+ LOGE("GLITCH: only expected abstract methods here\n");
+ LOGE(" cloning %s.%s\n", src->clazz->descriptor, src->name);
+ dvmAbort();
+ }
memcpy(dst, src, sizeof(Method));
-#if 0
- /* for current usage, these are never set, so no need to implement copy */
- assert(dst->exceptions == NULL);
- assert(dst->lines == NULL);
- assert(dst->locals == NULL);
-#endif
}
/*
@@ -4270,9 +4327,9 @@
/*
* Add a RegisterMap to a Method. This is done when we verify the class
- * and compute the register maps at class initialization time, which means
- * that "pMap" is on the heap and should be freed when the Method is
- * discarded.
+ * and compute the register maps at class initialization time (i.e. when
+ * we don't have a pre-generated map). This means "pMap" is on the heap
+ * and should be freed when the Method is discarded.
*/
void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
{
@@ -4283,6 +4340,7 @@
method->clazz->descriptor, method->name);
/* keep going */
}
+ assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
/* might be virtual or direct */
dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);