method_handles: Complete support for emulated stack frames.

Most of this change is a refactor that templatizes the code
that performs argument conversions. This allows us to copy arguments
between two shadow frames, or an emulated stack frame and a shadow
frame.

Test: make test-art-host
Bug: 30550796

Change-Id: I23e65735a2dbd28f3c7b7d1ccf9762e77e0cf1f1
diff --git a/runtime/Android.bp b/runtime/Android.bp
index b498573..8f961af 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -123,6 +123,7 @@
         "mirror/array.cc",
         "mirror/class.cc",
         "mirror/dex_cache.cc",
+        "mirror/emulated_stack_frame.cc",
         "mirror/executable.cc",
         "mirror/field.cc",
         "mirror/method.cc",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7f15a16..4823caa 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -70,6 +70,7 @@
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache.h"
 #include "mirror/dex_cache-inl.h"
+#include "mirror/emulated_stack_frame.h"
 #include "mirror/field.h"
 #include "mirror/iftable-inl.h"
 #include "mirror/method.h"
@@ -650,6 +651,11 @@
   SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root);
   mirror::MethodHandleImpl::SetClass(class_root);
 
+  class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kDalvikSystemEmulatedStackFrame, class_root);
+  mirror::EmulatedStackFrame::SetClass(class_root);
+
   // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
   // finish initializing Reference class
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
@@ -1059,6 +1065,7 @@
   mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
   mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
   mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
+  mirror::EmulatedStackFrame::SetClass(GetClassRoot(kDalvikSystemEmulatedStackFrame));
 
   for (gc::space::ImageSpace* image_space : spaces) {
     // Boot class loader, use a null handle.
@@ -2038,6 +2045,7 @@
   mirror::ShortArray::ResetArrayClass();
   mirror::MethodType::ResetClass();
   mirror::MethodHandleImpl::ResetClass();
+  mirror::EmulatedStackFrame::ResetClass();
   Thread* const self = Thread::Current();
   for (const ClassLoaderData& data : class_loaders_) {
     DeleteClassLoader(self, data);
@@ -8050,6 +8058,7 @@
     "Ljava/lang/Throwable;",
     "Ljava/lang/ClassNotFoundException;",
     "Ljava/lang/StackTraceElement;",
+    "Ldalvik/system/EmulatedStackFrame;",
     "Z",
     "B",
     "C",
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index e99dfe3..3248d0e 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -109,6 +109,7 @@
     kJavaLangThrowable,
     kJavaLangClassNotFoundException,
     kJavaLangStackTraceElement,
+    kDalvikSystemEmulatedStackFrame,
     kPrimitiveBoolean,
     kPrimitiveByte,
     kPrimitiveChar,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index ab18627..5878bf3 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -31,6 +31,7 @@
 #include "mirror/accessible_object.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
+#include "mirror/emulated_stack_frame.h"
 #include "mirror/executable.h"
 #include "mirror/field.h"
 #include "mirror/method_type.h"
@@ -740,6 +741,15 @@
   }
 };
 
+struct EmulatedStackFrameOffsets : public CheckOffsets<mirror::EmulatedStackFrame> {
+  EmulatedStackFrameOffsets() : CheckOffsets<mirror::EmulatedStackFrame>(
+      false, "Ldalvik/system/EmulatedStackFrame;") {
+    addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, references_), "references");
+    addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, stack_frame_), "stackFrame");
+    addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, type_), "type");
+  }
+};
+
 // C++ fields must exactly match the fields in the Java classes. If this fails,
 // reorder the fields in the C++ class. Managed class fields are ordered by
 // ClassLinker::LinkFields.
@@ -760,6 +770,7 @@
   EXPECT_TRUE(ExecutableOffsets().Check());
   EXPECT_TRUE(MethodTypeOffsets().Check());
   EXPECT_TRUE(MethodHandleImplOffsets().Check());
+  EXPECT_TRUE(EmulatedStackFrameOffsets().Check());
 }
 
 TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 1ed3d55..34ccc13 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -27,6 +27,7 @@
 #include "method_handles-inl.h"
 #include "mirror/array-inl.h"
 #include "mirror/class.h"
+#include "mirror/emulated_stack_frame.h"
 #include "mirror/method_handle_impl.h"
 #include "reflection.h"
 #include "reflection-inl.h"
@@ -529,15 +530,19 @@
                                      ShadowFrame& shadow_frame,
                                      JValue* result,
                                      uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                     uint32_t vregC) ALWAYS_INLINE;
+                                     uint32_t vregC,
+                                     const MethodHandleKind handle_kind) ALWAYS_INLINE;
 
