Filling in some Class, Method, and Field native code needed during startup and I/O

Change-Id: Ia2f2a0ec295d1bd848e6f65254bd9fec2fde56f6
diff --git a/Android.mk b/Android.mk
index abdcc06..ccf9b50 100644
--- a/Android.mk
+++ b/Android.mk
@@ -88,7 +88,7 @@
 	adb shell touch /sdcard/test-art-target-gtest
 	adb shell rm /sdcard/test-art-target-gtest
 	adb shell sh -c "$(foreach file,$(sort $(ART_TARGET_TEST_EXECUTABLES)), /system/bin/$(notdir $(file)) &&) touch /sdcard/test-art-target-gtest"
-	(adb pull /sdcard/test-art-target-gtest /tmp/ && echo test-art-target-gtest PASSED) || echo test-art-target-gtest FAILED
+	$(hide) (adb pull /sdcard/test-art-target-gtest /tmp/ && echo test-art-target-gtest PASSED) || echo test-art-target-gtest FAILED
 	$(hide) rm /tmp/test-art-target-gtest
 
 .PHONY: test-art-target-oat
@@ -99,7 +99,7 @@
 	adb shell touch /sdcard/test-art-target-oat-HelloWorld
 	adb shell rm /sdcard/test-art-target-oat-HelloWorld
 	adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootimage:/system/framework/boot.oat -classpath /system/framework/art-test-dex-HelloWorld.jar -Ximage:/system/framework/art-test-dex-HelloWorld.oat HelloWorld && touch /sdcard/test-art-target-oat-HelloWorld"
-	(adb pull /sdcard/test-art-target-oat-HelloWorld /tmp/ && echo test-art-target-oat-HelloWorld PASSED) || (echo test-art-target-oat-HelloWorld FAILED && exit 1)
+	$(hide) (adb pull /sdcard/test-art-target-oat-HelloWorld /tmp/ && echo test-art-target-oat-HelloWorld PASSED) || (echo test-art-target-oat-HelloWorld FAILED && exit 1)
 	$(hide) rm /tmp/test-art-target-oat-HelloWorld
 
 .PHONY: test-art-target-oat-Fibonacci
@@ -107,7 +107,7 @@
 	adb shell touch /sdcard/test-art-target-oat-Fibonacci
 	adb shell rm /sdcard/test-art-target-oat-Fibonacci
 	adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootimage:/system/framework/boot.oat -classpath /system/framework/art-test-dex-Fibonacci.jar -Ximage:/system/framework/art-test-dex-Fibonacci.oat Fibonacci 10 && touch /sdcard/test-art-target-oat-Fibonacci"
-	(adb pull /sdcard/test-art-target-oat-Fibonacci /tmp/ && echo test-art-target-oat-Fibonacci PASSED) || (echo test-art-target-oat-Fibonacci FAILED && exit 1)
+	$(hide) (adb pull /sdcard/test-art-target-oat-Fibonacci /tmp/ && echo test-art-target-oat-Fibonacci PASSED) || (echo test-art-target-oat-Fibonacci FAILED && exit 1)
 	$(hide) rm /tmp/test-art-target-oat-Fibonacci
 
 .PHONY: dump-boot-oat
diff --git a/build/Android.common.mk b/build/Android.common.mk
index b99a876..ae96dab 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -106,6 +106,8 @@
 	src/java_lang_System.cc \
 	src/java_lang_Thread.cc \
 	src/java_lang_Throwable.cc \
+	src/java_lang_reflect_Field.cc \
+	src/java_lang_reflect_Method.cc \
 	src/java_util_concurrent_atomic_AtomicLong.cc \
 	src/jni_compiler.cc \
 	src/jni_internal.cc \
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index 7648425..4bc1caa 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -60,6 +60,27 @@
   return env->NewObjectArray(0, java_lang_Class_class, NULL);
 }
 
+jobject Class_getDeclaredField(JNIEnv* env, jclass java_lang_Class_class, jclass jklass, jobject jname) {
+  Class* klass = Decode<Class*>(env, jklass);
+  DCHECK(klass->IsClass());
+  String* name = Decode<String*>(env, jname);
+  DCHECK(name->IsString());
+
+  for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
+    Field* f = klass->GetInstanceField(i);
+    if (f->GetName()->Equals(name)) {
+      return AddLocalReference<jclass>(env, f);
+    }
+  }
+  for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
+    Field* f = klass->GetStaticField(i);
+    if (f->GetName()->Equals(name)) {
+      return AddLocalReference<jclass>(env, f);
+    }
+  }
+  return NULL;
+}
+
 jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
   UNIMPLEMENTED(WARNING) << "needs annotations";
   return NULL;
