Add new comparator function.
This one compares a DexProto with a list of method parameter types,
and it is immediately useful in the new getMethod() reflection code,
to avoid doing a bunch of extra string manipulation.
While I was in the territory, I removed some comment redundancy.
Change-Id: I5049e2ac4606e44a65c3c426ac2f880a891c51f9
diff --git a/libdex/DexProto.c b/libdex/DexProto.c
index 66d3e64..25ab400 100644
--- a/libdex/DexProto.c
+++ b/libdex/DexProto.c
@@ -122,19 +122,14 @@
return dexGetProtoId(pProto->dexFile, pProto->protoIdx);
}
-/*
- * Get the short-form method descriptor for the given prototype. The
- * prototype must be protoIdx-based.
- */
+/* (documented in header file) */
const char* dexProtoGetShorty(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
return dexStringById(pProto->dexFile, protoId->shortyIdx);
}
-/*
- * Get the full method descriptor for the given prototype.
- */
+/* (documented in header file) */
const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
DexStringCache* pCache) {
const DexFile* dexFile = pProto->dexFile;
@@ -169,10 +164,7 @@
return pCache->value;
}
-/*
- * Get a copy of the descriptor string associated with the given prototype.
- * The returned pointer must be free()ed by the caller.
- */
+/* (documented in header file) */
char* dexProtoCopyMethodDescriptor(const DexProto* pProto) {
DexStringCache cache;
@@ -181,11 +173,7 @@
dexProtoGetMethodDescriptor(pProto, &cache));
}
-/*
- * Get the parameter descriptors for the given prototype. This is the
- * concatenation of all the descriptors for all the parameters, in
- * order, with no other adornment.
- */
+/* (documented in header file) */
const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
DexStringCache* pCache) {
DexParameterIterator iterator;
@@ -220,17 +208,13 @@
return pCache->value;
}
-/*
- * Get the type descriptor for the return type of the given prototype.
- */
+/* (documented in header file) */
const char* dexProtoGetReturnType(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
return dexStringByTypeIdx(pProto->dexFile, protoId->returnTypeIdx);
}
-/*
- * Get the parameter count of the given prototype.
- */
+/* (documented in header file) */
size_t dexProtoGetParameterCount(const DexProto* pProto) {
const DexProtoId* protoId = getProtoId(pProto);
const DexTypeList* typeList =
@@ -238,12 +222,7 @@
return (typeList == NULL) ? 0 : typeList->size;
}
-/*
- * Compute the number of parameter words (u4 units) required by the
- * given prototype. For example, if the method takes (int, long) and
- * returns double, this would return 3 (one for the int, two for the
- * long, and the return type isn't relevant).
- */
+/* (documented in header file) */
int dexProtoComputeArgsSize(const DexProto* pProto) {
const char* shorty = dexProtoGetShorty(pProto);
int count = 0;
@@ -335,24 +314,12 @@
}
}
-/*
- * Compare the two prototypes. The two prototypes are compared
- * with the return type as the major order, then the first arguments,
- * then second, etc. If two prototypes are identical except that one
- * has extra arguments, then the shorter argument is considered the
- * earlier one in sort order (similar to strcmp()).
- */
+/* (documented in header file) */
int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2) {
return protoCompare(pProto1, pProto2, true);
}
-/*
- * Compare the two prototypes. The two prototypes are compared
- * with the first argument as the major order, then second, etc. If two
- * prototypes are identical except that one has extra arguments, then the
- * shorter argument is considered the earlier one in sort order (similar
- * to strcmp()).
- */
+/* (documented in header file) */
int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2){
return protoCompare(pProto1, pProto2, false);
}
@@ -404,34 +371,28 @@
}
/*
- * Compare a prototype and a string method descriptor. The comparison
- * is done as if the descriptor were converted to a prototype and compared
- * with dexProtoCompare().
+ * Common implementation for dexProtoCompareToDescriptor() and
+ * dexProtoCompareToParameterDescriptors(). The descriptor argument
+ * can be either a full method descriptor (with parens and a return
+ * type) or an unadorned concatenation of types (e.g. a list of
+ * argument types).
*/
-int dexProtoCompareToDescriptor(const DexProto* proto,
- const char* descriptor) {
- // First compare the return types.
-
- int result = strcmp(dexProtoGetReturnType(proto),
- methodDescriptorReturnType(descriptor));
-
- if (result != 0) {
- return result;
- }
-
- // The return types match, so we have to check arguments.
-
+static int protoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptor, bool expectParens) {
+ char expectedEndChar = expectParens ? ')' : '\0';
DexParameterIterator iterator;
dexParameterIteratorInit(&iterator, proto);
- // Skip the '('.
- assert (*descriptor == '(');
- descriptor++;
+ if (expectParens) {
+ // Skip the '('.
+ assert (*descriptor == '(');
+ descriptor++;
+ }
for (;;) {
const char* protoDesc = dexParameterIteratorNextDescriptor(&iterator);
- if (*descriptor == ')') {
+ if (*descriptor == expectedEndChar) {
// It's the end of the descriptor string.
if (protoDesc == NULL) {
// It's also the end of the prototype's arguments.
@@ -453,6 +414,7 @@
// Both prototype and descriptor have arguments. Compare them.
const char* nextDesc = methodDescriptorNextType(descriptor);
+ assert(nextDesc != NULL);
for (;;) {
char c1 = *(protoDesc++);
@@ -477,6 +439,34 @@
}
}
+/* (documented in header file) */
+int dexProtoCompareToDescriptor(const DexProto* proto,
+ const char* descriptor) {
+ // First compare the return types.
+
+ const char *returnType = methodDescriptorReturnType(descriptor);
+ assert(returnType != NULL);
+
+ int result = strcmp(dexProtoGetReturnType(proto), returnType);
+
+ if (result != 0) {
+ return result;
+ }
+
+ // The return types match, so we have to check arguments.
+ return protoCompareToParameterDescriptors(proto, descriptor, true);
+}
+
+/* (documented in header file) */
+int dexProtoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptors) {
+ return protoCompareToParameterDescriptors(proto, descriptors, false);
+}
+
+
+
+
+
/*
* ===========================================================================
diff --git a/libdex/DexProto.h b/libdex/DexProto.h
index 6e31648..50d4bf3 100644
--- a/libdex/DexProto.h
+++ b/libdex/DexProto.h
@@ -171,13 +171,14 @@
int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2);
/*
- * Compare the two prototypes. The two prototypes are compared
- * with the first argument as the major order, then second, etc. If two
- * prototypes are identical except that one has extra arguments, then the
- * shorter argument is considered the earlier one in sort order (similar
- * to strcmp()).
+ * Compare the two prototypes, ignoring return type. The two
+ * prototypes are compared with the first argument as the major order,
+ * then second, etc. If two prototypes are identical except that one
+ * has extra arguments, then the shorter argument is considered the
+ * earlier one in sort order (similar to strcmp()).
*/
-int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2);
+int dexProtoCompareParameters(const DexProto* pProto1,
+ const DexProto* pProto2);
/*
* Compare a prototype and a string method descriptor. The comparison
@@ -187,6 +188,14 @@
int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor);
/*
+ * Compare a prototype and a concatenation of type descriptors. The
+ * comparison is done as if the descriptors were converted to a
+ * prototype and compared with dexProtoCompareParameters().
+ */
+int dexProtoCompareToParameterDescriptors(const DexProto* proto,
+ const char* descriptors);
+
+/*
* Single-thread prototype parameter iterator. This structure holds a
* pointer to a prototype and its parts, along with a cursor.
*/
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index a881a92..48eb477 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -848,8 +848,7 @@
}
static Object* findConstructorOrMethodInArray(int methodsCount, Method* methods,
- const char* name, const char* parameterDescriptors,
- DexStringCache* stringCache)
+ const char* name, const char* parameterDescriptors)
{
Method* method = NULL;
Method* result = NULL;
@@ -859,8 +858,8 @@
method = &methods[i];
if (strcmp(name, method->name) != 0
|| dvmIsMirandaMethod(method)
- || strcmp(parameterDescriptors, dexProtoGetParameterDescriptors(
- &method->prototype, stringCache)) != 0) {
+ || dexProtoCompareToParameterDescriptors(&method->prototype,
+ parameterDescriptors) != 0) {
continue;
}
@@ -891,12 +890,10 @@
StringObject* nameObj, ArrayObject* args)
{
Object* result = NULL;
- DexStringCache stringCache;
DexStringCache targetDescriptorCache;
char* name;
const char* targetDescriptor;
- dexStringCacheInit(&stringCache);
dexStringCacheInit(&targetDescriptorCache);
name = dvmCreateCstrFromString(nameObj);
@@ -904,14 +901,13 @@
targetDescriptor = targetDescriptorCache.value;
result = findConstructorOrMethodInArray(clazz->directMethodCount,
- clazz->directMethods, name, targetDescriptor, &stringCache);
+ clazz->directMethods, name, targetDescriptor);
if (result == NULL) {
result = findConstructorOrMethodInArray(clazz->virtualMethodCount,
- clazz->virtualMethods, name, targetDescriptor, &stringCache);
+ clazz->virtualMethods, name, targetDescriptor);
}
free(name);
- dexStringCacheRelease(&stringCache);
dexStringCacheRelease(&targetDescriptorCache);
return result;
}