in runtime/entrypoints/quick/quick_trampoline_entrypoints.cc [438:561]
void VisitArguments() SHARED_REQUIRES(Locks::mutator_lock_) {
// (a) 'stack_args_' should point to the first method's argument
// (b) whatever the argument type it is, the 'stack_index_' should
// be moved forward along with every visiting.
gpr_index_ = 0;
fpr_index_ = 0;
if (kQuickDoubleRegAlignedFloatBackFilled) {
fpr_double_index_ = 0;
}
stack_index_ = 0;
if (!is_static_) { // Handle this.
cur_type_ = Primitive::kPrimNot;
is_split_long_or_double_ = false;
Visit();
stack_index_++;
if (kNumQuickGprArgs > 0) {
IncGprIndex();
}
}
for (uint32_t shorty_index = 1; shorty_index < shorty_len_; ++shorty_index) {
cur_type_ = Primitive::GetType(shorty_[shorty_index]);
switch (cur_type_) {
case Primitive::kPrimNot:
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
case Primitive::kPrimChar:
case Primitive::kPrimShort:
case Primitive::kPrimInt:
is_split_long_or_double_ = false;
Visit();
stack_index_++;
if (gpr_index_ < kNumQuickGprArgs) {
IncGprIndex();
}
break;
case Primitive::kPrimFloat:
is_split_long_or_double_ = false;
Visit();
stack_index_++;
if (kQuickSoftFloatAbi) {
if (gpr_index_ < kNumQuickGprArgs) {
IncGprIndex();
}
} else {
if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
IncFprIndex();
if (kQuickDoubleRegAlignedFloatBackFilled) {
// Double should not overlap with float.
// For example, if fpr_index_ = 3, fpr_double_index_ should be at least 4.
fpr_double_index_ = std::max(fpr_double_index_, RoundUp(fpr_index_, 2));
// Float should not overlap with double.
if (fpr_index_ % 2 == 0) {
fpr_index_ = std::max(fpr_double_index_, fpr_index_);
}
} else if (kQuickSkipOddFpRegisters) {
IncFprIndex();
}
}
}
break;
case Primitive::kPrimDouble:
case Primitive::kPrimLong:
if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) {
if (cur_type_ == Primitive::kPrimLong && kAlignPairRegister && gpr_index_ == 0) {
// Currently, this is only for ARM and MIPS, where the first available parameter
// register is R1 (on ARM) or A1 (on MIPS). So we skip it, and use R2 (on ARM) or
// A2 (on MIPS) instead.
IncGprIndex();
}
is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) &&
((gpr_index_ + 1) == kNumQuickGprArgs);
if (!kSplitPairAcrossRegisterAndStack && is_split_long_or_double_) {
// We don't want to split this. Pass over this register.
gpr_index_++;
is_split_long_or_double_ = false;
}
Visit();
if (kBytesStackArgLocation == 4) {
stack_index_+= 2;
} else {
CHECK_EQ(kBytesStackArgLocation, 8U);
stack_index_++;
}
if (gpr_index_ < kNumQuickGprArgs) {
IncGprIndex();
if (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) {
if (gpr_index_ < kNumQuickGprArgs) {
IncGprIndex();
}
}
}
} else {
is_split_long_or_double_ = (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) &&
((fpr_index_ + 1) == kNumQuickFprArgs) && !kQuickDoubleRegAlignedFloatBackFilled;
Visit();
if (kBytesStackArgLocation == 4) {
stack_index_+= 2;
} else {
CHECK_EQ(kBytesStackArgLocation, 8U);
stack_index_++;
}
if (kQuickDoubleRegAlignedFloatBackFilled) {
if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) {
fpr_double_index_ += 2;
// Float should not overlap with double.
if (fpr_index_ % 2 == 0) {
fpr_index_ = std::max(fpr_double_index_, fpr_index_);
}
}
} else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
IncFprIndex();
if (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) {
if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
IncFprIndex();
}
}
}
}
break;
default:
LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty_;
}
}
}