Determine direct method trampoline type from dispatch.

Change-Id: I7a8e577ad3cf622df06a70a2d4f12505b5e8383e
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 79fc790..e844421 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -321,38 +321,47 @@
   const char* shorty = linker->MethodShorty(method_idx, *caller_sp);
   size_t shorty_len = strlen(shorty);
   size_t args_in_regs = shorty_len < 3 ? shorty_len : 3;
+  bool is_static;
   if (type == Runtime::kUnknownMethod) {
     uint32_t dex_pc = (*caller_sp)->ToDexPC(caller_pc - 2);
-    UNIMPLEMENTED(WARNING) << "Missed argument handlerization in direct method trampoline. "
-        "Need to discover method invoke type at " << PrettyMethod(*caller_sp)
-        << " PC: " << (void*)dex_pc;
+    Method* caller = *caller_sp;
+    const DexFile& dex_file = Runtime::Current()->GetClassLinker()
+                                  ->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
+    const DexFile::CodeItem* code = dex_file.GetCodeItem(caller->GetCodeItemOffset());
+    CHECK_LT(dex_pc, code->insns_size_);
+    const Instruction* instr = Instruction::At(reinterpret_cast<const byte*>(&code->insns_[dex_pc]));
+    Instruction::Code instr_code = instr->Opcode();
+    is_static = (instr_code == Instruction::INVOKE_STATIC) ||
+                (instr_code == Instruction::INVOKE_STATIC_RANGE);
+    DCHECK(is_static || (instr_code == Instruction::INVOKE_DIRECT) ||
+           (instr_code == Instruction::INVOKE_DIRECT_RANGE));
   } else {
-    bool is_static = type == Runtime::kStaticMethod;
-    // Handlerize references in registers
-    int cur_arg = 1;   // skip method_idx in R0, first arg is in R1
-    if (!is_static) {
+    is_static = type == Runtime::kStaticMethod;
+  }
+  // Handlerize references in registers
+  int cur_arg = 1;   // skip method_idx in R0, first arg is in R1
+  if (!is_static) {
+    Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
+    cur_arg++;
+    AddLocalReference<jobject>(env, obj);
+  }
+  for(size_t i = 0; i < args_in_regs; i++) {
+    char c = shorty[i + 1];  // offset to skip return value
+    if (c == 'L') {
       Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
-      cur_arg++;
       AddLocalReference<jobject>(env, obj);
     }
-    for(size_t i = 0; i < args_in_regs; i++) {
-      char c = shorty[i + 1];  // offset to skip return value
-      if (c == 'L') {
-        Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
-        AddLocalReference<jobject>(env, obj);
-      }
-      cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
+    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
+  }
+  // Handlerize references in out going arguments
+  for(size_t i = 3; i < (shorty_len - 1); i++) {
+    char c = shorty[i + 1];  // offset to skip return value
+    if (c == 'L') {
+      // Plus 6 to skip args 1 to 3, LR and Method* plus the start offset of 3 to skip the spills
+      Object* obj = reinterpret_cast<Object*>(regs[i + 6]);
+      AddLocalReference<jobject>(env, obj);
     }
-    // Handlerize references in out going arguments
-    for(size_t i = 3; i < (shorty_len - 1); i++) {
-      char c = shorty[i + 1];  // offset to skip return value
-      if (c == 'L') {
-        // Plus 6 to skip args 1 to 3, LR and Method* plus the start offset of 3 to skip the spills
-        Object* obj = reinterpret_cast<Object*>(regs[i + 6]);
-        AddLocalReference<jobject>(env, obj);
-      }
-      cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
-    }
+    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
   }
   // Resolve method filling in dex cache
   Method* called = linker->ResolveMethod(method_idx, *caller_sp, true);