summaryrefslogtreecommitdiffstats
path: root/vm/reflect
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2011-02-22 20:20:36 -0800
committerJesse Wilson <jessewilson@google.com>2011-02-23 13:30:36 -0800
commit3c6f4c012e0a314dc9f9f540b9374dbf530d03b0 (patch)
treea8b909adb787ca7847a1d181a9996a0bbf00c868 /vm/reflect
parent6c360b86f5774376140636ff60ad4af3814fef21 (diff)
downloadandroid_dalvik-3c6f4c012e0a314dc9f9f540b9374dbf530d03b0.tar.gz
android_dalvik-3c6f4c012e0a314dc9f9f540b9374dbf530d03b0.tar.bz2
android_dalvik-3c6f4c012e0a314dc9f9f540b9374dbf530d03b0.zip
Optimize Class.getMethod() by loading only one method.
Change-Id: Ia2cd776c0a14914264e8d94e978d55854ed75623 http://b/3431686
Diffstat (limited to 'vm/reflect')
-rw-r--r--vm/reflect/Reflect.c100
-rw-r--r--vm/reflect/Reflect.h6
2 files changed, 106 insertions, 0 deletions
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index 2a7c74061..a881a92b3 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -817,6 +817,106 @@ fail:
}
/*
+ * Fills targetDescriptorCache with the descriptors of the classes in args.
+ * This is the concatenation of the descriptors with no other adornment,
+ * consistent with dexProtoGetParameterDescriptors.
+ */
+static void createTargetDescriptor(ArrayObject* args,
+ DexStringCache* targetDescriptorCache)
+{
+ size_t i;
+ ClassObject** argsArray = NULL;
+ size_t length;
+ char* at;
+ const char* descriptor;
+
+ argsArray = (ClassObject**) args->contents;
+
+ length = 1; /* +1 for the terminating '\0' */
+ for (i = 0; i < args->length; ++i) {
+ length += strlen(argsArray[i]->descriptor);
+ }
+
+ dexStringCacheAlloc(targetDescriptorCache, length);
+
+ at = (char*) targetDescriptorCache->value;
+ for (i = 0; i < args->length; ++i) {
+ descriptor = argsArray[i]->descriptor;
+ strcpy(at, descriptor);
+ at += strlen(descriptor);
+ }
+}
+
+static Object* findConstructorOrMethodInArray(int methodsCount, Method* methods,
+ const char* name, const char* parameterDescriptors,
+ DexStringCache* stringCache)
+{
+ Method* method = NULL;
+ Method* result = NULL;
+ int i;
+
+ for (i = 0; i < methodsCount; ++i) {
+ method = &methods[i];
+ if (strcmp(name, method->name) != 0
+ || dvmIsMirandaMethod(method)
+ || strcmp(parameterDescriptors, dexProtoGetParameterDescriptors(
+ &method->prototype, stringCache)) != 0) {
+ continue;
+ }
+
+ result = method;
+
+ /*
+ * Covariant return types permit the class to define multiple
+ * methods with the same name and parameter types. Prefer to return
+ * a non-synthetic method in such situations. We may still return
+ * a synthetic method to handle situations like escalated visibility.
+ */
+ if (!dvmIsSyntheticMethod(method)) {
+ break;
+ }
+ }
+
+ if (result != NULL) {
+ return dvmCreateReflectObjForMethod(result->clazz, result);
+ }
+
+ return NULL;
+}
+
+/*
+ * Get the named method.
+ */
+Object* dvmGetDeclaredConstructorOrMethod(ClassObject* clazz,
+ StringObject* nameObj, ArrayObject* args)
+{
+ Object* result = NULL;
+ DexStringCache stringCache;
+ DexStringCache targetDescriptorCache;
+ char* name;
+ const char* targetDescriptor;
+
+ dexStringCacheInit(&stringCache);
+ dexStringCacheInit(&targetDescriptorCache);
+
+ name = dvmCreateCstrFromString(nameObj);
+ createTargetDescriptor(args, &targetDescriptorCache);
+ targetDescriptor = targetDescriptorCache.value;
+
+ result = findConstructorOrMethodInArray(clazz->directMethodCount,
+ clazz->directMethods, name, targetDescriptor, &stringCache);
+ if (result == NULL) {
+ result = findConstructorOrMethodInArray(clazz->virtualMethodCount,
+ clazz->virtualMethods, name, targetDescriptor, &stringCache);
+ }
+
+ free(name);
+ dexStringCacheRelease(&stringCache);
+ dexStringCacheRelease(&targetDescriptorCache);
+ return result;
+}
+
+/*
* Get all interfaces a class implements. If this is unable to allocate
* the result array, this raises an OutOfMemoryError and returns NULL.
*/
diff --git a/vm/reflect/Reflect.h b/vm/reflect/Reflect.h
index c9a9a22ca..42b18c01b 100644
--- a/vm/reflect/Reflect.h
+++ b/vm/reflect/Reflect.h
@@ -51,6 +51,12 @@ ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly);
ArrayObject* dvmGetDeclaredMethods(ClassObject* clazz, bool publicOnly);
/*
+ * Get the named method.
+ */
+Object* dvmGetDeclaredConstructorOrMethod(ClassObject* clazz,
+ StringObject* nameObj, ArrayObject* args);
+
+/*
* Get all interfaces a class implements. If this is unable to allocate
* the result array, this raises an OutOfMemoryError and returns NULL.
*/