From: Sebastien Hertz Date: Tue, 25 Nov 2014 15:30:53 +0000 (+0100) Subject: Support proxy method in StackVisitor::GetThisObject X-Git-Tag: android-x86-7.1-r1~889^2~2376^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a836bc9760419af4a515f96c66100a39e865f3b9;p=android-x86%2Fart.git Support proxy method in StackVisitor::GetThisObject 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 --- diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index cb816298a..9db1646f5 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -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* 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(sp) + this_arg_offset; + return reinterpret_cast*>(this_arg_address)->AsMirrorPtr(); + } + static mirror::ArtMethod* GetCallingMethod(StackReference* 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* 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: diff --git a/runtime/stack.cc b/runtime/stack.cc index 43714b95e..aaa5b898b 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -113,6 +113,9 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const { } } +extern "C" mirror::Object* artQuickGetProxyThisObject(StackReference* 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)