Optimizing: Introduce {Increase,Decrease}Frame().
And use it to clean up code generators.
Also fix CFI in MaybeIncrementHotness() for arm/arm64/x86.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: testrunner.py --host --debuggable --ndebuggable \
--optimizing --jit --jit-on-first-use -t 178
Test: aosp_cf_x86_phone-userdebug boots.
Test: aosp_cf_x86_phone-userdebug/jitzygote boots.
Test: # On blueline:
testrunner.py --target --debuggable --ndebuggable \
--optimizing --jit --jit-on-first-use -t 178
Bug: 112189621
Change-Id: I524e6c3054ffe1b05e2860fd7988cd9995df2963
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index f74a938..8e64e18 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -545,8 +545,10 @@
}
}
-void CodeGenerator::AdjustCriticalNativeArgumentMoves(size_t out_frame_size,
- /*inout*/HParallelMove* parallel_move) {
+void CodeGenerator::FinishCriticalNativeFrameSetup(size_t out_frame_size,
+ /*inout*/HParallelMove* parallel_move) {
+ DCHECK_NE(out_frame_size, 0u);
+ IncreaseFrame(out_frame_size);
// Adjust the source stack offsets by `out_frame_size`, i.e. the additional
// frame size needed for outgoing stack arguments.
for (size_t i = 0, num = parallel_move->NumMoves(); i != num; ++i) {
@@ -558,6 +560,8 @@
operands->SetSource(Location::DoubleStackSlot(source.GetStackIndex() + out_frame_size));
}
}
+ // Emit the moves.
+ GetMoveResolver()->EmitNativeCode(parallel_move);
}
const char* CodeGenerator::GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke,
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 4bfc14a..12e2e97 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -573,12 +573,12 @@
template <typename CriticalNativeCallingConventionVisitor,
size_t kNativeStackAlignment,
size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len)>
- static size_t PrepareCriticalNativeCall(HInvokeStaticOrDirect* invoke,
- /*out*/HParallelMove* parallel_move) {
+ size_t PrepareCriticalNativeCall(HInvokeStaticOrDirect* invoke) {
DCHECK(!invoke->GetLocations()->Intrinsified());
CriticalNativeCallingConventionVisitor calling_convention_visitor(
/*for_register_allocation=*/ false);
- PrepareCriticalNativeArgumentMoves(invoke, &calling_convention_visitor, parallel_move);
+ HParallelMove parallel_move(GetGraph()->GetAllocator());
+ PrepareCriticalNativeArgumentMoves(invoke, &calling_convention_visitor, ¶llel_move);
size_t out_frame_size =
RoundUp(calling_convention_visitor.GetStackOffset(), kNativeStackAlignment);
if (kIsDebugBuild) {
@@ -587,7 +587,7 @@
DCHECK_EQ(GetCriticalNativeDirectCallFrameSize(shorty, shorty_len), out_frame_size);
}
if (out_frame_size != 0u) {
- AdjustCriticalNativeArgumentMoves(out_frame_size, parallel_move);
+ FinishCriticalNativeFrameSetup(out_frame_size, ¶llel_move);
}
return out_frame_size;
}
@@ -690,6 +690,9 @@
// Copy the result of a call into the given target.
virtual void MoveFromReturnRegister(Location trg, DataType::Type type) = 0;
+ virtual void IncreaseFrame(size_t adjustment) = 0;
+ virtual void DecreaseFrame(size_t adjustment) = 0;
+
virtual void GenerateNop() = 0;
static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array);
@@ -826,8 +829,7 @@
/*inout*/InvokeDexCallingConventionVisitor* visitor,
/*out*/HParallelMove* parallel_move);
- static void AdjustCriticalNativeArgumentMoves(size_t out_frame_size,
- /*inout*/HParallelMove* parallel_move);
+ void FinishCriticalNativeFrameSetup(size_t out_frame_size, /*inout*/HParallelMove* parallel_move);
static const char* GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke, uint32_t* shorty_len);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d108623..b7f519b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1157,9 +1157,9 @@
__ B(ne, &done);
if (is_frame_entry) {
if (HasEmptyFrame()) {
- // The entyrpoint expects the method at the bottom of the stack. We
+ // The entrypoint expects the method at the bottom of the stack. We
// claim stack space necessary for alignment.
- __ Claim(kStackAlignment);
+ IncreaseFrame(kStackAlignment);
__ Stp(kArtMethodRegister, lr, MemOperand(sp, 0));
} else if (!RequiresCurrentMethod()) {
__ Str(kArtMethodRegister, MemOperand(sp, 0));
@@ -1176,7 +1176,7 @@
if (HasEmptyFrame()) {
CHECK(is_frame_entry);
__ Ldr(lr, MemOperand(sp, 8));
- __ Drop(kStackAlignment);
+ DecreaseFrame(kStackAlignment);
}
__ Bind(&done);
}
@@ -3654,6 +3654,16 @@
// MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
}
+void CodeGeneratorARM64::IncreaseFrame(size_t adjustment) {
+ __ Claim(adjustment);
+ GetAssembler()->cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorARM64::DecreaseFrame(size_t adjustment) {
+ __ Drop(adjustment);
+ GetAssembler()->cfi().AdjustCFAOffset(-adjustment);
+}
+
void CodeGeneratorARM64::GenerateNop() {
__ Nop();
}
@@ -4448,16 +4458,10 @@
}
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative: {
- HParallelMove parallel_move(GetGraph()->GetAllocator());
size_t out_frame_size =
PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorARM64,
kAapcs64StackAlignment,
- GetCriticalNativeDirectCallFrameSize>(invoke, ¶llel_move);
- if (out_frame_size != 0u) {
- __ Claim(out_frame_size);
- GetAssembler()->cfi().AdjustCFAOffset(out_frame_size);
- GetMoveResolver()->EmitNativeCode(¶llel_move);
- }
+ GetCriticalNativeDirectCallFrameSize>(invoke);
call_code_pointer_member(ArtMethod::EntryPointFromJniOffset(kArm64PointerSize));
// Zero-/sign-extend the result when needed due to native and managed ABI mismatch.
switch (invoke->GetType()) {
@@ -4484,8 +4488,7 @@
break;
}
if (out_frame_size != 0u) {
- __ Drop(out_frame_size);
- GetAssembler()->cfi().AdjustCFAOffset(-out_frame_size);
+ DecreaseFrame(out_frame_size);
}
break;
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index bebf43d..5c62e0a 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -894,6 +894,9 @@
// artReadBarrierForRootSlow.
void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
+ void IncreaseFrame(size_t adjustment) override;
+ void DecreaseFrame(size_t adjustment) override;
+
void GenerateNop() override;
void GenerateImplicitNullCheck(HNullCheck* instruction) override;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 9916257..cafb601 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2088,6 +2088,7 @@
static_assert(ArtMethod::MaxCounter() == 0xFFFF, "asm is probably wrong");
if (!is_frame_entry) {
__ Push(vixl32::Register(kMethodRegister));
+ GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize);
GetAssembler()->LoadFromOffset(kLoadWord, kMethodRegister, sp, kArmWordSize);
}
// Load with zero extend to clear the high bits for integer overflow check.
@@ -2098,6 +2099,7 @@
__ Strh(temp, MemOperand(kMethodRegister, ArtMethod::HotnessCountOffset().Int32Value()));
if (!is_frame_entry) {
__ Pop(vixl32::Register(kMethodRegister));
+ GetAssembler()->cfi().AdjustCFAOffset(-static_cast<int>(kArmWordSize));
}
}
@@ -2111,6 +2113,7 @@
temps.Exclude(ip);
if (!is_frame_entry) {
__ Push(r4); // Will be used as temporary. For frame entry, r4 is always available.
+ GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize);
}
__ Mov(r4, address);
__ Ldrh(ip, MemOperand(r4, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
@@ -2118,6 +2121,7 @@
__ Strh(ip, MemOperand(r4, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
if (!is_frame_entry) {
__ Pop(r4);
+ GetAssembler()->cfi().AdjustCFAOffset(-static_cast<int>(kArmWordSize));
}
__ Lsls(ip, ip, 16);
__ B(ne, &done);
@@ -2130,9 +2134,12 @@
uint32_t core_spill_mask =
(1 << lr.GetCode()) | (1 << r0.GetCode()) | (1 << r1.GetCode()) | (1 << r2.GetCode());
__ Push(RegisterList(core_spill_mask));
+ GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(core_spill_mask));
__ Ldr(lr, MemOperand(tr, entry_point_offset));
__ Blx(lr);
__ Pop(RegisterList(core_spill_mask));
+ GetAssembler()->cfi().AdjustCFAOffset(
+ -static_cast<int>(kArmWordSize) * POPCOUNT(core_spill_mask));
} else {
if (!RequiresCurrentMethod()) {
CHECK(is_frame_entry);
@@ -2240,8 +2247,7 @@
__ Push(RegisterList(MaxInt<uint32_t>(fp_spills_offset / kArmWordSize)));
GetAssembler()->cfi().AdjustCFAOffset(fp_spills_offset);
} else {
- __ Sub(sp, sp, dchecked_integral_cast<int32_t>(fp_spills_offset));
- GetAssembler()->cfi().AdjustCFAOffset(fp_spills_offset);
+ IncreaseFrame(fp_spills_offset);
if (RequiresCurrentMethod()) {
GetAssembler()->StoreToOffset(kStoreWord, kMethodRegister, sp, 0);
}
@@ -2297,8 +2303,7 @@
}
} else {
GetAssembler()->cfi().RememberState();
- __ Add(sp, sp, fp_spills_offset);
- GetAssembler()->cfi().AdjustCFAOffset(-dchecked_integral_cast<int32_t>(fp_spills_offset));
+ DecreaseFrame(fp_spills_offset);
if (fpu_spill_mask_ != 0) {
uint32_t first = LeastSignificantBit(fpu_spill_mask_);
@@ -2995,6 +3000,16 @@
// MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
}
+void CodeGeneratorARMVIXL::IncreaseFrame(size_t adjustment) {
+ __ Claim(adjustment);
+ GetAssembler()->cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorARMVIXL::DecreaseFrame(size_t adjustment) {
+ __ Drop(adjustment);
+ GetAssembler()->cfi().AdjustCFAOffset(-adjustment);
+}
+
void CodeGeneratorARMVIXL::GenerateNop() {
__ Nop();
}
@@ -9013,16 +9028,10 @@
}
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative: {
- HParallelMove parallel_move(GetGraph()->GetAllocator());
size_t out_frame_size =
PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorARMVIXL,
kAapcsStackAlignment,
- GetCriticalNativeDirectCallFrameSize>(invoke, ¶llel_move);
- if (out_frame_size != 0u) {
- __ Claim(out_frame_size);
- GetAssembler()->cfi().AdjustCFAOffset(out_frame_size);
- GetMoveResolver()->EmitNativeCode(¶llel_move);
- }
+ GetCriticalNativeDirectCallFrameSize>(invoke);
call_code_pointer_member(ArtMethod::EntryPointFromJniOffset(kArmPointerSize));
// Move the result when needed due to native and managed ABI mismatch.
switch (invoke->GetType()) {
@@ -9045,8 +9054,7 @@
break;
}
if (out_frame_size != 0u) {
- __ Drop(out_frame_size);
- GetAssembler()->cfi().AdjustCFAOffset(-out_frame_size);
+ DecreaseFrame(out_frame_size);
}
break;
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index d6300c7..b8d20d1 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -756,6 +756,9 @@
// artReadBarrierForRootSlow.
void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
+ void IncreaseFrame(size_t adjustment) override;
+ void DecreaseFrame(size_t adjustment) override;
+
void GenerateNop() override;
void GenerateImplicitNullCheck(HNullCheck* instruction) override;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 595b31e..99d3240 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1080,6 +1080,7 @@
reg = kMethodRegisterArgument;
} else {
__ pushl(EAX);
+ __ cfi().AdjustCFAOffset(4);
__ movl(EAX, Address(ESP, kX86WordSize));
}
NearLabel overflow;
@@ -1091,6 +1092,7 @@
__ Bind(&overflow);
if (!is_frame_entry) {
__ popl(EAX);
+ __ cfi().AdjustCFAOffset(-4);
}
}
@@ -1103,8 +1105,7 @@
if (HasEmptyFrame()) {
CHECK(is_frame_entry);
// Alignment
- __ subl(ESP, Immediate(8));
- __ cfi().AdjustCFAOffset(8);
+ IncreaseFrame(8);
// We need a temporary. The stub also expects the method at bottom of stack.
__ pushl(EAX);
__ cfi().AdjustCFAOffset(4);
@@ -1119,8 +1120,7 @@
// code easier to reason about.
__ popl(EAX);
__ cfi().AdjustCFAOffset(-4);
- __ addl(ESP, Immediate(8));
- __ cfi().AdjustCFAOffset(-8);
+ DecreaseFrame(8);
} else {
if (!RequiresCurrentMethod()) {
CHECK(is_frame_entry);
@@ -1167,8 +1167,7 @@
}
int adjust = GetFrameSize() - FrameEntrySpillSize();
- __ subl(ESP, Immediate(adjust));
- __ cfi().AdjustCFAOffset(adjust);
+ IncreaseFrame(adjust);
// Save the current method if we need it. Note that we do not
// do this in HCurrentMethod, as the instruction might have been removed
// in the SSA graph.
@@ -1189,8 +1188,7 @@
__ cfi().RememberState();
if (!HasEmptyFrame()) {
int adjust = GetFrameSize() - FrameEntrySpillSize();
- __ addl(ESP, Immediate(adjust));
- __ cfi().AdjustCFAOffset(-adjust);
+ DecreaseFrame(adjust);
for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
Register reg = kCoreCalleeSaves[i];
@@ -1401,15 +1399,14 @@
__ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
} else if (source.IsRegisterPair()) {
size_t elem_size = DataType::Size(DataType::Type::kInt32);
- // Create stack space for 2 elements.
- __ subl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(2 * elem_size);
- __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>());
- __ movl(Address(ESP, elem_size), source.AsRegisterPairHigh<Register>());
+ // Push the 2 source registers to the stack.
+ __ pushl(source.AsRegisterPairHigh<Register>());
+ __ cfi().AdjustCFAOffset(elem_size);
+ __ pushl(source.AsRegisterPairLow<Register>());
+ __ cfi().AdjustCFAOffset(elem_size);
__ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
// And remove the temporary stack space we allocated.
- __ addl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(-(2 * elem_size));
+ DecreaseFrame(2 * elem_size);
} else {
LOG(FATAL) << "Unimplemented";
}
@@ -1970,6 +1967,16 @@
// MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
}
+void CodeGeneratorX86::IncreaseFrame(size_t adjustment) {
+ __ subl(ESP, Immediate(adjustment));
+ __ cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorX86::DecreaseFrame(size_t adjustment) {
+ __ addl(ESP, Immediate(adjustment));
+ __ cfi().AdjustCFAOffset(-adjustment);
+}
+
void CodeGeneratorX86::GenerateNop() {
__ nop();
}
@@ -3025,8 +3032,7 @@
// TODO: enhance register allocator to ask for stack temporaries.
if (!in.IsDoubleStackSlot() || !out.IsStackSlot()) {
adjustment = DataType::Size(DataType::Type::kInt64);
- __ subl(ESP, Immediate(adjustment));
- __ cfi().AdjustCFAOffset(adjustment);
+ codegen_->IncreaseFrame(adjustment);
}
// Load the value to the FP stack, using temporaries if needed.
@@ -3042,8 +3048,7 @@
// Remove the temporary stack space we allocated.
if (adjustment != 0) {
- __ addl(ESP, Immediate(adjustment));
- __ cfi().AdjustCFAOffset(-adjustment);
+ codegen_->DecreaseFrame(adjustment);
}
break;
}
@@ -3077,8 +3082,7 @@
// TODO: enhance register allocator to ask for stack temporaries.
if (!in.IsDoubleStackSlot() || !out.IsDoubleStackSlot()) {
adjustment = DataType::Size(DataType::Type::kInt64);
- __ subl(ESP, Immediate(adjustment));
- __ cfi().AdjustCFAOffset(adjustment);
+ codegen_->IncreaseFrame(adjustment);
}
// Load the value to the FP stack, using temporaries if needed.
@@ -3094,8 +3098,7 @@
// Remove the temporary stack space we allocated.
if (adjustment != 0) {
- __ addl(ESP, Immediate(adjustment));
- __ cfi().AdjustCFAOffset(-adjustment);
+ codegen_->DecreaseFrame(adjustment);
}
break;
}
@@ -3591,8 +3594,7 @@
// Create stack space for 2 elements.
// TODO: enhance register allocator to ask for stack temporaries.
- __ subl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(2 * elem_size);
+ codegen_->IncreaseFrame(2 * elem_size);
// Load the values to the FP stack in reverse order, using temporaries if needed.
const bool is_wide = !is_float;
@@ -3632,8 +3634,7 @@
}
// And remove the temporary stack space we allocated.
- __ addl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(-(2 * elem_size));
+ codegen_->DecreaseFrame(2 * elem_size);
}
@@ -5054,16 +5055,10 @@
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative: {
- HParallelMove parallel_move(GetGraph()->GetAllocator());
size_t out_frame_size =
PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorX86,
kNativeStackAlignment,
- GetCriticalNativeDirectCallFrameSize>(invoke, ¶llel_move);
- if (out_frame_size != 0u) {
- __ subl(ESP, Immediate(out_frame_size));
- __ cfi().AdjustCFAOffset(out_frame_size);
- GetMoveResolver()->EmitNativeCode(¶llel_move);
- }
+ GetCriticalNativeDirectCallFrameSize>(invoke);
// (callee_method + offset_of_jni_entry_point)()
__ call(Address(callee_method.AsRegister<Register>(),
ArtMethod::EntryPointFromJniOffset(kX86PointerSize).Int32Value()));
@@ -5071,8 +5066,7 @@
if (out_frame_size == 0u && DataType::IsFloatingPointType(invoke->GetType())) {
// Create space for conversion.
out_frame_size = 8u;
- __ subl(ESP, Immediate(out_frame_size));
- __ cfi().AdjustCFAOffset(out_frame_size);
+ IncreaseFrame(out_frame_size);
}
// Zero-/sign-extend or move the result when needed due to native and managed ABI mismatch.
switch (invoke->GetType()) {
@@ -5105,8 +5099,7 @@
break;
}
if (out_frame_size != 0u) {
- __ addl(ESP, Immediate(out_frame_size));
- __ cfi().AdjustCFAOffset(-out_frame_size);
+ DecreaseFrame(out_frame_size);
}
break;
}
@@ -6466,7 +6459,7 @@
__ movl(destination.AsRegisterPairHigh<Register>(), source.AsRegisterPairHigh<Register>());
} else if (destination.IsFpuRegister()) {
size_t elem_size = DataType::Size(DataType::Type::kInt32);
- // Push the 2 source registers to stack.
+ // Push the 2 source registers to the stack.
__ pushl(source.AsRegisterPairHigh<Register>());
__ cfi().AdjustCFAOffset(elem_size);
__ pushl(source.AsRegisterPairLow<Register>());
@@ -6474,8 +6467,7 @@
// Load the destination register.
__ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
// And remove the temporary stack space we allocated.
- __ addl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(-(2 * elem_size));
+ codegen_->DecreaseFrame(2 * elem_size);
} else {
DCHECK(destination.IsDoubleStackSlot());
__ movl(Address(ESP, destination.GetStackIndex()), source.AsRegisterPairLow<Register>());
@@ -6490,8 +6482,7 @@
} else if (destination.IsRegisterPair()) {
size_t elem_size = DataType::Size(DataType::Type::kInt32);
// Create stack space for 2 elements.
- __ subl(ESP, Immediate(2 * elem_size));
- __ cfi().AdjustCFAOffset(2 * elem_size);
+ codegen_->IncreaseFrame(2 * elem_size);
// Store the source register.
__ movsd(Address(ESP, 0), source.AsFpuRegister<XmmRegister>());
// And pop the values into destination registers.
@@ -6600,8 +6591,7 @@
__ pushl(low);
__ cfi().AdjustCFAOffset(4);
__ movsd(dest, Address(ESP, 0));
- __ addl(ESP, Immediate(8));
- __ cfi().AdjustCFAOffset(-8);
+ codegen_->DecreaseFrame(8);
}
} else {
DCHECK(destination.IsDoubleStackSlot()) << destination;
@@ -6638,13 +6628,11 @@
void ParallelMoveResolverX86::Exchange128(XmmRegister reg, int mem) {
size_t extra_slot = 4 * kX86WordSize;
- __ subl(ESP, Immediate(extra_slot));
- __ cfi().AdjustCFAOffset(extra_slot);
+ codegen_->IncreaseFrame(extra_slot);
__ movups(Address(ESP, 0), XmmRegister(reg));
ExchangeMemory(0, mem + extra_slot, 4);
__ movups(XmmRegister(reg), Address(ESP, 0));
- __ addl(ESP, Immediate(extra_slot));
- __ cfi().AdjustCFAOffset(-extra_slot);
+ codegen_->DecreaseFrame(extra_slot);
}
void ParallelMoveResolverX86::ExchangeMemory(int mem1, int mem2, int number_of_words) {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 22d8778..c267f76 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -647,6 +647,9 @@
}
}
+ void IncreaseFrame(size_t adjustment) override;
+ void DecreaseFrame(size_t adjustment) override;
+
void GenerateNop() override;
void GenerateImplicitNullCheck(HNullCheck* instruction) override;
void GenerateExplicitNullCheck(HNullCheck* instruction) override;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 4a0cc78..2df2d16 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1046,16 +1046,10 @@
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative: {
- HParallelMove parallel_move(GetGraph()->GetAllocator());
size_t out_frame_size =
PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorX86_64,
kNativeStackAlignment,
- GetCriticalNativeDirectCallFrameSize>(invoke, ¶llel_move);
- if (out_frame_size != 0u) {
- __ subq(CpuRegister(RSP), Immediate(out_frame_size));
- __ cfi().AdjustCFAOffset(out_frame_size);
- GetMoveResolver()->EmitNativeCode(¶llel_move);
- }
+ GetCriticalNativeDirectCallFrameSize>(invoke);
// (callee_method + offset_of_jni_entry_point)()
__ call(Address(callee_method.AsRegister<CpuRegister>(),
ArtMethod::EntryPointFromJniOffset(kX86_64PointerSize).SizeValue()));
@@ -1085,8 +1079,7 @@
break;
}
if (out_frame_size != 0u) {
- __ addq(CpuRegister(RSP), Immediate(out_frame_size));
- __ cfi().AdjustCFAOffset(-out_frame_size);
+ DecreaseFrame(out_frame_size);
}
break;
}
@@ -1477,8 +1470,7 @@
}
int adjust = GetFrameSize() - GetCoreSpillSize();
- __ subq(CpuRegister(RSP), Immediate(adjust));
- __ cfi().AdjustCFAOffset(adjust);
+ IncreaseFrame(adjust);
uint32_t xmm_spill_location = GetFpuSpillStart();
size_t xmm_spill_slot_size = GetCalleePreservedFPWidth();
@@ -1523,8 +1515,7 @@
}
int adjust = GetFrameSize() - GetCoreSpillSize();
- __ addq(CpuRegister(RSP), Immediate(adjust));
- __ cfi().AdjustCFAOffset(-adjust);
+ DecreaseFrame(adjust);
for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
Register reg = kCoreCalleeSaves[i];
@@ -2045,6 +2036,16 @@
// MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
}
+void CodeGeneratorX86_64::IncreaseFrame(size_t adjustment) {
+ __ subq(CpuRegister(RSP), Immediate(adjustment));
+ __ cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorX86_64::DecreaseFrame(size_t adjustment) {
+ __ addq(CpuRegister(RSP), Immediate(adjustment));
+ __ cfi().AdjustCFAOffset(-adjustment);
+}
+
void CodeGeneratorX86_64::GenerateNop() {
__ nop();
}
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index dcdd632..d7c5b54 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -626,6 +626,9 @@
}
}
+ void IncreaseFrame(size_t adjustment) override;
+ void DecreaseFrame(size_t adjustment) override;
+
void GenerateNop() override;
void GenerateImplicitNullCheck(HNullCheck* instruction) override;
void GenerateExplicitNullCheck(HNullCheck* instruction) override;