Skip to content

Commit

Permalink
[vm] Consolidate generic move code between ParallelMoveResolver and F…
Browse files Browse the repository at this point in the history
…FICall

Will be useful for FFI callbacks.

Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try
Change-Id: I7940d4a58a036e4cb868fc89311f659039f5d23f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100381
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Aart Bik <ajcbik@google.com>
  • Loading branch information
sjindel-google authored and commit-bot@chromium.org committed Apr 30, 2019
1 parent 1dd0f88 commit 7757c3e
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 196 deletions.
5 changes: 5 additions & 0 deletions runtime/vm/compiler/assembler/assembler_ia32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,11 @@ void Assembler::Bind(Label* label) {
label->BindTo(bound);
}

void Assembler::MoveMemoryToMemory(Address dst, Address src, Register tmp) {
movl(tmp, src);
movl(dst, tmp);
}

#ifndef PRODUCT
void Assembler::MaybeTraceAllocation(intptr_t cid,
Register temp_reg,
Expand Down
4 changes: 4 additions & 0 deletions runtime/vm/compiler/assembler/assembler_ia32.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,10 @@ class Assembler : public AssemblerBase {
void Bind(Label* label);
void Jump(Label* label) { jmp(label); }

// Moves one word from the memory at [from] to the memory at [to].
// Needs a temporary register.
void MoveMemoryToMemory(Address to, Address from, Register tmp);

bool has_single_entry_point() const { return true; }

// Set up a Dart frame on entry with a frame pointer and PC information to
Expand Down
58 changes: 52 additions & 6 deletions runtime/vm/compiler/backend/flow_graph_compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,30 @@ void ParallelMoveResolver::PerformMove(int index) {
compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
}

#if !defined(TARGET_ARCH_DBC)
void ParallelMoveResolver::EmitMove(int index) {
MoveOperands* const move = moves_[index];
const Location dst = move->dest();
if (dst.IsStackSlot() || dst.IsDoubleStackSlot()) {
ASSERT((dst.base_reg() != FPREG) ||
((-compiler::target::frame_layout.VariableIndexForFrameSlot(
dst.stack_index())) < compiler_->StackSize()));
}
const Location src = move->src();
ParallelMoveResolver::TemporaryAllocator temp(this, /*blocked=*/kNoRegister);
compiler_->EmitMove(dst, src, &temp);
#if defined(DEBUG)
// Allocating a scratch register here may cause stack spilling. Neither the
// source nor destination register should be SP-relative in that case.
for (const Location loc : {dst, src}) {
ASSERT(!temp.DidAllocateTemporary() || !loc.HasStackIndex() ||
loc.base_reg() != SPREG);
}
#endif
move->Eliminate();
}
#endif

bool ParallelMoveResolver::IsScratchLocation(Location loc) {
for (int i = 0; i < moves_.length(); ++i) {
if (moves_[i]->Blocks(loc)) {
Expand Down Expand Up @@ -1753,12 +1777,19 @@ ParallelMoveResolver::ScratchFpuRegisterScope::~ScratchFpuRegisterScope() {
}
}

ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
ParallelMoveResolver::TemporaryAllocator::TemporaryAllocator(
ParallelMoveResolver* resolver,
Register blocked)
: resolver_(resolver), reg_(kNoRegister), spilled_(false) {
uword blocked_mask = RegMaskBit(blocked) | kReservedCpuRegisters;
if (resolver->compiler_->intrinsic_mode()) {
: resolver_(resolver),
blocked_(blocked),
reg_(kNoRegister),
spilled_(false) {}

Register ParallelMoveResolver::TemporaryAllocator::AllocateTemporary() {
ASSERT(reg_ == kNoRegister);

uword blocked_mask = RegMaskBit(blocked_) | kReservedCpuRegisters;
if (resolver_->compiler_->intrinsic_mode()) {
// Block additional registers that must be preserved for intrinsics.
blocked_mask |= RegMaskBit(ARGS_DESC_REG);
#if !defined(TARGET_ARCH_IA32)
Expand All @@ -1772,14 +1803,29 @@ ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
kNumberOfCpuRegisters - 1, &spilled_));

if (spilled_) {
resolver->SpillScratch(reg_);
resolver_->SpillScratch(reg_);
}

DEBUG_ONLY(allocated_ = true;)
return reg_;
}

ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
void ParallelMoveResolver::TemporaryAllocator::ReleaseTemporary() {
if (spilled_) {
resolver_->RestoreScratch(reg_);
}
reg_ = kNoRegister;
}

ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
ParallelMoveResolver* resolver,
Register blocked)
: allocator_(resolver, blocked) {
reg_ = allocator_.AllocateTemporary();
}

ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
allocator_.ReleaseTemporary();
}

const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
Expand Down
50 changes: 48 additions & 2 deletions runtime/vm/compiler/backend/flow_graph_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ class GrowableArray;
class ParsedFunction;
class SpeculativeInliningPolicy;

// Used in methods which need conditional access to a temporary register.
// May only be used to allocate a single temporary register.
class TemporaryRegisterAllocator : public ValueObject {
public:
virtual ~TemporaryRegisterAllocator() {}
virtual Register AllocateTemporary() = 0;
virtual void ReleaseTemporary() = 0;
};

class ConstantTemporaryAllocator : public TemporaryRegisterAllocator {
public:
explicit ConstantTemporaryAllocator(Register tmp) : tmp_(tmp) {}

Register AllocateTemporary() override { return tmp_; }
void ReleaseTemporary() override {}

private:
Register const tmp_;
};

class NoTemporaryAllocator : public TemporaryRegisterAllocator {
public:
Register AllocateTemporary() override { UNREACHABLE(); }
void ReleaseTemporary() override { UNREACHABLE(); }
};

class ParallelMoveResolver : public ValueObject {
public:
explicit ParallelMoveResolver(FlowGraphCompiler* compiler);
Expand All @@ -50,6 +76,24 @@ class ParallelMoveResolver : public ValueObject {
bool spilled_;
};

class TemporaryAllocator : public TemporaryRegisterAllocator {
public:
TemporaryAllocator(ParallelMoveResolver* resolver, Register blocked);

Register AllocateTemporary() override;
void ReleaseTemporary() override;
DEBUG_ONLY(bool DidAllocateTemporary() { return allocated_; })

virtual ~TemporaryAllocator() { ASSERT(reg_ == kNoRegister); }

private:
ParallelMoveResolver* const resolver_;
const Register blocked_;
Register reg_;
bool spilled_;
DEBUG_ONLY(bool allocated_ = false);
};

class ScratchRegisterScope : public ValueObject {
public:
ScratchRegisterScope(ParallelMoveResolver* resolver, Register blocked);
Expand All @@ -58,9 +102,8 @@ class ParallelMoveResolver : public ValueObject {
Register reg() const { return reg_; }

private:
ParallelMoveResolver* resolver_;
TemporaryAllocator allocator_;
Register reg_;
bool spilled_;
};

bool IsScratchLocation(Location loc);
Expand Down Expand Up @@ -427,6 +470,9 @@ class FlowGraphCompiler : public ValueObject {
// Returns 'true' if regular code generation should be skipped.
bool TryIntrinsify();

// Emits code for a generic move from a location 'src' to a location 'dst'.
void EmitMove(Location dst, Location src, TemporaryRegisterAllocator* temp);

void GenerateAssertAssignable(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
Expand Down
59 changes: 35 additions & 24 deletions runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1313,13 +1313,11 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Assembler* assembler,
}

#undef __
#define __ compiler_->assembler()->

void ParallelMoveResolver::EmitMove(int index) {
MoveOperands* move = moves_[index];
const Location source = move->src();
const Location destination = move->dest();
#define __ assembler()->

void FlowGraphCompiler::EmitMove(Location destination,
Location source,
TemporaryRegisterAllocator* allocator) {
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ mov(destination.reg(), Operand(source.reg()));
Expand Down Expand Up @@ -1351,24 +1349,32 @@ void ParallelMoveResolver::EmitMove(int index) {
__ vmovd(EvenDRegisterOf(destination.fpu_reg()),
EvenDRegisterOf(source.fpu_reg()));
}
} else if (destination.IsStackSlot()) {
// 32-bit float
const intptr_t dest_offset = destination.ToStackSlotOffset();
const SRegister src = EvenSRegisterOf(EvenDRegisterOf(source.fpu_reg()));
__ StoreSToOffset(src, destination.base_reg(), dest_offset);
} else if (destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
DRegister src = EvenDRegisterOf(source.fpu_reg());
__ StoreDToOffset(src, destination.base_reg(), dest_offset);
} else {
if (destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
DRegister src = EvenDRegisterOf(source.fpu_reg());
__ StoreDToOffset(src, destination.base_reg(), dest_offset);
} else {
ASSERT(destination.IsQuadStackSlot());
const intptr_t dest_offset = destination.ToStackSlotOffset();
const DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
__ StoreMultipleDToOffset(dsrc0, 2, destination.base_reg(),
dest_offset);
}
ASSERT(destination.IsQuadStackSlot());
const intptr_t dest_offset = destination.ToStackSlotOffset();
const DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
__ StoreMultipleDToOffset(dsrc0, 2, destination.base_reg(), dest_offset);
}
} else if (source.IsDoubleStackSlot()) {
if (destination.IsFpuRegister()) {
const intptr_t source_offset = source.ToStackSlotOffset();
const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
__ LoadDFromOffset(dst, source.base_reg(), source_offset);
} else if (destination.IsStackSlot()) {
// 32-bit float
const intptr_t source_offset = source.ToStackSlotOffset();
const intptr_t dest_offset = destination.ToStackSlotOffset();
__ LoadSFromOffset(STMP, source.base_reg(), source_offset);
__ StoreSToOffset(STMP, destination.base_reg(), dest_offset);
} else {
ASSERT(destination.IsDoubleStackSlot());
const intptr_t source_offset = source.ToStackSlotOffset();
Expand All @@ -1389,22 +1395,27 @@ void ParallelMoveResolver::EmitMove(int index) {
__ LoadMultipleDFromOffset(dtmp0, 2, source.base_reg(), source_offset);
__ StoreMultipleDToOffset(dtmp0, 2, destination.base_reg(), dest_offset);
}
} else if (source.IsPairLocation()) {
ASSERT(destination.IsPairLocation());
for (intptr_t i : {0, 1}) {
EmitMove(destination.Component(i), source.Component(i), allocator);
}
} else {
ASSERT(source.IsConstant());

if (destination.IsFpuRegister() || destination.IsDoubleStackSlot() ||
destination.IsStackSlot()) {
ScratchRegisterScope scratch(this, kNoRegister);
source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
scratch.reg());
Register tmp = allocator->AllocateTemporary();
source.constant_instruction()->EmitMoveToLocation(this, destination, tmp);
allocator->ReleaseTemporary();
} else {
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
source.constant_instruction()->EmitMoveToLocation(this, destination);
}
}

move->Eliminate();
}

#undef __
#define __ compiler_->assembler()->

void ParallelMoveResolver::EmitSwap(int index) {
MoveOperands* move = moves_[index];
const Location source = move->src();
Expand Down
36 changes: 19 additions & 17 deletions runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1305,13 +1305,11 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Assembler* assembler,
}

#undef __
#define __ compiler_->assembler()->

void ParallelMoveResolver::EmitMove(int index) {
MoveOperands* move = moves_[index];
const Location source = move->src();
const Location destination = move->dest();
#define __ assembler()->

void FlowGraphCompiler::EmitMove(Location destination,
Location source,
TemporaryRegisterAllocator* allocator) {
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ mov(destination.reg(), source.reg());
Expand All @@ -1328,15 +1326,17 @@ void ParallelMoveResolver::EmitMove(int index) {
ASSERT(destination.IsStackSlot());
const intptr_t source_offset = source.ToStackSlotOffset();
const intptr_t dest_offset = destination.ToStackSlotOffset();
ScratchRegisterScope tmp(this, kNoRegister);
__ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset);
__ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
Register tmp = allocator->AllocateTemporary();
__ LoadFromOffset(tmp, source.base_reg(), source_offset);
__ StoreToOffset(tmp, destination.base_reg(), dest_offset);
allocator->ReleaseTemporary();
}
} else if (source.IsFpuRegister()) {
if (destination.IsFpuRegister()) {
__ vmov(destination.fpu_reg(), source.fpu_reg());
} else {
if (destination.IsDoubleStackSlot()) {
if (destination.IsStackSlot() /*32-bit float*/ ||
destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
VRegister src = source.fpu_reg();
__ StoreDToOffset(src, destination.base_reg(), dest_offset);
Expand All @@ -1353,7 +1353,8 @@ void ParallelMoveResolver::EmitMove(int index) {
const VRegister dst = destination.fpu_reg();
__ LoadDFromOffset(dst, source.base_reg(), source_offset);
} else {
ASSERT(destination.IsDoubleStackSlot());
ASSERT(destination.IsDoubleStackSlot() ||
destination.IsStackSlot() /*32-bit float*/);
const intptr_t source_offset = source.ToStackSlotOffset();
const intptr_t dest_offset = destination.ToStackSlotOffset();
__ LoadDFromOffset(VTMP, source.base_reg(), source_offset);
Expand All @@ -1374,17 +1375,18 @@ void ParallelMoveResolver::EmitMove(int index) {
} else {
ASSERT(source.IsConstant());
if (destination.IsStackSlot()) {
ScratchRegisterScope scratch(this, kNoRegister);
source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
scratch.reg());
Register tmp = allocator->AllocateTemporary();
source.constant_instruction()->EmitMoveToLocation(this, destination, tmp);
allocator->ReleaseTemporary();
} else {
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
source.constant_instruction()->EmitMoveToLocation(this, destination);
}
}

move->Eliminate();
}

#undef __
#define __ compiler_->assembler()->

void ParallelMoveResolver::EmitSwap(int index) {
MoveOperands* move = moves_[index];
const Location source = move->src();
Expand Down
Loading

0 comments on commit 7757c3e

Please sign in to comment.