Implement the dalvik side of libcore.reflect.

(Cherry-pick of b4d5cf78d4731ffc6211d07a0d69c92c559ba792.)

Change-Id: I5d1b41f029c9c49a2d60a066a5fb0ed0f52f4b52
diff --git a/vm/DvmDex.h b/vm/DvmDex.h
index b3b5960..1785c26 100644
--- a/vm/DvmDex.h
+++ b/vm/DvmDex.h
@@ -21,6 +21,7 @@
 #ifndef DALVIK_DVMDEX_H_
 #define DALVIK_DVMDEX_H_
 
+#include "jni.h"
 #include "libdex/DexFile.h"
 
 /* extern */
@@ -61,6 +62,8 @@
     bool                isMappedReadOnly;
     MemMapping          memMap;
 
+    jobject dex_object;
+
     /* lock ensuring mutual exclusion during updates */
     pthread_mutex_t     modLock;
 };
diff --git a/vm/InitRefs.cpp b/vm/InitRefs.cpp
index 672abaa..9a04842 100644
--- a/vm/InitRefs.cpp
+++ b/vm/InitRefs.cpp
@@ -321,12 +321,12 @@
         { &gDvm.methJavaLangStackTraceElement_init, "Ljava/lang/StackTraceElement;",
           "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" },
         { &gDvm.methJavaLangReflectConstructor_init, "Ljava/lang/reflect/Constructor;",
-          "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V" },
+          "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;II)V" },
         { &gDvm.methJavaLangReflectField_init, "Ljava/lang/reflect/Field;",
-          "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V" },
+          "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;II)V" },
         { &gDvm.methJavaLangReflectMethod_init, "Ljava/lang/reflect/Method;",
           "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;"
-          "Ljava/lang/String;I)V" },
+          "Ljava/lang/String;II)V" },
         { &gDvm.methJavaNioDirectByteBuffer_init, "Ljava/nio/DirectByteBuffer;",
           "(JI)V" },
         { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
diff --git a/vm/native/java_lang_Class.cpp b/vm/native/java_lang_Class.cpp
index 93455e7..88d31ef 100644
--- a/vm/native/java_lang_Class.cpp
+++ b/vm/native/java_lang_Class.cpp
@@ -19,7 +19,7 @@
  */
 #include "Dalvik.h"
 #include "native/InternalNativePriv.h"
-
+#include "ScopedPthreadMutexLock.h"
 
 /*
  * native public boolean desiredAssertionStatus()
@@ -757,6 +757,52 @@
     }
 }
 
+JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass) {
+    Thread* self = dvmThreadSelf();
+    ClassObject* c = (ClassObject*) dvmDecodeIndirectRef(self, javaClass);
+
+    DvmDex* dvm_dex = c->pDvmDex;
+    if (dvm_dex == NULL) {
+        return NULL;
+    }
+
+    ScopedPthreadMutexLock lock(&dvm_dex->modLock);
+
+    // Already cached?
+    if (dvm_dex->dex_object != NULL) {
+        return dvm_dex->dex_object;
+    }
+
+    jobject byte_buffer = env->NewDirectByteBuffer(dvm_dex->memMap.addr, dvm_dex->memMap.length);
+    if (byte_buffer == NULL) {
+        return NULL;
+    }
+
+    jclass com_android_dex_Dex = env->FindClass("com/android/dex/Dex");
+    if (com_android_dex_Dex == NULL) {
+        return NULL;
+    }
+
+    jmethodID com_android_dex_Dex_create =
+            env->GetStaticMethodID(com_android_dex_Dex,
+                                   "<init>", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
+    if (com_android_dex_Dex_create == NULL) {
+        return NULL;
+    }
+
+    jvalue args[1];
+    args[0].l = byte_buffer;
+    jobject local_ref = env->CallStaticObjectMethodA(com_android_dex_Dex,
+                                                     com_android_dex_Dex_create,
+                                                     args);
+    if (local_ref == NULL) {
+        return NULL;
+    }
+
+    dvm_dex->dex_object = env->NewGlobalRef(local_ref);
+    return dvm_dex->dex_object;
+}
+
 const DalvikNativeMethod dvm_java_lang_Class[] = {
     { "desiredAssertionStatus", "()Z",
         Dalvik_java_lang_Class_desiredAssertionStatus },
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index 4e6103a..ca41157 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -306,6 +306,8 @@
     u4              accessFlags;
 };
 
+u4 dvmGetFieldIdx(const Field* field);
+
 /*
  * Static field.
  */
@@ -582,6 +584,8 @@
     bool            inProfile;
 };
 
