Create proxy class, constructor, and methods.

This code compiles but has not been exercised. I still
need to wire in the code blocks and return types.

Change-Id: I1796103d3bc4fc3c863f95bdca4cfb9765d4b3b7
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6ad6543..99b5b0e 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1513,6 +1513,77 @@
   }
 }
 
+Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
+    ClassLoader* loader, ObjectArray<Method>* methods, ObjectArray<Object>* throws) {
+  Class* klass = AllocClass(GetClassRoot(kJavaLangClass), sizeof(ProxyClass));
+  CHECK(klass != NULL);
+  klass->SetObjectSize(sizeof(Proxy));
+  klass->SetDescriptor(intern_table_->InternStrong(name));
+  klass->SetAccessFlags(kAccPublic | kAccFinal);
+  klass->SetClassLoader(loader);
+  klass->SetStatus(Class::kStatusInitialized);
+  klass->SetInterfaces(interfaces);
+
+  klass->SetDirectMethods(AllocObjectArray<Method>(1));
+  klass->SetDirectMethod(0, CreateProxyConstructor(klass));
+
+  size_t num_virtual_methods = methods->GetLength();
+  klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
+  for (size_t i = 0; i < num_virtual_methods; ++i) {
+    Method* prototype = methods->Get(i);
+    klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype, throws->Get(i)));
+  }
+
+  if (!LinkMethods(klass)) {
+    DCHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+
+  return klass;
+}
+
+Method* ClassLinker::CreateProxyConstructor(Class* klass) {
+  Method* constructor = AllocMethod();
+  constructor->SetDeclaringClass(klass);
+  constructor->SetName(intern_table_->InternStrong("<init>"));
+  constructor->SetSignature(intern_table_->InternStrong("(Ljava/lang/reflect/InvocationHandler;)V"));
+  constructor->SetShorty(intern_table_->InternStrong("LV"));
+  constructor->SetAccessFlags(kAccPublic | kAccNative);
+
+  // TODO: return type
+  // TODO: code block
+
+  return constructor;
+}
+
+Method* ClassLinker::CreateProxyMethod(Class* klass, Method* prototype, Object* throws) {
+  Method* method = AllocMethod();
+  method->SetDeclaringClass(klass);
+  method->SetName(const_cast<String*>(prototype->GetName()));
+  method->SetSignature(const_cast<String*>(prototype->GetSignature()));
+  method->SetShorty(prototype->GetShorty());
+  method->SetAccessFlags(prototype->GetAccessFlags());
+  method->SetExceptionTypes(throws);
+
+  // TODO: return type
+  // method->SetReturnTypeIdx(dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_);
+
+  // TODO: code block
+  // method->SetCodeItemOffset(src.code_off_);
+  // method->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
+  // method->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
+  // method->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
+  // method->SetDexCacheResolvedFields(klass->GetDexCache()->GetResolvedFields());
+  // method->SetDexCacheCodeAndDirectMethods(klass->GetDexCache()->GetCodeAndDirectMethods());
+  // method->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
+  // method->SetNumRegisters(code_item->registers_size_);
+  // method->SetNumIns(code_item->ins_size_);
+  // method->SetNumOuts(code_item->outs_size_);
+  // LinkCode(method, oat_class.get(), method_index);
+
+  return method;
+}
+
 bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit) {
   CHECK(klass->IsResolved() || klass->IsErroneous())
       << PrettyClass(klass) << " is " << klass->GetStatus();