-REQUIRES_SHARED(Locks::mutator_lock_)
+template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
 static inline bool DoCallTransform(ArtMethod* called_method,
                                    Handle<mirror::MethodType> callsite_type,
+                                   Handle<mirror::MethodType> callee_type,
                                    Thread* self,
                                    ShadowFrame& shadow_frame,
                                    Handle<mirror::MethodHandleImpl> receiver,
-                                   JValue* result) ALWAYS_INLINE;
+                                   JValue* result,
+                                   uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                                   uint32_t vregC) ALWAYS_INLINE;
 
 REQUIRES_SHARED(Locks::mutator_lock_)
 inline void PerformCall(Thread* self,
@@ -683,9 +688,9 @@
   CHECK(handle_type.Get() != nullptr);
 
   uint32_t arg[Instruction::kMaxVarArgRegs] = {};
-  uint32_t receiver_vregC = 0;
+  uint32_t first_src_reg = 0;
   if (is_range) {
-    receiver_vregC = (inst->VRegC_4rcc() + 1);
+    first_src_reg = (inst->VRegC_4rcc() + 1);
   } else {
     inst->GetVarArgs(arg, inst_data);
     arg[0] = arg[1];
@@ -693,20 +698,15 @@
     arg[2] = arg[3];
     arg[3] = arg[4];
     arg[4] = 0;
-    receiver_vregC = arg[0];
+    first_src_reg = arg[0];
   }
 
   if (IsInvoke(handle_kind)) {
     if (handle_kind == kInvokeVirtual || handle_kind == kInvokeInterface) {
-      ObjPtr<mirror::Object> receiver = shadow_frame.GetVRegReference(receiver_vregC);
-      ObjPtr<mirror::Class> declaring_class = called_method->GetDeclaringClass();
-      // Verify that _vRegC is an object reference and of the type expected by
-      // the receiver.
-      called_method = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
-          called_method, kRuntimePointerSize);
-      if (!VerifyObjectIsClass(receiver, declaring_class)) {
-        return false;
-      }
+      // TODO: Unfortunately, we have to postpone dynamic receiver based checks
+      // because the receiver might be cast or might come from an emulated stack
+      // frame, which means that it is unknown at this point. We perform these
+      // checks inside DoCallPolymorphic right before we do the actualy invoke.
     } else if (handle_kind == kInvokeDirect) {
       if (called_method->IsConstructor()) {
         // TODO(narayan) : We need to handle the case where the target method is a
@@ -744,12 +744,15 @@
     }
 
     if (handle_kind == kInvokeTransform) {
-      return DoCallTransform(called_method,
-                             callsite_type,
-                             self,
-                             shadow_frame,
-                             method_handle /* receiver */,
-                             result);
+      return DoCallTransform<is_range>(called_method,
+                                       callsite_type,
+                                       handle_type,
+                                       self,
+                                       shadow_frame,
+                                       method_handle /* receiver */,
+                                       result,
+                                       arg,
+                                       first_src_reg);
     } else {
       return DoCallPolymorphic<is_range>(called_method,
                                          callsite_type,
@@ -758,7 +761,8 @@
                                          shadow_frame,
                                          result,
                                          arg,
-                                         receiver_vregC);
+                                         first_src_reg,
+                                         handle_kind);
     }
   } else {
     // TODO(narayan): Implement field getters and setters.
@@ -860,7 +864,8 @@
                                      ShadowFrame& shadow_frame,
                                      JValue* result,
                                      uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                     uint32_t first_src_reg) {
+                                     uint32_t first_src_reg,
+                                     const MethodHandleKind handle_kind) {
   // TODO(narayan): Wire in the String.init hacks.
 
   // Compute method information.
@@ -893,6 +898,8 @@
       CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0);
   ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
 
+  // Whether this polymorphic invoke was issued by a transformer method.
+  bool is_caller_transformer = false;
   // Thread might be suspended during PerformArgumentConversions due to the
   // allocations performed during boxing.
   {
@@ -914,18 +921,16 @@
       // case, we'll have to unmarshal the EmulatedStackFrame into the
       // new_shadow_frame and perform argument conversions on it.
       if (IsCallerTransformer(callsite_type)) {
-        // The emulated stack frame will be the first ahnd only argument
-        // when we're coming through from a transformer.
-        //
-        // TODO(narayan): This should be a mirror::EmulatedStackFrame after that
-        // type is introduced.
-        ObjPtr<mirror::Object> emulated_stack_frame(
-            shadow_frame.GetVRegReference(first_src_reg));
-        if (!ConvertAndCopyArgumentsFromEmulatedStackFrame<is_range>(self,
-                                                                     emulated_stack_frame,
-                                                                     target_type,
-                                                                     first_dest_reg,
-                                                                     new_shadow_frame)) {
+        is_caller_transformer = true;
+        // The emulated stack frame is the first and only argument when we're coming
+        // through from a transformer.
+        ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
+            reinterpret_cast<mirror::EmulatedStackFrame*>(
+                shadow_frame.GetVRegReference(first_src_reg)));
+        if (!emulated_stack_frame->WriteToShadowFrame(self,
+                                                      target_type,
+                                                      first_dest_reg,
+                                                      new_shadow_frame)) {
           DCHECK(self->IsExceptionPending());
           result->SetL(0);
           return false;
@@ -945,20 +950,51 @@
     }
   }
 
+  // See TODO in DoInvokePolymorphic : We need to perform this dynamic, receiver
+  // based dispatch right before we perform the actual call, because the
+  // receiver isn't known very early.
+  if (handle_kind == kInvokeVirtual || handle_kind == kInvokeInterface) {
+    ObjPtr<mirror::Object> receiver(new_shadow_frame->GetVRegReference(first_dest_reg));
+    ObjPtr<mirror::Class> declaring_class(called_method->GetDeclaringClass());
+    // Verify that _vRegC is an object reference and of the type expected by
+    // the receiver.
+    if (!VerifyObjectIsClass(receiver, declaring_class)) {
+      DCHECK(self->IsExceptionPending());
+      return false;
+    }
+
+    called_method = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
+        called_method, kRuntimePointerSize);
+  }
+
   PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
 
   // TODO(narayan): Perform return value conversions.
 
+  // If the caller of this signature polymorphic method was a transformer,
+  // we need to copy the result back out to the emulated stack frame.
+  if (is_caller_transformer && !self->IsExceptionPending()) {
+    ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
+        reinterpret_cast<mirror::EmulatedStackFrame*>(
+            shadow_frame.GetVRegReference(first_src_reg)));
+
+    emulated_stack_frame->SetReturnValue(self, *result);
+  }
+
   return !self->IsExceptionPending();
 }
 
