artQuickGenericJniTrampoline

该函数的注释如下:

1798 /*
1799  * Initializes an alloca region assumed to be directly below sp for a native call:
1800  * Create a HandleScope and call stack and fill a mini stack with values to be pushed to registers.
1801  * The final element on the stack is a pointer to the native code.
1802  *
1803  * On entry, the stack has a standard callee-save frame above sp, and an alloca below it.
1804  * We need to fix this, as the handle scope needs to go into the callee-save frame.
1805  *
1806  * The return of this function denotes:
1807  * 1) How many bytes of the alloca can be released, if the value is non-negative.
1808  * 2) An error, if the value is negative.
1809  */

在汇编语言实现的art_quick_generic_jni_trampoline函数中调用了该函数
分为几部分来分析该函数:
一.

1810 extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** sp)
1811     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1812   ArtMethod* called = *sp;
1813   DCHECK(called->IsNative()) << PrettyMethod(called, true);
1814   uint32_t shorty_len = 0;
1815   const char* shorty = called->GetShorty(&shorty_len);
1816 
1817   // Run the visitor and update sp.
1818   BuildGenericJniFrameVisitor visitor(self, called->IsStatic(), shorty, shorty_len, &sp);
1819   visitor.VisitArguments();
1820   visitor.FinalizeHandleScope(self);

sp就是当前栈的栈指针所在,其指向的是需要寻找具体机器指令地址的ArtMethod* 。

①生成了一个BuildGenericJniFrameVisitor的实例,该类的作用是visit在栈中的arguments,将它们放入比栈要低的位置以实现到native code的转换(Visits arguments on the stack placing them into a region lower down the stack for the benefit of transitioning into native code.)

1635   BuildGenericJniFrameVisitor(Thread* self, bool is_static, const char* shorty, uint32_t shorty_len,
1636                               ArtMethod*** sp)
1637      : QuickArgumentVisitor(*sp, is_static, shorty, shorty_len),
1638        jni_call_(nullptr, nullptr, nullptr, nullptr), sm_(&jni_call_) {
1639     ComputeGenericJniFrameSize fsc;
1640     uintptr_t* start_gpr_reg;
1641     uint32_t* start_fpr_reg;
1642     uintptr_t* start_stack_arg;
1643     bottom_of_used_area_ = fsc.ComputeLayout(self, sp, shorty, shorty_len,
1644                                              &handle_scope_,
1645                                              &start_stack_arg,
1646                                              &start_gpr_reg, &start_fpr_reg);
1647      //FillJniCall
1648     jni_call_.Reset(start_gpr_reg, start_fpr_reg, start_stack_arg, handle_scope_);
1649 
1650     // jni environment is always first argument.将JNIEnv放入第一个参数中。
         // BuildNativeCallFrameStateMachine<FillJniCall> sm_;
1651     sm_.AdvancePointer(self->GetJniEnv());
1652 
1653     if (is_static) {
1654       sm_.AdvanceHandleScope((**sp)->GetDeclaringClass());
1655     }
1656   }

其中的fsc.ComputeLayout的具体实现如下:

1544   // WARNING: After this, *sp won't be pointing to the method anymore!
1545   uint8_t* ComputeLayout(Thread* self, ArtMethod*** m, const char* shorty, uint32_t shorty_len,
1546                          HandleScope** handle_scope, uintptr_t** start_stack, uintptr_t** start_gpr,
1547                          uint32_t** start_fpr)
1548       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1549     Walk(shorty, shorty_len);
1550 
1551     // JNI part.
        // Re-layout the callee-save frame (insert a handle-scope). Then add space for the cookie. Returns the new bottom. Note: this may be unaligned.
1552     uint8_t* sp8 = LayoutJNISaveFrame(self, m, reinterpret_cast<void*>(*m), handle_scope);
1553 
1554     sp8 = LayoutNativeCall(sp8, start_stack, start_gpr, start_fpr);
1555 
1556     // Return the new bottom.
1557     return sp8;
1558   }

