Static and direct resolution stub.

Ensure that invoke static and direct go through a stub that causes
resolution and initialization.

Change-Id: I872900560322817d8f4378b04ac410d9ea0b3b17
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index 75d60f5..772950c 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -9,6 +9,46 @@
 namespace art {
 namespace arm {
 
+ByteArray* ArmCreateResolutionTrampoline(bool is_static) {
+  UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
+  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
+
+  // | Out args |
+  // | Method*  | <- SP on entry
+  // | LR       |    return address into caller
+  // | R3       |    possible argument
+  // | R2       |    possible argument
+  // | R1       |    possible argument
+  // | R0       |    method index (loaded from code and method array - will be converted to Method*)
+  __ PushList(save);
+  __ mov(R1, ShifterOperand(SP));  // Pass address of saved R0... in R1
+  __ LoadFromOffset(kLoadWord, R12, TR,
+                    OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
+  __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
+  __ LoadImmediate(R3, is_static ? 1 : 0);
+  __ IncreaseFrameSize(12);        // 3 words of space for alignment
+  // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
+  __ blx(R12);
+  // Save code address returned into R12
+  __ mov(R12, ShifterOperand(R0));
+  // Restore registers which may have been modified by GC and R0 which will now hold the method*
+  __ DecreaseFrameSize(12);
+  __ PopList(save);
+  // Leaf call to method's code
+  __ mov(PC, ShifterOperand(R12));
+
+  __ bkpt(0);
+
+  assembler->EmitSlowPaths();
+  size_t cs = assembler->CodeSize();
+  ByteArray* resolution_trampoline = ByteArray::Alloc(cs);
+  CHECK(resolution_trampoline != NULL);
+  MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
+  assembler->FinalizeInstructions(code);
+
+  return resolution_trampoline;
+}
+
 typedef void (*ThrowAme)(Method*, Thread*);
 
 ByteArray* CreateAbstractMethodErrorStub() {