@@ -148,7 +169,7 @@
   NATIVE_METHOD(Class, getDeclaredClasses, "(Ljava/lang/Class;Z)[Ljava/lang/Class;"),
   //NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
   //NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
-  //NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
   //NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
   //NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
   NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
new file mode 100644
index 0000000..528c09f
--- /dev/null
+++ b/src/java_lang_reflect_Field.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_internal.h"
+#include "class_linker.h"
+#include "object.h"
+
+#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+
+namespace art {
+
+namespace {
+
+jint Field_getFieldModifiers(JNIEnv* env, jobject jfield, jclass javaDeclaringClass, jint slot) {
+  return Decode<Object*>(env, jfield)->AsField()->GetAccessFlags() & kAccFieldFlagsMask;
+}
+
+static JNINativeMethod gMethods[] = {
+  //NATIVE_METHOD(Field, getAnnotation, "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
+  //NATIVE_METHOD(Field, getBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B"),
+  //NATIVE_METHOD(Field, getCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C"),
+  //NATIVE_METHOD(Field, getDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D"),
+  //NATIVE_METHOD(Field, getDeclaredAnnotations, "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;"),
+  //NATIVE_METHOD(Field, getFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F"),
+  //NATIVE_METHOD(Field, getField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+  NATIVE_METHOD(Field, getFieldModifiers, "(Ljava/lang/Class;I)I"),
+  //NATIVE_METHOD(Field, getIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I"),
+  //NATIVE_METHOD(Field, getJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J"),
+  //NATIVE_METHOD(Field, getSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S"),
+  //NATIVE_METHOD(Field, getSignatureAnnotation, "(Ljava/lang/Class;I)[Ljava/lang/Object;"),
+  //NATIVE_METHOD(Field, getZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z"),
+  //NATIVE_METHOD(Field, isAnnotationPresent, "(Ljava/lang/Class;ILjava/lang/Class;)Z"),
+  //NATIVE_METHOD(Field, setBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V"),
+  //NATIVE_METHOD(Field, setCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V"),
+  //NATIVE_METHOD(Field, setDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V"),
+  //NATIVE_METHOD(Field, setFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V"),
+  //NATIVE_METHOD(Field, setField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V"),
+  //NATIVE_METHOD(Field, setIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V"),
+  //NATIVE_METHOD(Field, setJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V"),
+  //NATIVE_METHOD(Field, setSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V"),
+  //NATIVE_METHOD(Field, setZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V"),
+};
+
+}  // namespace
+
+void register_java_lang_reflect_Field(JNIEnv* env) {
+  jniRegisterNativeMethods(env, "java/lang/reflect/Field", gMethods, NELEM(gMethods));
+}
+
+}  // namespace art
diff --git a/src/java_lang_reflect_Method.cc b/src/java_lang_reflect_Method.cc
new file mode 100644
index 0000000..c886f59
--- /dev/null
+++ b/src/java_lang_reflect_Method.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_internal.h"
+#include "class_linker.h"
+#include "object.h"
+
+#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+
+namespace art {
+
+namespace {
+
+
+// We move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
+// position, because the callers of this function are trying to convey
+// the "traditional" meaning of the flags to their callers.
+uint32_t FixupMethodFlags(uint32_t access_flags) {
+  access_flags &= ~kAccSynchronized;
+  if ((access_flags & kAccDeclaredSynchronized) != 0) {
+    access_flags |= kAccSynchronized;
+  }
+  return access_flags & kAccMethodFlagsMask;
+}
+
+jint Method_getMethodModifiers(JNIEnv* env, jclass, jclass javaDeclaringClass, jobject jmethod, jint slot) {
+  return FixupMethodFlags(Decode<Object*>(env, jmethod)->AsMethod()->GetAccessFlags());
+}
+
+static JNINativeMethod gMethods[] = {
+  //NATIVE_METHOD(Method, getAnnotation, "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
+  //NATIVE_METHOD(Method, getDeclaredAnnotations, "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;"),
+  //NATIVE_METHOD(Method, getDefaultValue, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
+  NATIVE_METHOD(Method, getMethodModifiers, "(Ljava/lang/Class;Ljava/lang/reflect/AccessibleObject;I)I"),
+  //NATIVE_METHOD(Method, getParameterAnnotations, "(Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;"),
+  //NATIVE_METHOD(Method, getSignatureAnnotation, "(Ljava/lang/Class;I)[Ljava/lang/Object;"),
+  //NATIVE_METHOD(Method, invokeNative, "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+  //NATIVE_METHOD(Method, isAnnotationPresent, "(Ljava/lang/Class;ILjava/lang/Class;)Z"),
+};
+
+}  // namespace
+
+void register_java_lang_reflect_Method(JNIEnv* env) {
+  jniRegisterNativeMethods(env, "java/lang/reflect/Method", gMethods, NELEM(gMethods));
+}
+
+}  // namespace art
diff --git a/src/oatexec.cc b/src/oatexec.cc
index 68c67e1..3730b43 100644
--- a/src/oatexec.cc
+++ b/src/oatexec.cc
@@ -30,7 +30,6 @@
     return false;
   }
   static const int PUBLIC = 0x0001;   // java.lang.reflect.Modifiers.PUBLIC