各种调用之后发现,在栈中增加了handle scope和cookie的大小,以及增加了8个FPR和7个GPR的大小。并设定好了start_stack_arg,start_gpr,start_fpr的地址。据此重置了jni_call_.

②1819 visitor.VisitArguments();该函数的具体实现为:

 395   void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 396     // (a) 'stack_args_' should point to the first method's argument
 397     // (b) whatever the argument type it is, the 'stack_index_' should
 398     //     be moved forward along with every visiting.
 399     gpr_index_ = 0;
 400     fpr_index_ = 0;
         //在arm64架构中,kQuickDoubleRegAlignedFloatBackFilled=false   ->该值与具体架构相关。
 401     if (kQuickDoubleRegAlignedFloatBackFilled) {
 402       fpr_double_index_ = 0;
 403     }
 404     stack_index_ = 0;
 405     if (!is_static_) {  // Handle this.
 406       cur_type_ = Primitive::kPrimNot;
 407       is_split_long_or_double_ = false;
           //Visit()该函数负责获取当前parameter的type然后根据type在ShadowFrame* sf_中设置VReg。
 408       Visit();
 409       stack_index_++;
 410       if (kNumQuickGprArgs > 0) {
 411         IncGprIndex();
 412       }
 413     }

继续看下面的代码:

 414     for (uint32_t shorty_index = 1; shorty_index < shorty_len_; ++shorty_index) {
 415       cur_type_ = Primitive::GetType(shorty_[shorty_index]);
 416       switch (cur_type_) {
 417         case Primitive::kPrimNot:
 418         case Primitive::kPrimBoolean:
 419         case Primitive::kPrimByte:
 420         case Primitive::kPrimChar:
 421         case Primitive::kPrimShort:
 422         case Primitive::kPrimInt:
 423           is_split_long_or_double_ = false;
 424           Visit();
 425           stack_index_++;
 426           if (gpr_index_ < kNumQuickGprArgs) {
 427             IncGprIndex();
 428           }
 429           break;

对于Integral type,用Visit()对参数进行处理,然后stack_index_++,如果gpr_index_<7,gpr_index_++.
继续float类型:

 430         case Primitive::kPrimFloat:
 431           is_split_long_or_double_ = false;
 432           Visit();
 433           stack_index_++;
             //对于arm64而言,kQuickSoftFloatAbi=false
 434           if (kQuickSoftFloatAbi) {
 435             if (gpr_index_ < kNumQuickGprArgs) {
 436               IncGprIndex();
 437             }
 438           } else {
 439             if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
 440               IncFprIndex();//该函数的操作是fpr_index_++
 441               if (kQuickDoubleRegAlignedFloatBackFilled) {//在arm64中,该值为false。
 442                 // Double should not overlap with float.
 443                 // For example, if fpr_index_ = 3, fpr_double_index_ should be at least 4.
 444                 fpr_double_index_ = std::max(fpr_double_index_, RoundUp(fpr_index_, 2));
 445                 // Float should not overlap with double.
 446                 if (fpr_index_ % 2 == 0) {
 447                   fpr_index_ = std::max(fpr_double_index_, fpr_index_);
 448                 }
 449               }
 450             }
 451           }
 452           break;

继续,对于long和double类型:

 453         case Primitive::kPrimDouble:
 454         case Primitive::kPrimLong:
             //如果是long类型的话,对于arm64而言,gpr_index_只需要+1.由于kBytesStackArgLocation =4,所以stack_index_需要+2。
 455           if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) {
                     //对于arm64而言,kAlignPairRegister=false
 456             if (cur_type_ == Primitive::kPrimLong && kAlignPairRegister && gpr_index_ == 0) {
 457               // Currently, this is only for ARM, where the first available parameter register
 458               // is R1. So we skip it, and use R2 instead.
 459               IncGprIndex();
 460             }
 461             is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) &&
 462                 ((gpr_index_ + 1) == kNumQuickGprArgs);
 463             if (!kSplitPairAcrossRegisterAndStack && is_split_long_or_double_) {
 464               // We don't want to split this. Pass over this register.
 465               gpr_index_++;
 466               is_split_long_or_double_ = false;
 467             }
 468             Visit();
 469             if (kBytesStackArgLocation == 4) {
 470               stack_index_+= 2;
 471             } else {
 472               CHECK_EQ(kBytesStackArgLocation, 8U);
 473               stack_index_++;
 474             }
 475             if (gpr_index_ < kNumQuickGprArgs) {
 476               IncGprIndex();
 477               if (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) {
 478                 if (gpr_index_ < kNumQuickGprArgs) {
 479                   IncGprIndex();
 480                 }
 481               }
 482             }
 483           } else {//对于double类型的参数而言,
 484             is_split_long_or_double_ = (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) &&
 485                 ((fpr_index_ + 1) == kNumQuickFprArgs) && !kQuickDoubleRegAlignedFloatBackFilled;//arm64中kQuickDoubleRegAlignedFloatBackFilled=false。GetBytesPerFprSpillLocation(...)=8
 486             Visit();
 487             if (kBytesStackArgLocation == 4) {
 488               stack_index_+= 2;
 489             } else {
 490               CHECK_EQ(kBytesStackArgLocation, 8U);
 491               stack_index_++;
 492             }
 493             if (kQuickDoubleRegAlignedFloatBackFilled) {
 494               if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) {
 495                 fpr_double_index_ += 2;
 496                 // Float should not overlap with double.
 497                 if (fpr_index_ % 2 == 0) {
 498                   fpr_index_ = std::max(fpr_double_index_, fpr_index_);
 499                 }
 500               }
 501             } else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
 502               IncFprIndex();
 503               if (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) {
 504                 if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
 505                   IncFprIndex();
 506                 }
 507               }
 508             }
 509           }
 510           break;