+template <bool is_range>
 static inline bool DoCallTransform(ArtMethod* called_method,
                                    Handle<mirror::MethodType> callsite_type,
+                                   Handle<mirror::MethodType> callee_type,
                                    Thread* self,
                                    ShadowFrame& shadow_frame,
                                    Handle<mirror::MethodHandleImpl> receiver,
-                                   JValue* result) {
-  // This can be fixed, because the method we're calling here
+                                   JValue* result,
+                                   uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                                   uint32_t first_src_reg) {
+  // This can be fixed to two, because the method we're calling here
   // (MethodHandle.transformInternal) doesn't have any locals and the signature
   // is known :
   //
@@ -978,18 +1014,33 @@
       CREATE_SHADOW_FRAME(kNumRegsForTransform, &shadow_frame, called_method, /* dex pc */ 0);
   ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
 
-  // TODO(narayan): Perform argument conversions first (if this is an inexact invoke), and
-  // then construct an argument list object that's passed through to the
-  // method. Note that the ArgumentList reference is currently a nullptr.
-  //
-  // NOTE(narayan): If the caller is a transformer method (i.e, there is only
-  // one argument and its type is EmulatedStackFrame), we can directly pass that
-  // through without having to do any additional work.
-  UNUSED(callsite_type);
+  StackHandleScope<1> hs(self);
+  MutableHandle<mirror::EmulatedStackFrame> sf(hs.NewHandle<mirror::EmulatedStackFrame>(nullptr));
+  if (IsCallerTransformer(callsite_type)) {
+    // If we're entering this transformer from another transformer, we can pass
+    // through the handle directly to the callee, instead of having to
+    // instantiate a new stack frame based on the shadow frame.
+    sf.Assign(reinterpret_cast<mirror::EmulatedStackFrame*>(
+        shadow_frame.GetVRegReference(first_src_reg)));
+  } else {
+    sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs<is_range>(
+        self,
+        callsite_type,
+        callee_type,
+        shadow_frame,
+        first_src_reg,
+        arg));
+
+    // Something went wrong while creating the emulated stack frame, we should
+    // throw the pending exception.
+    if (sf.Get() == nullptr) {
+      DCHECK(self->IsExceptionPending());
+      return false;
+    }
+  }
 
   new_shadow_frame->SetVRegReference(0, receiver.Get());
-  // TODO(narayan): This is the EmulatedStackFrame, currently nullptr.
-  new_shadow_frame->SetVRegReference(1, nullptr);
+  new_shadow_frame->SetVRegReference(1, sf.Get());
 
   PerformCall(self,
               code_item,
@@ -998,6 +1049,12 @@
               new_shadow_frame,
               result);
 
+  // If the called transformer method we called has returned a value, then we
+  // need to copy it back to |result|.
+  if (!self->IsExceptionPending()) {
+    sf->GetReturnValue(self, result);
+  }
+
   return !self->IsExceptionPending();
 }
 
diff --git a/runtime/method_handles-inl.h b/runtime/method_handles-inl.h
index b488133..ff5d2a1 100644
--- a/runtime/method_handles-inl.h
+++ b/runtime/method_handles-inl.h
@@ -64,44 +64,11 @@
   }
 }
 
-// A convenience class that allows for iteration through a list of
-// input argument registers |arg| for non-range invokes or a list of
-// consecutive registers starting with a given based for range
-// invokes.
-template <bool is_range> class ArgIterator {
- public:
-  ArgIterator(size_t first_src_reg,
-              const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) :
-      first_src_reg_(first_src_reg),
-      arg_(arg),
-      arg_index_(0) {
-  }
-
-  uint32_t Next() {
-    const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
-    ++arg_index_;
-
-    return next;
-  }
-
-  uint32_t NextPair() {
-    const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
-    arg_index_ += 2;
-
-    return next;
-  }
-
- private:
-  const size_t first_src_reg_;
-  const uint32_t (&arg_)[Instruction::kMaxVarArgRegs];
-  size_t arg_index_;
-};
-
 REQUIRES_SHARED(Locks::mutator_lock_)
-bool ConvertJValue(Handle<mirror::Class> from,
-                   Handle<mirror::Class> to,
-                   const JValue& from_value,
-                   JValue* to_value) {
+inline bool ConvertJValue(Handle<mirror::Class> from,
+                          Handle<mirror::Class> to,
+                          const JValue& from_value,
+                          JValue* to_value) {
   const Primitive::Type from_type = from->GetPrimitiveType();
   const Primitive::Type to_type = to->GetPrimitiveType();
 
@@ -161,6 +128,66 @@
   return true;
 }
 
+template <typename G, typename S>
+bool PerformConversions(Thread* self,
+                        Handle<mirror::ObjectArray<mirror::Class>> from_types,
+                        Handle<mirror::ObjectArray<mirror::Class>> to_types,
+                        G* getter,
+                        S* setter,
+                        int32_t num_conversions) {
+  StackHandleScope<2> hs(self);
+  MutableHandle<mirror::Class> from(hs.NewHandle<mirror::Class>(nullptr));
+  MutableHandle<mirror::Class> to(hs.NewHandle<mirror::Class>(nullptr));
+
+  for (int32_t i = 0; i < num_conversions; ++i) {
+    from.Assign(from_types->GetWithoutChecks(i));
+    to.Assign(to_types->GetWithoutChecks(i));
+
+    const Primitive::Type from_type = from->GetPrimitiveType();
+    const Primitive::Type to_type = to->GetPrimitiveType();
+
+    if (from.Get() == to.Get()) {
+      // Easy case - the types are identical. Nothing left to do except to pass
+      // the arguments along verbatim.
+      if (Primitive::Is64BitType(from_type)) {
+        setter->SetLong(getter->GetLong());
+      } else if (from_type == Primitive::kPrimNot) {
+        setter->SetReference(getter->GetReference());
+      } else {
+        setter->Set(getter->Get());
+      }
+
+      continue;
+    } else {
+      JValue from_value;
+      JValue to_value;
+
+      if (Primitive::Is64BitType(from_type)) {
+        from_value.SetJ(getter->GetLong());
+      } else if (from_type == Primitive::kPrimNot) {
+        from_value.SetL(getter->GetReference());
+      } else {
+        from_value.SetI(getter->Get());
+      }
+
+      if (!ConvertJValue(from, to, from_value, &to_value)) {
+        DCHECK(self->IsExceptionPending());
+        return false;
+      }
+
+      if (Primitive::Is64BitType(to_type)) {
+        setter->SetLong(to_value.GetJ());
+      } else if (to_type == Primitive::kPrimNot) {
+        setter->SetReference(to_value.GetL());
+      } else {
+        setter->Set(to_value.GetI());
+      }
+    }
+  }
+
+  return true;
+}
+
 template <bool is_range>
 bool ConvertAndCopyArgumentsFromCallerFrame(Thread* self,
                                             Handle<mirror::MethodType> callsite_type,
@@ -180,89 +207,17 @@
     return false;
   }
 
-  ArgIterator<is_range> input_args(first_src_reg, arg);
-  size_t to_arg_index = 0;
-  MutableHandle<mirror::Class> from(hs.NewHandle<mirror::Class>(nullptr));
-  MutableHandle<mirror::Class> to(hs.NewHandle<mirror::Class>(nullptr));
-  for (int32_t i = 0; i < num_method_params; ++i) {
-    from.Assign(from_types->GetWithoutChecks(i));
-    to.Assign(to_types->GetWithoutChecks(i));
+  ShadowFrameGetter<is_range> getter(first_src_reg, arg, caller_frame);
+  ShadowFrameSetter setter(callee_frame, first_dest_reg);
 
-    const Primitive::Type from_type = from->GetPrimitiveType();
-    const Primitive::Type to_type = to->GetPrimitiveType();
-
-    // Easy case - the types are identical. Nothing left to do except to pass
-    // the arguments along verbatim.
-    if (from.Get() == to.Get()) {
-      interpreter::AssignRegister(callee_frame,
-                                  caller_frame,
-                                  first_dest_reg + to_arg_index,
-                                  input_args.Next());
-      ++to_arg_index;
-
-      // This is a wide argument, we must use the second half of the register
-      // pair as well.
-      if (Primitive::Is64BitType(from_type)) {
-        interpreter::AssignRegister(callee_frame,
-                                    caller_frame,
-                                    first_dest_reg + to_arg_index,
-                                    input_args.Next());
-        ++to_arg_index;
-      }
-
-      continue;
-    } else {
-      JValue from_value;
-      JValue to_value;
-
-      if (Primitive::Is64BitType(from_type)) {
-        from_value.SetJ(caller_frame.GetVRegLong(input_args.NextPair()));
-      } else if (from_type == Primitive::kPrimNot) {
-        from_value.SetL(caller_frame.GetVRegReference(input_args.Next()));
-      } else {
-        from_value.SetI(caller_frame.GetVReg(input_args.Next()));
-      }
-
-      if (!ConvertJValue(from, to, from_value, &to_value)) {
-        DCHECK(self->IsExceptionPending());
-        return false;
-      }
-
-      if (Primitive::Is64BitType(to_type)) {
-        callee_frame->SetVRegLong(first_dest_reg + to_arg_index, to_value.GetJ());
-        to_arg_index += 2;
-      } else if (to_type == Primitive::kPrimNot) {
-        callee_frame->SetVRegReference(first_dest_reg + to_arg_index, to_value.GetL());
-        ++to_arg_index;
-      } else {
-        callee_frame->SetVReg(first_dest_reg + to_arg_index, to_value.GetI());
-        ++to_arg_index;
-      }
-    }
-  }
-
-  return true;
+  return PerformConversions<ShadowFrameGetter<is_range>, ShadowFrameSetter>(self,
+                                                                            from_types,
+                                                                            to_types,
+                                                                            &getter,
+                                                                            &setter,
+                                                                            num_method_params);
 }
 
