该函数的注释如下:
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_;