对于不符合上述类型的type:

 511         default:
 512           LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty_;

VisitArguments()结束。
③visitor.FinalizeHandleScope(self);的具体实现如下:

1769 void BuildGenericJniFrameVisitor::FinalizeHandleScope(Thread* self) {
1770   // Clear out rest of the scope.
       // FillJniCall jni_call_;
1771   jni_call_.ResetRemainingScopeSlots();
1772   // Install HandleScope.在栈中加入handlescope
1773   self->PushHandleScope(handle_scope_);
1774 }

二.继续看artQuickGenericJniTrampoline函数的第二部分:

1822   // Fix up managed-stack things in Thread.
1823   self->SetTopOfStack(sp);
1824         
1825   self->VerifyStack();

将sp放入manged-stack的top位置。SetTopOfStack(sp)的实现为:tlsPtr_.managed_stack.SetTopQuickFrame(sp);

三.第三部分:

1827   // Start JNI, save the cookie.
1828   uint32_t cookie;
1829   if (called->IsSynchronized()) {
1830     cookie = JniMethodStartSynchronized(visitor.GetFirstHandleScopeJObject(), self);
1831     if (self->IsExceptionPending()) {
1832       self->PopHandleScope();
1833       // A negative value denotes an error.
1834       return GetTwoWordFailureValue();
1835     }
1836   } else { 
1837     cookie = JniMethodStart(self);
1838   }
1839   uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
1840   *(sp32 - 1) = cookie;

将cookie存入sp后的一个位置。

四. 第四部分:

