Implement Class.getDeclared(Constructors|Fields|Methods).

This required making sure that a Method* that represents a constructor
has java.lang.reflect.Constructor as its class.

Change-Id: I25908845a2b8d686d5404ac584693db0edd5853c
diff --git a/src/object.cc b/src/object.cc
index 7b47d9f..f47f16e 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -103,8 +103,24 @@
 }
 
 Class* Field::GetType() const {
-  // Do full linkage (which sets dex cache value to speed next call)
-  return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+  if (type_ == NULL) {
+    type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+  }
+  return type_;
+}
+
+void Field::InitJavaFields() {
+  Thread* self = Thread::Current();
+  ScopedThreadStateChange tsc(self, Thread::kRunnable);
+  MonitorEnter(self);
+  if (type_ == NULL) {
+    InitJavaFieldsLocked();
+  }
+  MonitorExit(self);
+}
+
+void Field::InitJavaFieldsLocked() {
+  GetType(); // Sets type_ as a side-effect. May throw.
 }
 
 Field* Field::FindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer) {
@@ -308,15 +324,23 @@
 }
 
 // TODO: get global references for these
+Class* Method::java_lang_reflect_Constructor_ = NULL;
 Class* Method::java_lang_reflect_Method_ = NULL;
 
-void Method::SetClass(Class* java_lang_reflect_Method) {
+void Method::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) {
+  CHECK(java_lang_reflect_Constructor_ == NULL);
+  CHECK(java_lang_reflect_Constructor != NULL);
+  java_lang_reflect_Constructor_ = java_lang_reflect_Constructor;
+
   CHECK(java_lang_reflect_Method_ == NULL);
   CHECK(java_lang_reflect_Method != NULL);
   java_lang_reflect_Method_ = java_lang_reflect_Method;
 }
 
-void Method::ResetClass() {
+void Method::ResetClasses() {
+  CHECK(java_lang_reflect_Constructor_ != NULL);
+  java_lang_reflect_Constructor_ = NULL;
+
   CHECK(java_lang_reflect_Method_ != NULL);
   java_lang_reflect_Method_ = NULL;
 }
@@ -648,7 +672,7 @@
        !iter.HasNext(); iter.Next()) {
     uint32_t iter_type_idx = iter.Get().type_idx_;
     // Catch all case
-    if(iter_type_idx == DexFile::kDexNoIndex) {
+    if (iter_type_idx == DexFile::kDexNoIndex) {
       return iter.Get().address_;
     }
     // Does this catch exception type apply?
@@ -1186,6 +1210,19 @@
   return Alloc(array_class, component_count, array_class->GetComponentSize());
 }
 
+bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+  Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
+      "length=%i; index=%i", length_, index);
+  return false;
+}
+
+bool Array::ThrowArrayStoreException(Object* object) const {
+  Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;",
+      "Can't store an element of type %s into an array of type %s",
+      PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
+  return false;
+}
+
 template<typename T>
 PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
   DCHECK(array_class_ != NULL);