Generating stub code that throws AbstractMethodError exception when hit.

Change-Id: Ib440c0cb6e7f820fb1b73113763ebd2b7d64cdba
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a2e05c5..5b4c08c 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1612,9 +1612,6 @@
 
     // Link interface method tables
     LinkInterfaceMethods(klass);
-
-    // Insert stubs.
-    LinkAbstractMethods(klass);
   }
   return true;
 }
@@ -1797,16 +1794,6 @@
   return true;
 }
 
-void ClassLinker::LinkAbstractMethods(Class* klass) {
-  for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
-    Method* method = klass->GetVirtualMethodDuringLinking(i);
-    if (method->IsAbstract()) {
-      LG << "AbstractMethodError";
-      // TODO: throw AbstractMethodError
-    }
-  }
-}
-
 bool ClassLinker::LinkInstanceFields(Class* klass) {
   CHECK(klass != NULL);
   return LinkFields(klass, true);
diff --git a/src/class_linker.h b/src/class_linker.h
index b250593..88871f4 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -242,8 +242,6 @@
 
   bool LinkInterfaceMethods(Class* klass);
 
-  void LinkAbstractMethods(Class* klass);
-
   bool LinkStaticFields(Class* klass);
   bool LinkInstanceFields(Class* klass);
   bool LinkFields(Class *klass, bool instance);
diff --git a/src/compiler.cc b/src/compiler.cc
index e2768bf..fb510bb 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -14,6 +14,30 @@
 
 namespace art {
 
+typedef void (*ThrowAme)(Method*, Thread*);
+
+void ThrowAbstractMethodError(Method* method, Thread* thread) {
+  thread->ThrowNewException("Ljava/lang/AbstractMethodError",
+                            "abstract method \"%s\"",
+                            PrettyMethod(method).c_str());
+}
+
+namespace arm {
+  ByteArray* CreateAbstractMethodErrorStub(ThrowAme);
+}
+
+namespace x86 {
+  ByteArray* CreateAbstractMethodErrorStub(ThrowAme);
+}
+
+Compiler::Compiler(InstructionSet insns) : instruction_set_(insns), jni_compiler_(insns) {
+  if (insns == kArm || insns == kThumb2) {
+    abstract_method_error_stub_ = arm::CreateAbstractMethodErrorStub(&ThrowAbstractMethodError);
+  } else if (insns == kX86) {
+    abstract_method_error_stub_ = x86::CreateAbstractMethodErrorStub(&ThrowAbstractMethodError);
+  }
+}
+
 void Compiler::CompileAll(const ClassLoader* class_loader) {
   Resolve(class_loader);
   // TODO add verification step
@@ -107,13 +131,17 @@
   if (method->IsNative()) {
     jni_compiler_.Compile(method);
   } else if (method->IsAbstract()) {
-    // TODO: This might be also noted in the ClassLinker.
-    // Probably makes more sense to do here?
-    UNIMPLEMENTED(WARNING) << "compile stub to throw AbstractMethodError";
+    DCHECK(abstract_method_error_stub_ != NULL);
+    if (instruction_set_ == kX86) {
+      method->SetCode(abstract_method_error_stub_, kX86);
+    } else {
+      CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
+      method->SetCode(abstract_method_error_stub_, kArm);
+    }
   } else {
     oatCompileMethod(method, kThumb2);
   }
-  // CHECK(method->GetCode() != NULL);  // TODO: enable this check ASAP
+  CHECK(method->GetCode() != NULL);
 
   if (instruction_set_ == kX86) {
     art::x86::X86CreateInvokeStub(method);
diff --git a/src/compiler.h b/src/compiler.h
index e818a1c..24889e8 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,8 +12,7 @@
 
 class Compiler {
  public:
-  explicit Compiler(InstructionSet insns) : instruction_set_(insns),
-      jni_compiler_(insns) {}
+  explicit Compiler(InstructionSet insns);
 
   // Compile all Methods of all the Classes of all the DexFiles that are part of a ClassLoader.
   void CompileAll(const ClassLoader* class_loader);
@@ -40,6 +39,7 @@
 
   InstructionSet instruction_set_;
   JniCompiler jni_compiler_;
+  ByteArray* abstract_method_error_stub_;
 
   DISALLOW_COPY_AND_ASSIGN(Compiler);
 };
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 6784981..884f7a7 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -128,6 +128,10 @@
     EXPECT_TRUE(method != NULL) << "method_idx=" << i
                                 << " " << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
                                 << " " << dex->GetMethodName(dex->GetMethodId(i));
+    EXPECT_TRUE(method->GetCode() != NULL) << "method_idx=" << i
+                                           << " "
+                                           << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+                                           << " " << dex->GetMethodName(dex->GetMethodId(i));
   }
   EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index 2e2f6a6..7939780 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -9,6 +9,34 @@
 namespace art {
 namespace arm {
 
+typedef void (*ThrowAme)(Method*, Thread*);
+
+ByteArray* CreateAbstractMethodErrorStub(ThrowAme throw_ame) {
+  UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
+
+  // R0 is the Method* already.
+
+  // Pass Thread::Current() in R1
+  __ mov(R1, ShifterOperand(R9));
+
+  // Call throw_ame to throw AbstractMethodError
+  __ LoadImmediate(R12, reinterpret_cast<int32_t>(throw_ame));
+  // Leaf call to routine that never returns
+  __ mov(PC, ShifterOperand(R12));
+
+  __ bkpt(0);
+
+  assembler->EmitSlowPaths();
+
+  size_t cs = assembler->CodeSize();
+  ByteArray* abstract_stub = ByteArray::Alloc(cs);
+  CHECK(abstract_stub != NULL);
+  MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
+  assembler->FinalizeInstructions(code);
+
+  return abstract_stub;
+}
+
 ByteArray* CreateJniStub() {
   UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
 
diff --git a/src/stub_x86.cc b/src/stub_x86.cc
index bddfc6c..ce9a875 100644
--- a/src/stub_x86.cc
+++ b/src/stub_x86.cc
@@ -9,6 +9,35 @@
 namespace art {
 namespace x86 {
 
+typedef void (*ThrowAme)(Method*, Thread*);
+
+ByteArray* CreateAbstractMethodErrorStub(ThrowAme throw_ame) {
+  UniquePtr<X86Assembler> assembler( static_cast<X86Assembler*>(Assembler::Create(kX86)) );
+
+  // Pad stack to ensure 16-byte alignment
+  __ pushl(Immediate(0));
+  __ pushl(Immediate(0));
+  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // Thread*
+  __ pushl(EDI); // Method*
+
+  // Call throw_ame to throw AbstractMethodError
+  __ Call(reinterpret_cast<int32_t>(throw_ame), X86ManagedRegister::FromCpuRegister(ECX));
+
+  // Because the call above never returns, we do not need to do ESP+=16 here.
+
+  __ int3();
+
+  assembler->EmitSlowPaths();
+
+  size_t cs = assembler->CodeSize();
+  ByteArray* abstract_stub = ByteArray::Alloc(cs);
+  CHECK(abstract_stub != NULL);
+  MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
+  assembler->FinalizeInstructions(code);
+
+  return abstract_stub;
+}
+
 ByteArray* CreateJniStub() {
   UniquePtr<X86Assembler> assembler( static_cast<X86Assembler*>(Assembler::Create(kX86)) );