-// Similar to |ConvertAndCopyArgumentsFromCallerFrame|, except that the
-// arguments are copied from an |EmulatedStackFrame|.
-template <bool is_range>
-bool ConvertAndCopyArgumentsFromEmulatedStackFrame(Thread* self,
-                                                   ObjPtr<mirror::Object> emulated_stack_frame,
-                                                   Handle<mirror::MethodType> callee_type,
-                                                   const uint32_t first_dest_reg,
-                                                   ShadowFrame* callee_frame) {
-  UNUSED(self);
-  UNUSED(emulated_stack_frame);
-  UNUSED(callee_type);
-  UNUSED(first_dest_reg);
-  UNUSED(callee_frame);
-
-  UNIMPLEMENTED(FATAL) << "ConvertAndCopyArgumentsFromEmulatedStackFrame is unimplemented";
-  return false;
-}
-
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_METHOD_HANDLES_INL_H_
diff --git a/runtime/method_handles.h b/runtime/method_handles.h
index 5175dce..0d3f9f1 100644
--- a/runtime/method_handles.h
+++ b/runtime/method_handles.h
@@ -59,16 +59,66 @@
 // Performs a single argument conversion from type |from| to a distinct
 // type |to|. Returns true on success, false otherwise.
 REQUIRES_SHARED(Locks::mutator_lock_)
-bool ConvertJValue(Handle<mirror::Class> from,
-                   Handle<mirror::Class> to,
-                   const JValue& from_value,
-                   JValue* to_value) ALWAYS_INLINE;
+inline bool ConvertJValue(Handle<mirror::Class> from,
+                          Handle<mirror::Class> to,
+                          const JValue& from_value,
+                          JValue* to_value) ALWAYS_INLINE;
 
 // Perform argument conversions between |callsite_type| (the type of the
 // incoming arguments) and |callee_type| (the type of the method being
 // invoked). These include widening and narrowing conversions as well as
 // boxing and unboxing. Returns true on success, on false on failure. A
 // pending exception will always be set on failure.
+//
+// The values to be converted are read from an input source (of type G)
+// that provides three methods :
+//
+// class G {
+//   // Used to read the next boolean/short/int or float value from the
+//   // source.
+//   uint32_t Get();
+//
+//   // Used to the read the next reference value from the source.
+//   ObjPtr<mirror::Object> GetReference();
+//
+//   // Used to read the next double or long value from the source.
+//   int64_t GetLong();
+// }
+//
+// After conversion, the values are written to an output sink (of type S)
+// that provides three methods :
+//
+// class S {
+//   void Set(uint32_t);
+//   void SetReference(ObjPtr<mirror::Object>)
+//   void SetLong(int64_t);
+// }
+//
+// The semantics and usage of the Set methods are analagous to the getter
+// class.
+//
+// This method is instantiated in three different scenarions :
+// - <S = ShadowFrameSetter, G = ShadowFrameGetter> : copying from shadow
+//   frame to shadow frame, used in a regular polymorphic non-exact invoke.
+// - <S = EmulatedShadowFrameAccessor, G = ShadowFrameGetter> : entering into
+//   a transformer method from a polymorphic invoke.
+// - <S = ShadowFrameStter, G = EmulatedStackFrameAccessor> : entering into
+//   a regular poly morphic invoke from a transformer method.
+//
+// TODO(narayan): If we find that the instantiations of this function take
+// up too much space, we can make G / S abstract base classes that are
+// overridden by concrete classes.
+template <typename G, typename S>
+REQUIRES_SHARED(Locks::mutator_lock_)
+bool PerformConversions(Thread* self,
+                        Handle<mirror::ObjectArray<mirror::Class>> from_types,
+                        Handle<mirror::ObjectArray<mirror::Class>> to_types,
+                        G* getter,
+                        S* setter,
+                        int32_t num_conversions);
+
+// A convenience wrapper around |PerformConversions|, for the case where
+// the setter and getter are both ShadowFrame based.
 template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
 bool ConvertAndCopyArgumentsFromCallerFrame(Thread* self,
                                             Handle<mirror::MethodType> callsite_type,
@@ -79,15 +129,80 @@
                                             const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
                                             ShadowFrame* callee_frame);
 
