OSDN Git Service

Support proxy method in StackVisitor::GetThisObject
authorSebastien Hertz <shertz@google.com>
Tue, 25 Nov 2014 15:30:53 +0000 (16:30 +0100)
committerSebastien Hertz <shertz@google.com>
Tue, 9 Dec 2014 11:58:25 +0000 (12:58 +0100)
Adds function artQuickGetProxyThisObject which returns the 'this'
object of the proxy method using the QuickArgumentVisitor. Since
proxy methods have the same layout than the kRefsAndArgs runtime
method and 'this' is the 1st method argument, it is located in the
first GPR.

Bug: 17965861
Change-Id: Ic6ef6c83b9a549c25f9929d5e00ffe1d3a9a36f0

runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
runtime/stack.cc

index cb81629..9db1646 100644 (file)
@@ -208,6 +208,22 @@ class QuickArgumentVisitor {
 #endif
 
  public:
+  // Special handling for proxy methods. Proxy methods are instance methods so the
+  // 'this' object is the 1st argument. They also have the same frame layout as the
+  // kRefAndArgs runtime method. Since 'this' is a reference, it is located in the
+  // 1st GPR.
+  static mirror::Object* GetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    CHECK(sp->AsMirrorPtr()->IsProxyMethod());
+    CHECK_EQ(kQuickCalleeSaveFrame_RefAndArgs_FrameSize, sp->AsMirrorPtr()->GetFrameSizeInBytes());
+    CHECK_GT(kNumQuickGprArgs, 0u);
+    constexpr uint32_t kThisGprIndex = 0u;  // 'this' is in the 1st GPR.
+    size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset +
+        GprIndexToGprOffset(kThisGprIndex);
+    uint8_t* this_arg_address = reinterpret_cast<uint8_t*>(sp) + this_arg_offset;
+    return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address)->AsMirrorPtr();
+  }
+
   static mirror::ArtMethod* GetCallingMethod(StackReference<mirror::ArtMethod>* sp)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
@@ -435,6 +451,13 @@ class QuickArgumentVisitor {
   bool is_split_long_or_double_;
 };
 
+// Returns the 'this' object of a proxy method. This function is only used by StackVisitor. It
+// allows to use the QuickArgumentVisitor constants without moving all the code in its own module.
+extern "C" mirror::Object* artQuickGetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return QuickArgumentVisitor::GetProxyThisObject(sp);
+}
+
 // Visits arguments on the stack placing them into the shadow frame.
 class BuildQuickShadowFrameVisitor FINAL : public QuickArgumentVisitor {
  public:
index 43714b9..aaa5b89 100644 (file)
@@ -113,6 +113,9 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
   }
 }
 
+extern "C" mirror::Object* artQuickGetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 mirror::Object* StackVisitor::GetThisObject() const {
   mirror::ArtMethod* m = GetMethod();
   if (m->IsStatic()) {
@@ -125,6 +128,12 @@ mirror::Object* StackVisitor::GetThisObject() const {
     } else {
       return cur_shadow_frame_->GetVRegReference(0);
     }
+  } else if (m->IsProxyMethod()) {
+    if (cur_quick_frame_ != nullptr) {
+      return artQuickGetProxyThisObject(cur_quick_frame_);
+    } else {
+      return cur_shadow_frame_->GetVRegReference(0);
+    }
   } else if (m->IsOptimized(sizeof(void*))) {
     // TODO: Implement, currently only used for exceptions when jdwp is enabled.
     UNIMPLEMENTED(WARNING)