+u4 dvmGetMethodIdx(const Method* method);
+
 
 /*
  * Find a method within a class.  The superclass is not searched.
diff --git a/vm/reflect/Annotation.cpp b/vm/reflect/Annotation.cpp
index bb1d2f5..942027c 100644
--- a/vm/reflect/Annotation.cpp
+++ b/vm/reflect/Annotation.cpp
@@ -1610,8 +1610,10 @@
  * out reasonably well because it's in sorted order, though we're still left
  * doing a fair number of string comparisons.
  */
-static u4 getMethodIdx(const Method* method)
+u4 dvmGetMethodIdx(const Method* method)
 {
+    if (method->clazz->pDvmDex == NULL) return 0;
+
     DexFile* pDexFile = method->clazz->pDvmDex->pDexFile;
     u4 hi = pDexFile->pHeader->methodIdsSize -1;
     u4 lo = 0;
@@ -1676,7 +1678,7 @@
              * find the method definition in the DEX file and perform string
              * comparisons on class name, method name, and signature.
              */
-            u4 methodIdx = getMethodIdx(method);
+            u4 methodIdx = dvmGetMethodIdx(method);
             u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir);
             u4 idx;
 
@@ -1918,10 +1920,12 @@
 /*
  * Given a field, determine the field's index.
  *
- * This has the same tradeoffs as getMethodIdx.
+ * This has the same tradeoffs as dvmGetMethodIdx.
  */
-static u4 getFieldIdx(const Field* field)
+u4 dvmGetFieldIdx(const Field* field)
 {
+    if (field->clazz->pDvmDex == NULL) return 0;
+
     DexFile* pDexFile = field->clazz->pDvmDex->pDexFile;
     u4 hi = pDexFile->pHeader->fieldIdsSize -1;
     u4 lo = 0;
@@ -1987,7 +1991,7 @@
      * find the field definition in the DEX file and perform string
      * comparisons on class name, field name, and signature.
      */
-    u4 fieldIdx = getFieldIdx(field);
+    u4 fieldIdx = dvmGetFieldIdx(field);
     u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir);
     u4 idx;
 
@@ -2169,7 +2173,7 @@
      * find the method definition in the DEX file and perform string
      * comparisons on class name, method name, and signature.
      */
-    u4 methodIdx = getMethodIdx(method);
+    u4 methodIdx = dvmGetMethodIdx(method);
     u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir);
     u4 idx;
 
diff --git a/vm/reflect/Reflect.cpp b/vm/reflect/Reflect.cpp
index 1d055c1..9cb9fc7 100644
--- a/vm/reflect/Reflect.cpp
+++ b/vm/reflect/Reflect.cpp
@@ -226,7 +226,7 @@
     ClassObject* type;
     char* mangle;
     char* cp;
-    int slot;
+    int slot, field_idx;
 
     assert(dvmIsClassInitialized(gDvm.classJavaLangReflectField));
 
@@ -245,10 +245,11 @@
         goto bail;
 
     slot = fieldToSlot(field, clazz);
+    field_idx = dvmGetFieldIdx(field);
 
     JValue unused;
     dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectField_init,
-        fieldObj, &unused, clazz, type, nameObj, slot);
+        fieldObj, &unused, clazz, type, nameObj, slot, field_idx);
     if (dvmCheckException(dvmThreadSelf())) {
         ALOGD("Field class init threw exception");
         goto bail;
@@ -393,7 +394,7 @@
     Object* consObj;
     DexStringCache mangle;
     char* cp;
-    int slot;
+    int slot, method_idx;
 
     dexStringCacheInit(&mangle);
 
@@ -425,10 +426,11 @@
         goto bail;
 
     slot = methodToSlot(meth);
+    method_idx = dvmGetMethodIdx(meth);
 
     JValue unused;
     dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectConstructor_init,
-        consObj, &unused, meth->clazz, params, exceptions, slot);
+        consObj, &unused, meth->clazz, params, exceptions, slot, method_idx);
     if (dvmCheckException(dvmThreadSelf())) {
         ALOGD("Constructor class init threw exception");
         goto bail;
@@ -532,7 +534,7 @@
     ClassObject* returnType;
     DexStringCache mangle;
     char* cp;
-    int slot;
+    int slot, method_idx;
 
     if (dvmCheckException(dvmThreadSelf())) {
         ALOGW("WARNING: dvmCreateReflectMethodObject called with "
@@ -577,11 +579,12 @@
         goto bail;
 
     slot = methodToSlot(meth);
+    method_idx = dvmGetMethodIdx(meth);
 
     JValue unused;
     dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectMethod_init,
         methObj, &unused, meth->clazz, params, exceptions, returnType,
-        nameObj, slot);
+        nameObj, slot, method_idx);
     if (dvmCheckException(dvmThreadSelf())) {
         ALOGD("Method class init threw exception");
         goto bail;