-// Similar to |ConvertAndCopyArgumentsFromCallerFrame|, except that the
-// arguments are copied from an |EmulatedStackFrame|.
-template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
-bool ConvertAndCopyArgumentsFromEmulatedStackFrame(Thread* self,
-                                                   ObjPtr<mirror::Object> emulated_stack_frame,
-                                                   Handle<mirror::MethodType> callee_type,
-                                                   const uint32_t first_dest_reg,
-                                                   ShadowFrame* callee_frame);
+// A convenience class that allows for iteration through a list of
+// input argument registers |arg| for non-range invokes or a list of
+// consecutive registers starting with a given based for range
+// invokes.
+//
+// This is used to iterate over input arguments while performing standard
+// argument conversions.
+template <bool is_range> class ShadowFrameGetter {
+ public:
+  ShadowFrameGetter(size_t first_src_reg,
+                    const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                    const ShadowFrame& shadow_frame) :
+      first_src_reg_(first_src_reg),
+      arg_(arg),
+      shadow_frame_(shadow_frame),
+      arg_index_(0) {
+  }
 
+  ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
+    const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
+    ++arg_index_;
+
+    return shadow_frame_.GetVReg(next);
+  }
+
+  ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
+    const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
+    arg_index_ += 2;
+
+    return shadow_frame_.GetVRegLong(next);
+  }
+
+  ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
+    const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
+    ++arg_index_;
+
+    return shadow_frame_.GetVRegReference(next);
+  }
+
+ private:
+  const size_t first_src_reg_;
+  const uint32_t (&arg_)[Instruction::kMaxVarArgRegs];
+  const ShadowFrame& shadow_frame_;
+  size_t arg_index_;
+};
+
+// A convenience class that allows values to be written to a given shadow frame,
+// starting at location |first_dst_reg|.
+class ShadowFrameSetter {
+ public:
+  ShadowFrameSetter(ShadowFrame* shadow_frame,
+                    size_t first_dst_reg) :
+    shadow_frame_(shadow_frame),
+    arg_index_(first_dst_reg) {
+  }
+
+  ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame_->SetVReg(arg_index_++, value);
+  }
+
+  ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> value)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame_->SetVRegReference(arg_index_++, value.Ptr());
+  }
+
+  ALWAYS_INLINE void SetLong(int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame_->SetVRegLong(arg_index_, value);
+    arg_index_ += 2;
+  }
+
+ private:
+  ShadowFrame* shadow_frame_;
+  size_t arg_index_;
+};
 
 }  // namespace art
 
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index f5d1b80..1ae694d 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -74,6 +74,7 @@
   static GcRoot<T> Lookup(std::atomic<DexCachePair<T>>* dex_cache,
                           uint32_t idx,
                           uint32_t cache_size) {
+    DCHECK_NE(cache_size, 0u);
     DexCachePair<T> element = dex_cache[idx % cache_size].load(std::memory_order_relaxed);
     if (idx != element.index) {
       return GcRoot<T>(nullptr);
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
new file mode 100644
index 0000000..4ba71ea
--- /dev/null
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "emulated_stack_frame.h"
+
+#include "class-inl.h"
+#include "gc_root-inl.h"
+#include "jvalue-inl.h"
+#include "method_handles.h"
+#include "method_handles-inl.h"
+#include "reflection-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<mirror::Class> EmulatedStackFrame::static_class_;
+
+// Calculates the size of a stack frame based on the size of its argument
+// types and return types.
+static void CalculateFrameAndReferencesSize(ObjPtr<mirror::ObjectArray<mirror::Class>> p_types,
+                                            ObjPtr<mirror::Class> r_type,
+                                            size_t* frame_size_out,
+                                            size_t* references_size_out)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  const size_t length = p_types->GetLength();
+  size_t frame_size = 0;
+  size_t references_size = 0;
+  for (size_t i = 0; i < length; ++i) {
+    ObjPtr<mirror::Class> type = p_types->GetWithoutChecks(i);
+    const Primitive::Type primitive_type = type->GetPrimitiveType();
+    if (primitive_type == Primitive::kPrimNot) {
+      references_size++;
+    } else if (Primitive::Is64BitType(primitive_type)) {
+      frame_size += 8;
+    } else {
+      frame_size += 4;
+    }
+  }
+
+  const Primitive::Type return_type = r_type->GetPrimitiveType();
+  if (return_type == Primitive::kPrimNot) {
+    references_size++;
+  } else if (Primitive::Is64BitType(return_type)) {
+    frame_size += 8;
+  } else {
+    frame_size += 4;
+  }
+
+  (*frame_size_out) = frame_size;
+  (*references_size_out) = references_size;
+}
+
+// Allows for read or write access to an emulated stack frame. Each
+// accessor index has an associated index into the references / stack frame
+// arrays which is incremented on every read or write to the frame.
+//
+// This class is used in conjunction with PerformConversions, either as a setter
+// or as a getter.
+class EmulatedStackFrameAccessor {
+ public:
+  EmulatedStackFrameAccessor(Handle<mirror::ObjectArray<mirror::Object>> references,
+                             Handle<mirror::ByteArray> stack_frame,
+                             size_t stack_frame_size) :
+    references_(references),
+    stack_frame_(stack_frame),
+    stack_frame_size_(stack_frame_size),
+    reference_idx_(0u),
+    stack_frame_idx_(0u) {
+  }
+
+  ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> reference)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    references_->Set(reference_idx_++, reference);
+  }
+
+  ALWAYS_INLINE void Set(const uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
+    int8_t* array = stack_frame_->GetData();
+
+    CHECK_LE((stack_frame_idx_ + 4u), stack_frame_size_);
+    memcpy(array + stack_frame_idx_, &value, sizeof(uint32_t));
+    stack_frame_idx_ += 4u;
+  }
+
+  ALWAYS_INLINE void SetLong(const int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
+    int8_t* array = stack_frame_->GetData();
+
+    CHECK_LE((stack_frame_idx_ + 8u), stack_frame_size_);
+    memcpy(array + stack_frame_idx_, &value, sizeof(int64_t));
+    stack_frame_idx_ += 8u;
+  }
+
+  ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return ObjPtr<mirror::Object>(references_->Get(reference_idx_++));
+  }
+
+  ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
+    const int8_t* array = stack_frame_->GetData();
+
+    CHECK_LE((stack_frame_idx_ + 4u), stack_frame_size_);
+    uint32_t val = 0;
+
+    memcpy(&val, array + stack_frame_idx_, sizeof(uint32_t));
+    stack_frame_idx_ += 4u;
+    return val;
+  }
+
+  ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
+    const int8_t* array = stack_frame_->GetData();
+
+    CHECK_LE((stack_frame_idx_ + 8u), stack_frame_size_);
+    int64_t val = 0;
+
+    memcpy(&val, array + stack_frame_idx_, sizeof(int64_t));
+    stack_frame_idx_ += 8u;
+    return val;
+  }
+
+ private:
+  Handle<mirror::ObjectArray<mirror::Object>> references_;
+  Handle<mirror::ByteArray> stack_frame_;
+  const size_t stack_frame_size_;
+
+  size_t reference_idx_;
+  size_t stack_frame_idx_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmulatedStackFrameAccessor);
+};
+
+template <bool is_range>
+mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs(
+    Thread* self,
+    Handle<mirror::MethodType> caller_type,
+    Handle<mirror::MethodType> callee_type,
+    const ShadowFrame& caller_frame,
+    const uint32_t first_src_reg,
+    const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) {
+  StackHandleScope<6> hs(self);
+
+  // Step 1: We must throw a WrongMethodTypeException if there's a mismatch in the
+  // number of arguments between the caller and the callsite.
+  Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(caller_type->GetPTypes()));
+  Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));
+
+  const int32_t num_method_params = from_types->GetLength();
+  if (to_types->GetLength() != num_method_params) {
+    ThrowWrongMethodTypeException(callee_type.Get(), caller_type.Get());
+    return nullptr;
+  }
+
+  // Step 2: Calculate the size of the reference / byte arrays in the emulated
+  // stack frame.
+  size_t frame_size = 0;
+  size_t refs_size = 0;
+  Handle<mirror::Class> r_type(hs.NewHandle(callee_type->GetRType()));
+  CalculateFrameAndReferencesSize(to_types.Get(), r_type.Get(), &frame_size, &refs_size);
+
+  // Step 3 : Allocate the arrays.
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ObjPtr<mirror::Class> array_class(class_linker->GetClassRoot(ClassLinker::kObjectArrayClass));
+
+  Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(
+      mirror::ObjectArray<mirror::Object>::Alloc(self, array_class, refs_size)));
+  Handle<ByteArray> stack_frame(hs.NewHandle(ByteArray::Alloc(self, frame_size)));
+
+  // Step 4 : Perform argument conversions (if required).
+  ShadowFrameGetter<is_range> getter(first_src_reg, arg, caller_frame);
+  EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength());
+  if (!PerformConversions<ShadowFrameGetter<is_range>, EmulatedStackFrameAccessor>(
+      self, from_types, to_types, &getter, &setter, num_method_params)) {
+    return nullptr;
+  }
+
+  // Step 5: Construct the EmulatedStackFrame object.
+  Handle<EmulatedStackFrame> sf(hs.NewHandle(
+      ObjPtr<EmulatedStackFrame>::DownCast(StaticClass()->AllocObject(self))));
+  sf->SetFieldObject<false>(TypeOffset(), callee_type.Get());
+  sf->SetFieldObject<false>(ReferencesOffset(), references.Get());
+  sf->SetFieldObject<false>(StackFrameOffset(), stack_frame.Get());
+
+  return sf.Get();
+}
+
+bool EmulatedStackFrame::WriteToShadowFrame(Thread* self,
+                                            Handle<mirror::MethodType> callee_type,
+                                            const uint32_t first_dest_reg,
+                                            ShadowFrame* callee_frame) {
+  StackHandleScope<4> hs(self);
+  Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(GetType()->GetPTypes()));
+  Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));
+
+  const int32_t num_method_params = from_types->GetLength();
+  if (to_types->GetLength() != num_method_params) {
+    ThrowWrongMethodTypeException(callee_type.Get(), GetType());
+    return false;
+  }
+
+  Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
+  Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));
+
+  EmulatedStackFrameAccessor getter(references, stack_frame, stack_frame->GetLength());
+  ShadowFrameSetter setter(callee_frame, first_dest_reg);
+
+  return PerformConversions<EmulatedStackFrameAccessor, ShadowFrameSetter>(
+      self, from_types, to_types, &getter, &setter, num_method_params);
+}
+
+void EmulatedStackFrame::GetReturnValue(Thread* self, JValue* value) {
+  StackHandleScope<2> hs(self);
+  Handle<mirror::Class> r_type(hs.NewHandle(GetType()->GetRType()));
+
+  const Primitive::Type type = r_type->GetPrimitiveType();
+  if (type == Primitive::kPrimNot) {
+    Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
+    value->SetL(references->GetWithoutChecks(references->GetLength() - 1));
+  } else {
+    Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));
+    const int8_t* array = stack_frame->GetData();
+    const size_t length = stack_frame->GetLength();
+    if (Primitive::Is64BitType(type)) {
+      int64_t primitive = 0;
+      memcpy(&primitive, array + length - sizeof(int64_t), sizeof(int64_t));
+      value->SetJ(primitive);
+    } else {
+      uint32_t primitive = 0;
+      memcpy(&primitive, array + length - sizeof(uint32_t), sizeof(uint32_t));
+      value->SetI(primitive);
+    }
+  }
+}
+
+void EmulatedStackFrame::SetReturnValue(Thread* self, const JValue& value) {
+  StackHandleScope<2> hs(self);
+  Handle<mirror::Class> r_type(hs.NewHandle(GetType()->GetRType()));
+
+  const Primitive::Type type = r_type->GetPrimitiveType();
+  if (type == Primitive::kPrimNot) {
+    Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
+    references->SetWithoutChecks<false>(references->GetLength() - 1, value.GetL());
+  } else {
+    Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));
+    int8_t* array = stack_frame->GetData();
+    const size_t length = stack_frame->GetLength();
+    if (Primitive::Is64BitType(type)) {
+      const int64_t primitive = value.GetJ();
+      memcpy(array + length - sizeof(int64_t), &primitive, sizeof(int64_t));
+    } else {
+      const uint32_t primitive = value.GetI();
+      memcpy(array + length - sizeof(uint32_t), &primitive, sizeof(uint32_t));
+    }
+  }
+}
+
+void EmulatedStackFrame::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void EmulatedStackFrame::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void EmulatedStackFrame::VisitRoots(RootVisitor* visitor) {
+  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+// Explicit DoInvokePolymorphic template function declarations.
+#define EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(_is_range)                         \
+  template REQUIRES_SHARED(Locks::mutator_lock_)                                           \
+  mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs<_is_range>( \
+    Thread* self,                                                                          \
+    Handle<mirror::MethodType> caller_type,                                                \
+    Handle<mirror::MethodType> callee_type,                                                \
+    const ShadowFrame& caller_frame,                                                       \
+    const uint32_t first_src_reg,                                                          \
+    const uint32_t (&arg)[Instruction::kMaxVarArgRegs])                                    \
+
+EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(true);
+EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(false);
+#undef EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL
+
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
new file mode 100644
index 0000000..9fa06b7
--- /dev/null
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_EMULATED_STACK_FRAME_H_
+#define ART_RUNTIME_MIRROR_EMULATED_STACK_FRAME_H_
+
+#include "dex_instruction.h"
+#include "method_type.h"
+#include "object.h"
+#include "stack.h"
+#include "string.h"
+#include "utils.h"
+
+namespace art {
+
+struct EmulatedStackFrameOffsets;
+
+namespace mirror {
+
+// C++ mirror of dalvik.system.EmulatedStackFrame
+class MANAGED EmulatedStackFrame : public Object {
+ public:
+  // Creates an emulated stack frame whose type is |frame_type| from
+  // a shadow frame.
+  template <bool is_range>
+  static mirror::EmulatedStackFrame* CreateFromShadowFrameAndArgs(
+      Thread* self,
+      Handle<mirror::MethodType> args_type,
+      Handle<mirror::MethodType> frame_type,
+      const ShadowFrame& caller_frame,
+      const uint32_t first_src_reg,
+      const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Writes the contents of this emulated stack frame to the |callee_frame|
+  // whose type is |callee_type|, starting at |first_dest_reg|.
+  bool WriteToShadowFrame(
+      Thread* self,
+      Handle<mirror::MethodType> callee_type,
+      const uint32_t first_dest_reg,
+      ShadowFrame* callee_frame) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Sets |value| to the return value written to this emulated stack frame (if any).
+  void GetReturnValue(Thread* self, JValue* value) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Sets the return value slot of this emulated stack frame to |value|.
+  void SetReturnValue(Thread* self, const JValue& value) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
+  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  mirror::MethodType* GetType() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return GetFieldObject<MethodType>(OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, type_));
+  }
+
+  mirror::ObjectArray<mirror::Object>* GetReferences() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return GetFieldObject<mirror::ObjectArray<mirror::Object>>(
+        OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, references_));
+  }
+
+  mirror::ByteArray* GetStackFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return GetFieldObject<mirror::ByteArray>(
+        OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, stack_frame_));
+  }
+
+  static MemberOffset TypeOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, type_));
+  }
+
+  static MemberOffset ReferencesOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, references_));
+  }
+
+  static MemberOffset StackFrameOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, stack_frame_));
+  }
+
+  HeapReference<mirror::ObjectArray<mirror::Object>> references_;
+  HeapReference<mirror::ByteArray> stack_frame_;
+  HeapReference<mirror::MethodType> type_;
+
+  static GcRoot<mirror::Class> static_class_;  // dalvik.system.EmulatedStackFrame.class
+
+  friend struct art::EmulatedStackFrameOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(EmulatedStackFrame);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_EMULATED_STACK_FRAME_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4e600ae..d645c5a 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -86,6 +86,7 @@
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/emulated_stack_frame.h"
 #include "mirror/field.h"
 #include "mirror/method.h"
 #include "mirror/method_handle_impl.h"