-#if 0 // reflect.Method.getModifiers not yet implemented
   jmethodID get_modifiers = env->GetMethodID(method.get(),
                                              "getModifiers",
                                              "()I");
@@ -39,10 +38,6 @@
     return false;
   }
   int modifiers = env->CallIntMethod(reflected.get(), get_modifiers);
-#else
-  int modifiers = PUBLIC;
-  UNIMPLEMENTED(WARNING) << "assuming main is public...";
-#endif
   if ((modifiers & PUBLIC) == 0) {
     return false;
   }
diff --git a/src/object.cc b/src/object.cc
index 8d3a94f..157bfc9 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -611,7 +611,7 @@
   if (have_executable_code && stub != NULL) {
     LOG(INFO) << "invoking " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
     (*stub)(this, receiver, self, args, result);
-    LOG(INFO) << "returning " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
+    LOG(INFO) << "returned " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
   } else {
     LOG(WARNING) << "Not invoking method with no associated code: " << PrettyMethod(this);
     if (result != NULL) {
diff --git a/src/runtime.cc b/src/runtime.cc
index e0a0b20..b9120fa 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -361,9 +361,20 @@
   // Finish attaching the main thread.
   Thread::Current()->CreatePeer("main", false);
 
+  RunImageClinits();
+
   StartDaemonThreads();
 }
 
+// initialize classes that have instances in the image but that have
+// <clinit> methods so they could not be initialized by the compiler.
+void Runtime::RunImageClinits() {
+  Class* Field_class = class_linker_->FindSystemClass("Ljava/lang/reflect/Field;");
+  CHECK(Field_class->FindDeclaredDirectMethod("<clinit>", "()V") != NULL);
+  class_linker_->EnsureInitialized(Field_class);
+  CHECK(!Thread::Current()->IsExceptionPending());
+}
+
 void Runtime::StartDaemonThreads() {
   signal_catcher_ = new SignalCatcher;
 
@@ -372,8 +383,6 @@
   Method* m = c->FindDirectMethod("start", "()V");
   CHECK(m != NULL);
 //  m->Invoke(Thread::Current(), NULL, NULL, NULL);
-
-  signal_catcher_->HandleSigQuit();
 }
 
 bool Runtime::IsStarted() {
@@ -458,8 +467,8 @@
   //REGISTER(register_java_lang_reflect_AccessibleObject);
   //REGISTER(register_java_lang_reflect_Array);
   //REGISTER(register_java_lang_reflect_Constructor);
-  //REGISTER(register_java_lang_reflect_Field);
-  //REGISTER(register_java_lang_reflect_Method);
+  REGISTER(register_java_lang_reflect_Field);
+  REGISTER(register_java_lang_reflect_Method);
   //REGISTER(register_java_lang_reflect_Proxy);
   REGISTER(register_java_util_concurrent_atomic_AtomicLong);
   //REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
diff --git a/src/runtime.h b/src/runtime.h
index 35f8ef7..6d11cf3 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -163,6 +163,7 @@
   bool Init(const Options& options, bool ignore_unrecognized);
   void InitLibraries();
   void RegisterRuntimeNativeMethods(JNIEnv*);
+  void RunImageClinits();
   void StartDaemonThreads();
 
   std::string boot_class_path_;