1842   // Retrieve the stored native code.
1843   void* nativeCode = called->GetEntryPointFromJni();
1844    
1845   // There are two cases for the content of nativeCode:
1846   // 1) Pointer to the native function.
1847   // 2) Pointer to the trampoline for native code binding.
1848   // In the second case, we need to execute the binding and continue with the actual native function
1849   // pointer.
1850   DCHECK(nativeCode != nullptr);
1851   if (nativeCode == GetJniDlsymLookupStub()) {
1852 #if defined(__arm__) || defined(__aarch64__)
1853     nativeCode = artFindNativeMethod();
1854 #else
1855     nativeCode = artFindNativeMethod(self);
1856 #endif

获取native code的位置,有两种情况,一种是指向native function,一种是指向native code binding的trampoline,第二种情况下,需要运行binding,最后得到真正的native function。

五.第五部分:

1857 
1858     if (nativeCode == nullptr) {
1859       DCHECK(self->IsExceptionPending());    // There should be an exception pending now.
1860 
1861       // End JNI, as the assembly will move to deliver the exception.
1862       jobject lock = called->IsSynchronized() ? visitor.GetFirstHandleScopeJObject() : nullptr;
1863       if (shorty[0] == 'L') {
1864         artQuickGenericJniEndJNIRef(self, cookie, nullptr, lock);
1865       } else {
1866         artQuickGenericJniEndJNINonRef(self, cookie, lock);
1867       }
1868 
1869       return GetTwoWordFailureValue();
1870     }
1871     // Note that the native code pointer will be automatically set by artFindNativeMethod().
1872   }
1873 
1874   // Return native code addr(lo) and bottom of alloca address(hi).
1875   return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(visitor.GetBottomOfUsedArea()),
1876                                 reinterpret_cast<uintptr_t>(nativeCode));
1877 }

如果获取的nativeCode为nullptr的话,报错,返回GetTwoWordFailureValue,否则返回:GetTwoWordSuccessValue。

最后需要看一下类QuickArgumentVisitor,该类否则visit 被Runtime::kRefAndArgs callee save frame 存到栈中的参数。
定义了各个架构中的栈的架构,其中arm64的为:

  80 #elif defined(__aarch64__)
  81   // The callee save frame is pointed to by SP.
  82   // | argN       |  |
  83   // | ...        |  |
  84   // | arg4       |  |
  85   // | arg3 spill |  |  Caller's frame
  86   // | arg2 spill |  |
  87   // | arg1 spill |  |
  88   // | Method*    | ---
  89   // | LR         |
  90   // | X29        |
  91   // |  :         |
  92   // | X19        |
  93   // | X7         |
  94   // | :          |
  95   // | X1         |
  96   // | D7         |
  97   // |  :         |
  98   // | D0         |
  99   // |            |    padding
 100   // | Method*    |  <- sp
 101   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
 102   static constexpr bool kAlignPairRegister = false;
 103   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
 104   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
 105   static constexpr size_t kNumQuickGprArgs = 7;  // 7 arguments passed in GPRs.
 106   static constexpr size_t kNumQuickFprArgs = 8;  // 8 arguments passed in FPRs.
 107   static constexpr bool kGprFprLockstep = false;
 108   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset =
 109       arm64::Arm64CalleeSaveFpr1Offset(Runtime::kRefsAndArgs);  // Offset of first FPR arg.
 110   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset =
 111       arm64::Arm64CalleeSaveGpr1Offset(Runtime::kRefsAndArgs);  // Offset of first GPR arg.
 112   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset =
 113       arm64::Arm64CalleeSaveLrOffset(Runtime::kRefsAndArgs);  // Offset of return address.
 114   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
 115     return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
 116   }

其private变量中还包括:

 522  private:
 523   uint8_t* const gpr_args_;  // Address of GPR arguments in callee save frame.
 524   uint8_t* const fpr_args_;  // Address of FPR arguments in callee save frame.
 525   uint8_t* const stack_args_;  // Address of stack arguments in caller's frame.
 526   uint32_t gpr_index_;  // Index into spilled GPRs.
 527   // Index into spilled FPRs.
 528   // In case kQuickDoubleRegAlignedFloatBackFilled, it may index a hole while fpr_double_index_
 529   // holds a higher register number.
 530   uint32_t fpr_index_;
 531   // Index into spilled FPRs for aligned double.
 532   // Only used when kQuickDoubleRegAlignedFloatBackFilled. Next available double register indexed in
 533   // terms of singles, may be behind fpr_index.
 534   uint32_t fpr_double_index_;
 535   uint32_t stack_index_;  // Index into arguments on the stack.
 536   // The current type of argument during VisitArguments.
 537   Primitive::Type cur_type_;
 538   // Does a 64bit parameter straddle the register and stack arguments?
 539   bool is_split_long_or_double_;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值