@@ -1593,6 +1594,7 @@
   mirror::Field::VisitRoots(visitor);
   mirror::MethodType::VisitRoots(visitor);
   mirror::MethodHandleImpl::VisitRoots(visitor);
+  mirror::EmulatedStackFrame::VisitRoots(visitor);
   // Visit all the primitive array types classes.
   mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor);   // BooleanArray
   mirror::PrimitiveArray<int8_t>::VisitRoots(visitor);    // ByteArray
diff --git a/runtime/runtime.h b/runtime/runtime.h
index b25ec23..043ff5d 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -316,7 +316,8 @@
   }
 
   bool IsMethodHandlesEnabled() const {
-    return experimental_flags_ & ExperimentalFlags::kMethodHandles;
+    // return experimental_flags_ & ExperimentalFlags::kMethodHandles;
+    return true;
   }
 
   void DisallowNewSystemWeaks() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index badea53..2802dfa 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -57,8 +57,6 @@
   public static void main(String[] args) throws Throwable {
     testfindSpecial_invokeSuperBehaviour();
     testfindSpecial_invokeDirectBehaviour();
-
-    testThrowException();
   }
 
   public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -133,21 +131,6 @@
     } catch (IllegalAccessException expected) {
     }
   }
-
-  public static void testThrowException() throws Throwable {
-    MethodHandle handle = MethodHandles.throwException(String.class,
-        IllegalArgumentException.class);
-    if (handle.type().returnType() != String.class) {
-      System.out.println("Unexpected return type for handle: " + handle
-          + " [ " + handle.type() + "]");
-    }
-
-    try {
-      handle.invoke();
-      System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
-    } catch (IllegalArgumentException expected) {
-    }
-  }
 }
 
 
diff --git a/test/957-methodhandle-transforms/build b/test/957-methodhandle-transforms/build
new file mode 100755
index 0000000..a423ca6
--- /dev/null
+++ b/test/957-methodhandle-transforms/build
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# make us exit on a failure
+set -e
+
+if [[ $@ != *"--jvm"* ]]; then
+  # Don't do anything with jvm.
+  export USE_JACK=true
+fi
+
+./default-build "$@" --experimental method-handles
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected.txt
new file mode 100644
index 0000000..73a34bc
--- /dev/null
+++ b/test/957-methodhandle-transforms/expected.txt
@@ -0,0 +1,35 @@
+---
+-- testDelegation
+---
+boolean: false
+char: h
+short: 56
+int: 72
+long: 2147483689
+float: 0.56
+double: 100.0
+String: hello
+Object: goodbye
+boolean: false
+char: h
+short: 56
+int: 72
+long: 73
+float: 0.56
+double: 100.0
+String: hello
+Object: goodbye
+true
+true
+a
+a
+42
+42
+43
+43
+43.0
+43.0
+43.0
+43.0
+plank
+plank
diff --git a/test/957-methodhandle-transforms/info.txt b/test/957-methodhandle-transforms/info.txt
new file mode 100644
index 0000000..bc50e85
--- /dev/null
+++ b/test/957-methodhandle-transforms/info.txt
@@ -0,0 +1,3 @@
+Tests for method handle transformations.
+
+NOTE: needs to run under ART or a Java 8 Language runtime and compiler.
diff --git a/test/957-methodhandle-transforms/run b/test/957-methodhandle-transforms/run
new file mode 100755
index 0000000..a9f1822
--- /dev/null
+++ b/test/957-methodhandle-transforms/run
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# make us exit on a failure
+set -e
+
+./default-run "$@" --experimental method-handles
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
new file mode 100644
index 0000000..aaf6e2f
--- /dev/null
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.invoke.Transformers.Transformer;
+
+import dalvik.system.EmulatedStackFrame;
+
+public class Main {
+
+  public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d,
+                                           float e, double f, String g, Object h) {
+    System.out.println("boolean: " + z);
+    System.out.println("char: " + a);
+    System.out.println("short: " + b);
+    System.out.println("int: " + c);
+    System.out.println("long: " + d);
+    System.out.println("float: " + e);
+    System.out.println("double: " + f);
+    System.out.println("String: " + g);
+    System.out.println("Object: " + h);
+  }
+
+  public static boolean testDelegate_returnBoolean() {
+    return true;
+  }
+
+  public static char testDelegate_returnChar() {
+    return 'a';
+  }
+
+  public static int testDelegate_returnInt() {
+    return 42;
+  }
+
+  public static long testDelegate_returnLong() {
+    return 43;
+  }
+
+  public static float testDelegate_returnFloat() {
+    return 43.0f;
+  }
+
+  public static double testDelegate_returnDouble() {
+    return 43.0;
+  }
+
+  public static String testDelegate_returnString() {
+    return "plank";
+  }
+
+  public static class DelegatingTransformer extends Transformer {
+    private final MethodHandle delegate;
+
+    public DelegatingTransformer(MethodHandle delegate) {
+      super(delegate.type());
+      this.delegate = delegate;
+    }
+
+    @Override
+    public void transform(EmulatedStackFrame stackFrame) throws Throwable {
+      delegate.invoke(stackFrame);
+    }
+  }
+
+  public static void main(String[] args) throws Throwable {
+    testThrowException();
+
+    testDelegation();
+  }
+
+  public static void testDelegation() throws Throwable {
+    System.out.println("---");
+    System.out.println("-- testDelegation");
+    System.out.println("---");
+
+    MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_allTypes", MethodType.methodType(void.class,
+          new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class,
+            float.class, double.class, String.class, Object.class }));
+
+    DelegatingTransformer delegate = new DelegatingTransformer(specialFunctionHandle);
+
+    // Test an exact invoke.
+    delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l,
+        0.56f, 100.0d, "hello", "goodbye");
+
+    // Test a non exact invoke with one int -> long conversion and a float -> double
+    // conversion.
+    delegate.invoke(false, 'h', (short) 56, 72, 73,
+        0.56f, 100.0f, "hello", "goodbye");
+
+    // Should throw a WrongMethodTypeException if the types don't align.
+    try {
+      delegate.invoke(false);
+      throw new AssertionError("Call to invoke unexpectedly succeeded");
+    } catch (WrongMethodTypeException expected) {
+    }
+
+    // Test return values.
+
+    // boolean.
+    MethodHandle returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((boolean) delegate.invoke());
+    System.out.println((boolean) delegate.invokeExact());
+
+    // char.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnChar", MethodType.methodType(char.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((char) delegate.invoke());
+    System.out.println((char) delegate.invokeExact());
+
+    // int.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnInt", MethodType.methodType(int.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((int) delegate.invoke());
+    System.out.println((int) delegate.invokeExact());
+
+    // long.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnLong", MethodType.methodType(long.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((long) delegate.invoke());
+    System.out.println((long) delegate.invokeExact());
+
+    // float.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((float) delegate.invoke());
+    System.out.println((float) delegate.invokeExact());
+
+    // double.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((double) delegate.invoke());
+    System.out.println((double) delegate.invokeExact());
+
+    // references.
+    returner = MethodHandles.lookup().findStatic(
+        Main.class, "testDelegate_returnString", MethodType.methodType(String.class));
+    delegate = new DelegatingTransformer(returner);
+
+    System.out.println((String) delegate.invoke());
+    System.out.println((String) delegate.invokeExact());
+  }
+
+  public static void testThrowException() throws Throwable {
+    MethodHandle handle = MethodHandles.throwException(String.class,
+        IllegalArgumentException.class);
+
+    if (handle.type().returnType() != String.class) {
+      System.out.println("Unexpected return type for handle: " + handle +
+          " [ " + handle.type() + "]");
+    }
+
+    try {
+      handle.invoke();
+      System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+}
+
+