[vm/compiler] Rename PushArgument to MoveArgument

This is follow up to 65f4a733bb,
which switched optimized code to use fixed frame for outgoing
arguments.

Change Kernel to IL translation to handle null-checks in
invocations differently: this code used to duplicate receiver on
the stack to accomodate for PushArgument in unoptimized code, but
PushArgument has not been inserted since f4e61eacfd,
which means duplication of the receiver is no longer necessary.

TEST=ci

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try
Change-Id: I6c1f1e8c354f9ea92424b6602b83b9e9ebce8b69
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/284184
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Vyacheslav Egorov 2023-02-20 14:57:57 +00:00 committed by Commit Queue
parent 354e8068a4
commit 93e73bf93a
35 changed files with 238 additions and 338 deletions

View file

@ -35,14 +35,14 @@ void matchIL$test(FlowGraph graph) {
'bar' << match.Parameter(index: 3),
'baz' << match.Parameter(index: 4),
match.CheckStackOverflow(),
match.PushArgument('x'),
match.MoveArgument('x'),
match.StaticCall(),
match.PushArgument('y'),
match.MoveArgument('y'),
match.StaticCall(),
'baz_boxed' << match.BoxInt64('baz'),
match.PushArgument('foo'),
match.MoveArgument('foo'),
match.StaticCall(),
match.PushArgument('baz_boxed'),
match.MoveArgument('baz_boxed'),
match.StaticCall(),
match.Return(),
]),

View file

@ -103,42 +103,42 @@ void matchIL$test(FlowGraph graph) {
'obj2' << match.Parameter(index: 5),
match.CheckStackOverflow(),
match.PushArgument('x'),
match.PushArgument('z'),
match.MoveArgument('x'),
match.MoveArgument('z'),
'r1' << match.StaticCall(),
'r1_0' << match.ExtractNthOutput('r1', index: 0),
'r1_1' << match.ExtractNthOutput('r1', index: 1),
match.PushArgument('r1_0'),
match.MoveArgument('r1_0'),
match.StaticCall(),
match.PushArgument('r1_1'),
match.MoveArgument('r1_1'),
match.StaticCall(),
match.PushArgument('foo'),
match.PushArgument('bar'),
match.MoveArgument('foo'),
match.MoveArgument('bar'),
'r2' << match.StaticCall(),
'r2_bar' << match.ExtractNthOutput('r2', index: 0),
'r2_foo' << match.ExtractNthOutput('r2', index: 1),
match.PushArgument('r2_foo'),
match.MoveArgument('r2_foo'),
match.StaticCall(),
match.PushArgument('r2_bar'),
match.MoveArgument('r2_bar'),
match.StaticCall(),
match.PushArgument('obj1'),
match.MoveArgument('obj1'),
'r3' << match.StaticCall(),
'r3_0' << match.ExtractNthOutput('r3', index: 0),
'r3_y' << match.ExtractNthOutput('r3', index: 1),
match.PushArgument('r3_0'),
match.MoveArgument('r3_0'),
match.StaticCall(),
match.PushArgument('r3_y'),
match.MoveArgument('r3_y'),
match.StaticCall(),
'obj2_cid' << match.LoadClassId('obj2'),
match.PushArgument('obj2'),
match.MoveArgument('obj2'),
'r4' << match.DispatchTableCall('obj2_cid'),
'r4_0' << match.ExtractNthOutput('r4', index: 0),
'r4_y' << match.ExtractNthOutput('r4', index: 1),
'r4_boxed' << match.AllocateSmallRecord('r4_0', 'r4_y'),
match.PushArgument('r4_boxed'),
match.MoveArgument('r4_boxed'),
match.StaticCall(),
match.Return(),

View file

@ -432,8 +432,8 @@ void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) {
SetValue(instr, non_constant_);
}
void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
UNREACHABLE();
void ConstantPropagator::VisitMoveArgument(MoveArgumentInstr* instr) {
UNREACHABLE(); // Inserted right before register allocation.
}
void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) {
@ -1753,7 +1753,6 @@ bool ConstantPropagator::TransformDefinition(Definition* defn) {
// Replace constant-valued instructions without observable side
// effects. Do this for smis and old objects only to avoid having to
// copy other objects into the heap's old generation.
ASSERT((defn == nullptr) || !defn->IsPushArgument());
if ((defn != nullptr) && IsConstant(defn->constant_value()) &&
(defn->constant_value().IsSmi() || defn->constant_value().IsOld()) &&
!defn->IsConstant() && !defn->IsStoreIndexed() && !defn->IsStoreField() &&
@ -1770,7 +1769,7 @@ bool ConstantPropagator::TransformDefinition(Definition* defn) {
ASSERT(!constant_value_.IsNull());
}
if (auto call = defn->AsStaticCall()) {
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
}
Definition* replacement =
graph_->TryCreateConstantReplacementFor(defn, constant_value_);

View file

@ -158,7 +158,7 @@ void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator,
}
}
if (current->ArgumentCount() != 0) {
ASSERT(!current->HasPushArguments());
ASSERT(!current->HasMoveArguments());
}
iterator->RemoveCurrentFromGraph();
}
@ -1558,7 +1558,7 @@ void FlowGraph::RenameRecursive(
break;
}
case Instruction::kPushArgument:
case Instruction::kMoveArgument:
UNREACHABLE();
break;
@ -1628,7 +1628,7 @@ void FlowGraph::RenameRecursive(
// Rename input operand.
Definition* input = (*env)[i];
ASSERT(input != nullptr);
ASSERT(!input->IsPushArgument());
ASSERT(!input->IsMoveArgument());
Value* use = new (zone()) Value(input);
phi->SetInputAt(pred_index, use);
}
@ -2414,7 +2414,7 @@ void FlowGraph::WidenSmiToInt32() {
if (use_defn == NULL) {
// We assume that tagging before returning or pushing argument costs
// very little compared to the cost of the return/call itself.
ASSERT(!instr->IsPushArgument());
ASSERT(!instr->IsMoveArgument());
if (!instr->IsReturn() &&
(use->use_index() >= instr->ArgumentCount())) {
gain--;
@ -2998,7 +2998,7 @@ PhiInstr* FlowGraph::AddPhi(JoinEntryInstr* join,
return phi;
}
void FlowGraph::InsertPushArguments() {
void FlowGraph::InsertMoveArguments() {
intptr_t max_argument_slot_count = 0;
for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
block_it.Advance()) {
@ -3010,37 +3010,37 @@ void FlowGraph::InsertPushArguments() {
if (arg_count == 0) {
continue;
}
PushArgumentsArray* arguments =
new (Z) PushArgumentsArray(zone(), arg_count);
MoveArgumentsArray* arguments =
new (Z) MoveArgumentsArray(zone(), arg_count);
arguments->EnsureLength(arg_count, nullptr);
intptr_t top_of_stack_relative_index = 0;
intptr_t sp_relative_index = 0;
for (intptr_t i = arg_count - 1; i >= 0; --i) {
Value* arg = instruction->ArgumentValueAt(i);
const auto rep = instruction->RequiredInputRepresentation(i);
(*arguments)[i] = new (Z) PushArgumentInstr(
arg->CopyWithType(Z), rep, top_of_stack_relative_index);
(*arguments)[i] = new (Z)
MoveArgumentInstr(arg->CopyWithType(Z), rep, sp_relative_index);
static_assert(compiler::target::kIntSpillFactor ==
compiler::target::kDoubleSpillFactor,
"double and int are expected to be of the same size");
RELEASE_ASSERT(rep == kTagged || rep == kUnboxedDouble ||
rep == kUnboxedInt64);
top_of_stack_relative_index +=
sp_relative_index +=
(rep == kTagged) ? 1 : compiler::target::kIntSpillFactor;
}
max_argument_slot_count =
Utils::Maximum(max_argument_slot_count, top_of_stack_relative_index);
Utils::Maximum(max_argument_slot_count, sp_relative_index);
for (auto push_arg : *arguments) {
// Insert all PushArgument instructions immediately before call.
// PushArgumentInstr::EmitNativeCode may generate more efficient
// code for subsequent PushArgument instructions (ARM, ARM64).
InsertBefore(instruction, push_arg, /*env=*/nullptr, kEffect);
for (auto move_arg : *arguments) {
// Insert all MoveArgument instructions immediately before call.
// MoveArgumentInstr::EmitNativeCode may generate more efficient
// code for subsequent MoveArgument instructions (ARM, ARM64).
InsertBefore(instruction, move_arg, /*env=*/nullptr, kEffect);
}
instruction->ReplaceInputsWithPushArguments(arguments);
instruction->ReplaceInputsWithMoveArguments(arguments);
if (instruction->env() != nullptr) {
instruction->RepairPushArgsInEnvironment();
instruction->RepairArgumentUsesInEnvironment();
}
}
}

View file

@ -382,11 +382,11 @@ class FlowGraph : public ZoneAllocated {
// Remove the redefinition instructions inserted to inhibit code motion.
void RemoveRedefinitions(bool keep_checks = false);
// Insert PushArgument instructions and remove explicit def-use
// Insert MoveArgument instructions and remove explicit def-use
// relations between calls and their arguments.
//
// Compute the maximum number of arguments.
void InsertPushArguments();
void InsertMoveArguments();
// Copy deoptimization target from one instruction to another if we still
// have to keep deoptimization environment at gotos for LICM purposes.

View file

@ -140,10 +140,10 @@ static void AssertArgumentsInEnv(FlowGraph* flow_graph, Definition* call) {
ASSERT1((arg_count + after_args_input_count) <= env_count, call);
const intptr_t env_base = env_count - arg_count - after_args_input_count;
for (intptr_t i = 0; i < arg_count; i++) {
if (call->HasPushArguments()) {
if (call->HasMoveArguments()) {
ASSERT1(call->ArgumentAt(i) == env->ValueAt(env_base + i)
->definition()
->AsPushArgument()
->AsMoveArgument()
->value()
->definition(),
call);

View file

@ -95,16 +95,16 @@ compiler::LRState ComputeInnerLRState(const FlowGraph& flow_graph) {
}
#endif
// Assign locations to incoming arguments, i.e., values pushed above spill slots
// with PushArgument. Recursively allocates from outermost to innermost
// environment.
void CompilerDeoptInfo::AllocateIncomingParametersRecursive(Environment* env) {
// Assign locations to outgoing arguments. Note that MoveArgument
// can only occur in the innermost environment because we insert
// them immediately before the call instruction and right before
// register allocation.
void CompilerDeoptInfo::AllocateOutgoingArguments(Environment* env) {
if (env == NULL) return;
AllocateIncomingParametersRecursive(env->outer());
for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) {
if (it.CurrentLocation().IsInvalid()) {
if (auto push_arg = it.CurrentValue()->definition()->AsPushArgument()) {
it.SetCurrentLocation(push_arg->locs()->out(0));
if (auto move_arg = it.CurrentValue()->definition()->AsMoveArgument()) {
it.SetCurrentLocation(move_arg->locs()->out(0));
}
}
}
@ -592,8 +592,7 @@ static bool IsPusher(Instruction* instr) {
static bool IsPopper(Instruction* instr) {
// TODO(ajcbik): even allow deopt targets by making environment aware?
if (!instr->CanBecomeDeoptimizationTarget()) {
return !instr->IsPushArgument() && instr->ArgumentCount() == 0 &&
instr->InputCount() > 0;
return instr->ArgumentCount() == 0 && instr->InputCount() > 0;
}
return false;
}
@ -1040,21 +1039,21 @@ void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs,
RELEASE_ASSERT(args_count == 0 || is_optimizing());
for (intptr_t i = 0; i < args_count; i++) {
const auto push_arg =
instr->ArgumentValueAt(i)->instruction()->AsPushArgument();
const auto rep = push_arg->representation();
const auto move_arg =
instr->ArgumentValueAt(i)->instruction()->AsMoveArgument();
const auto rep = move_arg->representation();
ASSERT(rep == kTagged || rep == kUnboxedInt64 || rep == kUnboxedDouble);
static_assert(compiler::target::kIntSpillFactor ==
compiler::target::kDoubleSpillFactor,
"int and double are of the same size");
const bool is_tagged = push_arg->representation() == kTagged;
const bool is_tagged = move_arg->representation() == kTagged;
const intptr_t num_bits =
is_tagged ? 1 : compiler::target::kIntSpillFactor;
// Note: bits are reversed so higher bit corresponds to lower word.
const intptr_t last_arg_bit =
(spill_area_size - 1) - push_arg->top_of_stack_relative_index();
(spill_area_size - 1) - move_arg->sp_relative_index();
bitmap.SetRange(last_arg_bit - (num_bits - 1), last_arg_bit, is_tagged);
}
ASSERT(slow_path_argument_count == 0 || !using_shared_stub);
@ -1731,7 +1730,7 @@ void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
}
// Allocate all unallocated input locations.
RELEASE_ASSERT(!instr->IsPushArgument());
ASSERT(!instr->IsMoveArgument());
Register fpu_unboxing_temp = kNoRegister;
for (intptr_t i = locs->input_count() - 1; i >= 0; i--) {
Location loc = locs->in(i);
@ -3292,10 +3291,6 @@ void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
ASSERT(!is_optimizing());
switch (instr->tag()) {
case Instruction::kPushArgument:
// Do nothing.
break;
case Instruction::kDropTemps:
FrameStatePop(instr->locs()->input_count() +
instr->AsDropTemps()->num_temps());

View file

@ -199,7 +199,7 @@ class CompilerDeoptInfo : public ZoneAllocated {
private:
void EmitMaterializations(Environment* env, DeoptInfoBuilder* builder);
void AllocateIncomingParametersRecursive(Environment* env);
void AllocateOutgoingArguments(Environment* env);
intptr_t pc_offset_;
const intptr_t deopt_id_;

View file

@ -98,7 +98,7 @@ TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
return TypedData::null();
}
AllocateIncomingParametersRecursive(deopt_env_);
AllocateOutgoingArguments(deopt_env_);
intptr_t slot_ix = 0;
Environment* current = deopt_env_;

View file

@ -92,7 +92,7 @@ TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
return TypedData::null();
}
AllocateIncomingParametersRecursive(deopt_env_);
AllocateOutgoingArguments(deopt_env_);
intptr_t slot_ix = 0;
Environment* current = deopt_env_;

View file

@ -70,7 +70,7 @@ TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
return TypedData::null();
}
AllocateIncomingParametersRecursive(deopt_env_);
AllocateOutgoingArguments(deopt_env_);
intptr_t slot_ix = 0;
Environment* current = deopt_env_;

View file

@ -79,7 +79,7 @@ TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
return TypedData::null();
}
AllocateIncomingParametersRecursive(deopt_env_);
AllocateOutgoingArguments(deopt_env_);
intptr_t slot_ix = 0;
Environment* current = deopt_env_;

View file

@ -93,7 +93,7 @@ TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
return TypedData::null();
}
AllocateIncomingParametersRecursive(deopt_env_);
AllocateOutgoingArguments(deopt_env_);
intptr_t slot_ix = 0;
Environment* current = deopt_env_;

View file

@ -1475,18 +1475,18 @@ void Instruction::UnuseAllInputs() {
}
}
void Instruction::RepairPushArgsInEnvironment() const {
void Instruction::RepairArgumentUsesInEnvironment() const {
// Some calls (e.g. closure calls) have more inputs than actual arguments.
// Those extra inputs will be consumed from the stack before the call.
const intptr_t after_args_input_count = env()->LazyDeoptPruneCount();
PushArgumentsArray* push_arguments = GetPushArguments();
ASSERT(push_arguments != nullptr);
MoveArgumentsArray* move_arguments = GetMoveArguments();
ASSERT(move_arguments != nullptr);
const intptr_t arg_count = ArgumentCount();
ASSERT((arg_count + after_args_input_count) <= env()->Length());
const intptr_t env_base =
env()->Length() - arg_count - after_args_input_count;
for (intptr_t i = 0; i < arg_count; ++i) {
env()->ValueAt(env_base + i)->BindToEnvironment(push_arguments->At(i));
env()->ValueAt(env_base + i)->BindToEnvironment(move_arguments->At(i));
}
}

View file

@ -419,7 +419,7 @@ struct InstrAttrs {
M(MemoryCopy, kNoGC) \
M(TailCall, kNoGC) \
M(ParallelMove, kNoGC) \
M(PushArgument, kNoGC) \
M(MoveArgument, kNoGC) \
M(Return, kNoGC) \
M(NativeReturn, kNoGC) \
M(Throw, kNoGC) \
@ -860,7 +860,7 @@ class BinaryFeedback : public ZoneAllocated {
};
typedef GrowableArray<Value*> InputsArray;
typedef ZoneGrowableArray<PushArgumentInstr*> PushArgumentsArray;
typedef ZoneGrowableArray<MoveArgumentInstr*> MoveArgumentsArray;
template <typename Trait>
class InstructionIndexedPropertyIterable {
@ -1003,24 +1003,25 @@ class Instruction : public ZoneAllocated {
inline Value* ArgumentValueAt(intptr_t index) const;
inline Definition* ArgumentAt(intptr_t index) const;
// Sets array of PushArgument instructions.
virtual void SetPushArguments(PushArgumentsArray* push_arguments) {
// Sets array of MoveArgument instructions.
virtual void SetMoveArguments(MoveArgumentsArray* move_arguments) {
UNREACHABLE();
}
// Returns array of PushArgument instructions
virtual PushArgumentsArray* GetPushArguments() const {
// Returns array of MoveArgument instructions
virtual MoveArgumentsArray* GetMoveArguments() const {
UNREACHABLE();
return nullptr;
}
// Replace inputs with separate PushArgument instructions detached from call.
virtual void ReplaceInputsWithPushArguments(
PushArgumentsArray* push_arguments) {
// Replace inputs with separate MoveArgument instructions detached from call.
virtual void ReplaceInputsWithMoveArguments(
MoveArgumentsArray* move_arguments) {
UNREACHABLE();
}
bool HasPushArguments() const { return GetPushArguments() != nullptr; }
bool HasMoveArguments() const { return GetMoveArguments() != nullptr; }
// Repairs trailing PushArgs in environment.
void RepairPushArgsInEnvironment() const;
// Replaces direct uses of arguments with uses of corresponding MoveArgument
// instructions.
void RepairArgumentUsesInEnvironment() const;
// Returns true, if this instruction can deoptimize with its current inputs.
// This property can change if we add or remove redefinitions that constrain
@ -3163,21 +3164,20 @@ class TailCallInstr : public TemplateInstruction<1, Throws, Pure> {
DISALLOW_COPY_AND_ASSIGN(TailCallInstr);
};
class PushArgumentInstr : public TemplateDefinition<1, NoThrow> {
// Move the given argument value into the place where callee expects it.
// Currently all outgoing arguments are located in [SP+idx]
class MoveArgumentInstr : public TemplateDefinition<1, NoThrow> {
public:
explicit PushArgumentInstr(Value* value,
explicit MoveArgumentInstr(Value* value,
Representation representation,
intptr_t top_of_stack_relative_index)
: representation_(representation),
top_of_stack_relative_index_(top_of_stack_relative_index) {
intptr_t sp_relative_index)
: representation_(representation), sp_relative_index_(sp_relative_index) {
SetInputAt(0, value);
}
DECLARE_INSTRUCTION(PushArgument)
DECLARE_INSTRUCTION(MoveArgument)
intptr_t top_of_stack_relative_index() const {
return top_of_stack_relative_index_;
}
intptr_t sp_relative_index() const { return sp_relative_index_; }
virtual CompileType ComputeType() const;
@ -3188,7 +3188,7 @@ class PushArgumentInstr : public TemplateDefinition<1, NoThrow> {
virtual bool HasUnknownSideEffects() const { return false; }
virtual TokenPosition token_pos() const {
return TokenPosition::kPushArgument;
return TokenPosition::kMoveArgument;
}
virtual Representation representation() const { return representation_; }
@ -3202,20 +3202,20 @@ class PushArgumentInstr : public TemplateDefinition<1, NoThrow> {
#define FIELD_LIST(F) \
F(const Representation, representation_) \
F(const intptr_t, top_of_stack_relative_index_)
F(const intptr_t, sp_relative_index_)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(PushArgumentInstr,
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MoveArgumentInstr,
TemplateDefinition,
FIELD_LIST)
#undef FIELD_LIST
private:
DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
DISALLOW_COPY_AND_ASSIGN(MoveArgumentInstr);
};
inline Value* Instruction::ArgumentValueAt(intptr_t index) const {
PushArgumentsArray* push_arguments = GetPushArguments();
return push_arguments != nullptr ? (*push_arguments)[index]->value()
MoveArgumentsArray* move_arguments = GetMoveArguments();
return move_arguments != nullptr ? (*move_arguments)[index]->value()
: InputAt(index);
}
@ -3691,11 +3691,11 @@ class BranchInstr : public Instruction {
virtual intptr_t ArgumentCount() const {
return comparison()->ArgumentCount();
}
virtual void SetPushArguments(PushArgumentsArray* push_arguments) {
comparison()->SetPushArguments(push_arguments);
virtual void SetMoveArguments(MoveArgumentsArray* move_arguments) {
comparison()->SetMoveArguments(move_arguments);
}
virtual PushArgumentsArray* GetPushArguments() const {
return comparison()->GetPushArguments();
virtual MoveArgumentsArray* GetMoveArguments() const {
return comparison()->GetMoveArguments();
}
intptr_t InputCount() const { return comparison()->InputCount(); }
@ -4331,23 +4331,23 @@ class TemplateDartCall : public VariadicDefinition {
// ArgumentCount() includes the type argument vector if any.
// Caution: Must override Instruction::ArgumentCount().
intptr_t ArgumentCount() const {
return push_arguments_ != nullptr ? push_arguments_->length()
return move_arguments_ != nullptr ? move_arguments_->length()
: InputCount() - kExtraInputs;
}
virtual intptr_t ArgumentsSize() const { return ArgumentCount(); }
virtual void SetPushArguments(PushArgumentsArray* push_arguments) {
ASSERT(push_arguments_ == nullptr);
push_arguments_ = push_arguments;
virtual void SetMoveArguments(MoveArgumentsArray* move_arguments) {
ASSERT(move_arguments_ == nullptr);
move_arguments_ = move_arguments;
}
virtual PushArgumentsArray* GetPushArguments() const {
return push_arguments_;
virtual MoveArgumentsArray* GetMoveArguments() const {
return move_arguments_;
}
virtual void ReplaceInputsWithPushArguments(
PushArgumentsArray* push_arguments) {
ASSERT(push_arguments_ == nullptr);
ASSERT(push_arguments->length() == ArgumentCount());
SetPushArguments(push_arguments);
virtual void ReplaceInputsWithMoveArguments(
MoveArgumentsArray* move_arguments) {
ASSERT(move_arguments_ == nullptr);
ASSERT(move_arguments->length() == ArgumentCount());
SetMoveArguments(move_arguments);
ASSERT(InputCount() == ArgumentCount() + kExtraInputs);
const intptr_t extra_inputs_base = InputCount() - kExtraInputs;
for (intptr_t i = 0, n = ArgumentCount(); i < n; ++i) {
@ -4379,7 +4379,7 @@ class TemplateDartCall : public VariadicDefinition {
DECLARE_EXTRA_SERIALIZATION
private:
PushArgumentsArray* push_arguments_ = nullptr;
MoveArgumentsArray* move_arguments_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TemplateDartCall);
};
@ -4666,7 +4666,7 @@ class PolymorphicInstanceCallInstr : public InstanceCallBaseInstr {
InstanceCallBaseInstr* call,
const CallTargets& targets,
bool complete) {
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
InputsArray args(zone, call->ArgumentCount());
for (intptr_t i = 0, n = call->ArgumentCount(); i < n; ++i) {
args.Add(call->ArgumentValueAt(i)->CopyWithType(zone));
@ -5244,7 +5244,7 @@ class StaticCallInstr : public TemplateDartCall<0> {
const C* call,
const Function& target,
intptr_t call_count) {
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
InputsArray args(zone, call->ArgumentCount());
for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
args.Add(call->ArgumentValueAt(i)->CopyWithType());
@ -10833,7 +10833,7 @@ class Environment : public ZoneAllocated {
intptr_t CountArgsPushed() {
intptr_t count = 0;
for (Environment::DeepIterator it(this); !it.Done(); it.Advance()) {
if (it.CurrentValue()->definition()->IsPushArgument()) {
if (it.CurrentValue()->definition()->IsMoveArgument()) {
count++;
}
}

View file

@ -319,7 +319,7 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
}
}
LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -336,9 +336,9 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
return locs;
}
// Buffers registers to use STMDB in order to push
// Buffers registers to use STMDB in order to store
// multiple registers at once.
class ArgumentsPusher : public ValueObject {
class ArgumentsMover : public ValueObject {
public:
// Flush all buffered registers.
void Flush(FlowGraphCompiler* compiler) {
@ -393,13 +393,13 @@ class ArgumentsPusher : public ValueObject {
// Return a register which can be used to hold a value of an argument.
Register FindFreeRegister(FlowGraphCompiler* compiler,
Instruction* push_arg) {
Instruction* move_arg) {
// Dart calling conventions do not have callee-save registers,
// so arguments pushing can clobber all allocatable registers
// except registers used in arguments which were not pushed yet,
// as well as ParallelMove and inputs of a call instruction.
intptr_t busy = kReservedCpuRegisters;
for (Instruction* instr = push_arg;; instr = instr->next()) {
for (Instruction* instr = move_arg;; instr = instr->next()) {
ASSERT(instr != nullptr);
if (ParallelMoveInstr* parallel_move = instr->AsParallelMove()) {
for (intptr_t i = 0, n = parallel_move->NumMoves(); i < n; ++i) {
@ -412,7 +412,7 @@ class ArgumentsPusher : public ValueObject {
}
}
} else {
ASSERT(instr->IsPushArgument() || (instr->ArgumentCount() > 0));
ASSERT(instr->IsMoveArgument() || (instr->ArgumentCount() > 0));
for (intptr_t i = 0, n = instr->locs()->input_count(); i < n; ++i) {
const auto in_loc = instr->locs()->in(i);
if (in_loc.IsRegister()) {
@ -463,32 +463,31 @@ class ArgumentsPusher : public ValueObject {
}
};
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void MoveArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
if (previous()->IsPushArgument()) {
// Already generated by the first PushArgument in the chain.
if (previous()->IsMoveArgument()) {
// Already generated by the first MoveArgument in the chain.
return;
}
ArgumentsPusher pusher;
for (PushArgumentInstr* push_arg = this; push_arg != nullptr;
push_arg = push_arg->next()->AsPushArgument()) {
const Location value = push_arg->locs()->in(0);
ArgumentsMover pusher;
for (MoveArgumentInstr* move_arg = this; move_arg != nullptr;
move_arg = move_arg->next()->AsMoveArgument()) {
const Location value = move_arg->locs()->in(0);
if (value.IsRegister()) {
pusher.MoveRegister(compiler, push_arg->top_of_stack_relative_index(),
value.reg());
pusher.MoveRegister(compiler, move_arg->sp_relative_index(), value.reg());
} else if (value.IsPairLocation()) {
pusher.MoveRegister(compiler, push_arg->top_of_stack_relative_index() + 1,
pusher.MoveRegister(compiler, move_arg->sp_relative_index() + 1,
value.AsPairLocation()->At(1).reg());
pusher.MoveRegister(compiler, push_arg->top_of_stack_relative_index(),
pusher.MoveRegister(compiler, move_arg->sp_relative_index(),
value.AsPairLocation()->At(0).reg());
} else if (value.IsFpuRegister()) {
pusher.Flush(compiler);
__ StoreDToOffset(EvenDRegisterOf(value.fpu_reg()), SP,
push_arg->top_of_stack_relative_index() *
compiler::target::kWordSize);
__ StoreDToOffset(
EvenDRegisterOf(value.fpu_reg()), SP,
move_arg->sp_relative_index() * compiler::target::kWordSize);
} else {
const Register reg = pusher.FindFreeRegister(compiler, push_arg);
const Register reg = pusher.FindFreeRegister(compiler, move_arg);
ASSERT(reg != kNoRegister);
if (value.IsConstant()) {
__ LoadObject(reg, value.constant());
@ -497,8 +496,7 @@ void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const intptr_t value_offset = value.ToStackSlotOffset();
__ LoadFromOffset(reg, value.base_reg(), value_offset);
}
pusher.MoveRegister(compiler, push_arg->top_of_stack_relative_index(),
reg);
pusher.MoveRegister(compiler, move_arg->sp_relative_index(), reg);
}
}
pusher.Flush(compiler);

View file

@ -336,7 +336,7 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
}
}
LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -356,9 +356,9 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
return locs;
}
// Buffers registers in order to use STP to push
// Buffers registers in order to use STP to move
// two registers at once.
class ArgumentsPusher : public ValueObject {
class ArgumentsMover : public ValueObject {
public:
// Flush all buffered registers.
void Flush(FlowGraphCompiler* compiler) {
@ -404,18 +404,18 @@ class ArgumentsPusher : public ValueObject {
Register pending_register_ = kNoRegister;
};
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void MoveArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
if (previous()->IsPushArgument()) {
// Already generated by the first PushArgument in the chain.
if (previous()->IsMoveArgument()) {
// Already generated by the first MoveArgument in the chain.
return;
}
ArgumentsPusher pusher;
for (PushArgumentInstr* push_arg = this; push_arg != nullptr;
push_arg = push_arg->next()->AsPushArgument()) {
const Location value = push_arg->locs()->in(0);
ArgumentsMover pusher;
for (MoveArgumentInstr* move_arg = this; move_arg != nullptr;
move_arg = move_arg->next()->AsMoveArgument()) {
const Location value = move_arg->locs()->in(0);
Register reg = kNoRegister;
if (value.IsRegister()) {
reg = value.reg();
@ -423,7 +423,7 @@ void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (value.constant_instruction()->HasZeroRepresentation()) {
reg = ZR;
} else {
ASSERT(push_arg->representation() == kTagged);
ASSERT(move_arg->representation() == kTagged);
const Object& constant = value.constant();
if (constant.IsNull()) {
reg = NULL_REG;
@ -435,7 +435,7 @@ void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
} else if (value.IsFpuRegister()) {
pusher.Flush(compiler);
__ StoreDToOffset(value.fpu_reg(), SP,
push_arg->top_of_stack_relative_index() * kWordSize);
move_arg->sp_relative_index() * kWordSize);
continue;
} else {
ASSERT(value.IsStackSlot());
@ -443,7 +443,7 @@ void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
reg = pusher.GetFreeTempRegister(compiler);
__ LoadFromOffset(reg, value.base_reg(), value_offset);
}
pusher.MoveRegister(compiler, push_arg->top_of_stack_relative_index(), reg);
pusher.MoveRegister(compiler, move_arg->sp_relative_index(), reg);
}
pusher.Flush(compiler);
}

View file

@ -251,7 +251,7 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
__ leal(array_reg, compiler::Address(array_reg, start_reg, scale, offset));
}
LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -262,11 +262,11 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
return locs;
}
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void MoveArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
Location value = locs()->in(0);
const compiler::Address dst(ESP, top_of_stack_relative_index() * kWordSize);
const compiler::Address dst(ESP, sp_relative_index() * kWordSize);
if (value.IsConstant()) {
__ StoreToOffset(value.constant(), dst);
} else {

View file

@ -155,7 +155,7 @@ class IlTestPrinter : public AllStatic {
}
writer->CloseArray();
} else if (instr->ArgumentCount() != 0 &&
instr->GetPushArguments() != nullptr) {
instr->GetMoveArguments() != nullptr) {
writer->OpenArray("i");
for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
writer->PrintValue(
@ -1431,9 +1431,9 @@ void SuspendInstr::PrintOperandsTo(BaseTextBuffer* f) const {
f->AddString(")");
}
void PushArgumentInstr::PrintOperandsTo(BaseTextBuffer* f) const {
void MoveArgumentInstr::PrintOperandsTo(BaseTextBuffer* f) const {
value()->PrintTo(f);
f->Printf(", SP+%" Pd "", top_of_stack_relative_index());
f->Printf(", SP+%" Pd "", sp_relative_index());
}
void GotoInstr::PrintTo(BaseTextBuffer* f) const {
@ -1487,7 +1487,7 @@ void Environment::PrintTo(BaseTextBuffer* f) const {
int arg_count = 0;
for (intptr_t i = 0; i < values_.length(); ++i) {
if (i > 0) f->AddString(", ");
if (values_[i]->definition()->IsPushArgument()) {
if (values_[i]->definition()->IsMoveArgument()) {
f->Printf("a%d", arg_count++);
} else {
values_[i]->PrintTo(f);

View file

@ -376,7 +376,7 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
}
}
LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -401,12 +401,11 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
return locs;
}
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void MoveArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
const Location value = locs()->in(0);
const intptr_t offset =
top_of_stack_relative_index() * compiler::target::kWordSize;
const intptr_t offset = sp_relative_index() * compiler::target::kWordSize;
if (value.IsRegister()) {
__ StoreToOffset(value.reg(), SP, offset);
#if XLEN == 32

View file

@ -556,12 +556,12 @@ void FlowGraphSerializer::WriteRefTrait<Definition*>::WriteRef(
FlowGraphSerializer* s,
Definition* x) {
if (!x->HasSSATemp()) {
if (auto* push_arg = x->AsPushArgument()) {
// Environments of the calls can reference PushArgument instructions
if (auto* move_arg = x->AsMoveArgument()) {
// Environments of the calls can reference MoveArgument instructions
// and they don't have SSA temps.
// Write a reference to the original definition.
// When reading it is restored using RepairPushArgsInEnvironment.
x = push_arg->value()->definition();
// When reading it is restored using RepairArgumentUsesInEnvironment.
x = move_arg->value()->definition();
} else {
UNREACHABLE();
}
@ -2338,21 +2338,21 @@ void SpecialParameterInstr::ReadExtra(FlowGraphDeserializer* d) {
template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::WriteExtra(FlowGraphSerializer* s) {
VariadicDefinition::WriteExtra(s);
if (push_arguments_ == nullptr) {
if (move_arguments_ == nullptr) {
s->Write<intptr_t>(-1);
} else {
s->Write<intptr_t>(push_arguments_->length());
s->Write<intptr_t>(move_arguments_->length());
#if defined(DEBUG)
// Verify that PushArgument instructions are inserted immediately
// Verify that MoveArgument instructions are inserted immediately
// before this instruction. ReadExtra below relies on
// that when restoring push_arguments_.
// that when restoring move_arguments_.
Instruction* instr = this;
for (intptr_t i = push_arguments_->length() - 1; i >= 0; --i) {
for (intptr_t i = move_arguments_->length() - 1; i >= 0; --i) {
do {
instr = instr->previous();
ASSERT(instr != nullptr);
} while (!instr->IsPushArgument());
ASSERT(instr == (*push_arguments_)[i]);
} while (!instr->IsMoveArgument());
ASSERT(instr == (*move_arguments_)[i]);
}
#endif
}
@ -2361,21 +2361,21 @@ void TemplateDartCall<kExtraInputs>::WriteExtra(FlowGraphSerializer* s) {
template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::ReadExtra(FlowGraphDeserializer* d) {
VariadicDefinition::ReadExtra(d);
const intptr_t num_push_args = d->Read<intptr_t>();
if (num_push_args >= 0) {
push_arguments_ =
new (d->zone()) PushArgumentsArray(d->zone(), num_push_args);
push_arguments_->EnsureLength(num_push_args, nullptr);
const intptr_t num_move_args = d->Read<intptr_t>();
if (num_move_args >= 0) {
move_arguments_ =
new (d->zone()) MoveArgumentsArray(d->zone(), num_move_args);
move_arguments_->EnsureLength(num_move_args, nullptr);
Instruction* instr = this;
for (int i = num_push_args - 1; i >= 0; --i) {
for (int i = num_move_args - 1; i >= 0; --i) {
do {
instr = instr->previous();
ASSERT(instr != nullptr);
} while (!instr->IsPushArgument());
(*push_arguments_)[i] = instr->AsPushArgument();
} while (!instr->IsMoveArgument());
(*move_arguments_)[i] = instr->AsMoveArgument();
}
if (env() != nullptr) {
RepairPushArgsInEnvironment();
RepairArgumentUsesInEnvironment();
}
}
}

View file

@ -336,7 +336,7 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
__ leaq(array_reg, compiler::Address(array_reg, start_reg, scale, offset));
}
LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -352,11 +352,11 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
return locs;
}
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void MoveArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
const Location value = locs()->in(0);
const compiler::Address dst(RSP, top_of_stack_relative_index() * kWordSize);
const compiler::Address dst(RSP, sp_relative_index() * kWordSize);
if (value.IsRegister()) {
__ movq(dst, value.reg());
} else if (value.IsConstant()) {

View file

@ -197,14 +197,15 @@ class GraphInfoCollector : public ValueObject {
continue;
}
++instruction_count_;
// Count inputs of certain instructions as if separate PushArgument
// Count inputs of certain instructions as if separate MoveArgument
// instructions are used for inputs. This is done in order to
// preserve inlining behavior and avoid code size growth after
// PushArgument instructions are eliminated.
// MoveArgument insertion was moved to the end of the
// compilation pipeline.
if (current->IsAllocateObject()) {
instruction_count_ += current->InputCount();
} else if (current->ArgumentCount() > 0) {
ASSERT(!current->HasPushArguments());
ASSERT(!current->HasMoveArguments());
instruction_count_ += current->ArgumentCount();
}
if (current->IsInstanceCall() || current->IsStaticCall() ||
@ -465,7 +466,7 @@ class CallSites : public ValueObject {
}
// For instructions with arguments we don't expect push arguments to
// be inserted yet.
ASSERT(defn->ArgumentCount() == 0 || !defn->HasPushArguments());
ASSERT(defn->ArgumentCount() == 0 || !defn->HasMoveArguments());
}
};
@ -1730,7 +1731,7 @@ class CallSiteInliner : public ValueObject {
ReplaceParameterStubs(zone(), caller_graph_, call_data, NULL);
exit_collector->ReplaceCall(callee_function_entry);
ASSERT(!call_data->call->HasPushArguments());
ASSERT(!call_data->call->HasMoveArguments());
}
static intptr_t CountConstants(const GrowableArray<Value*>& arguments) {
@ -2411,7 +2412,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
}
}
ASSERT(!call_->HasPushArguments());
ASSERT(!call_->HasMoveArguments());
// Handle any non-inlined variants.
if (!non_inlined_variants_->is_empty()) {
@ -3628,7 +3629,7 @@ bool FlowGraphInliner::TryReplaceInstanceCallWithInline(
flow_graph->AddExactnessGuard(call, receiver_cid);
}
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
// Replace all uses of this definition with the result.
if (call->HasUses()) {
@ -3678,7 +3679,7 @@ bool FlowGraphInliner::TryReplaceStaticCallWithInline(
ASSERT((last != nullptr && result != nullptr) ||
(call->function().recognized_kind() ==
MethodRecognizer::kObjectConstructor));
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
// Replace all uses of this definition with the result.
if (call->HasUses()) {
ASSERT(result->HasSSATemp());

View file

@ -214,7 +214,7 @@ void SSALivenessAnalysis::ComputeInitialSets() {
// MaterializeObject instruction is not in the graph.
// Treat its inputs as part of the environment.
DeepLiveness(defn->AsMaterializeObject(), live_in);
} else if (!defn->IsPushArgument() && !defn->IsConstant()) {
} else if (!defn->IsMoveArgument() && !defn->IsConstant()) {
live_in->Add(defn->vreg(0));
if (defn->HasPairRepresentation()) {
live_in->Add(defn->vreg(1));
@ -1058,7 +1058,7 @@ void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
continue;
}
if (def->IsPushArgument()) {
if (def->IsMoveArgument()) {
// Frame size is unknown until after allocation.
locations[i] = Location::NoLocation();
continue;
@ -3293,19 +3293,19 @@ void FlowGraphAllocator::AllocateOutgoingArguments() {
for (auto block : flow_graph_.reverse_postorder()) {
for (auto instr : block->instructions()) {
if (auto push = instr->AsPushArgument()) {
if (auto move_arg = instr->AsMoveArgument()) {
Location loc;
const intptr_t spill_index =
(total_spill_slot_count - 1) - push->top_of_stack_relative_index();
(total_spill_slot_count - 1) - move_arg->sp_relative_index();
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariableIndex(
-spill_index);
push->locs()->set_out(0,
(push->representation() == kUnboxedDouble)
? Location::DoubleStackSlot(slot_index, FPREG)
: Location::StackSlot(slot_index, FPREG));
move_arg->locs()->set_out(
0, (move_arg->representation() == kUnboxedDouble)
? Location::DoubleStackSlot(slot_index, FPREG)
: Location::StackSlot(slot_index, FPREG));
}
}
}

View file

@ -4425,7 +4425,7 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) {
BlockEntryInstr* block = block_it.Current();
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
Instruction* current = it.Current();
ASSERT(!current->IsPushArgument());
ASSERT(!current->IsMoveArgument());
// TODO(alexmarkov): take control dependencies into account and
// eliminate dead branches/conditions.
if (!CanEliminateInstruction(current, block)) {
@ -4462,7 +4462,7 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) {
for (Environment::DeepIterator it(current->env()); !it.Done();
it.Advance()) {
Definition* input = it.CurrentValue()->definition();
ASSERT(!input->IsPushArgument());
ASSERT(!input->IsMoveArgument());
if (input->HasSSATemp() && !live.Contains(input->ssa_temp_index())) {
worklist.Add(input);
live.Add(input->ssa_temp_index());
@ -4488,8 +4488,8 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) {
if (!CanEliminateInstruction(current, block)) {
continue;
}
ASSERT(!current->IsPushArgument());
ASSERT((current->ArgumentCount() == 0) || !current->HasPushArguments());
ASSERT(!current->IsMoveArgument());
ASSERT((current->ArgumentCount() == 0) || !current->HasMoveArguments());
if (Definition* def = current->AsDefinition()) {
if (def->HasSSATemp() && live.Contains(def->ssa_temp_index())) {
continue;

View file

@ -249,9 +249,9 @@ static void TestAliasingViaRedefinition(
// v0 <- AllocateObject(class K)
// v1 <- LoadField(v0, K.field)
// v2 <- make_redefinition(v0)
// PushArgument(v1)
// MoveArgument(v1)
// #if make_it_escape
// PushArgument(v2)
// MoveArgument(v2)
// #endif
// v3 <- StaticCall(blackhole, v1, v2)
// v4 <- LoadField(v2, K.field)
@ -418,13 +418,13 @@ static void TestAliasingViaStore(
// #endif
// v1 <- LoadField(v0, K.field)
// v2 <- REDEFINITION(v5)
// PushArgument(v1)
// MoveArgument(v1)
// #if make_it_escape
// v6 <- LoadField(v2, K.field)
// PushArgument(v6)
// MoveArgument(v6)
// #elif make_host_escape
// StoreField(v2 . K.field = v0)
// PushArgument(v5)
// MoveArgument(v5)
// #endif
// v3 <- StaticCall(blackhole, v1, v6)
// v4 <- LoadField(v0, K.field)
@ -1213,7 +1213,7 @@ main() {
48: v335 <- Box(v15) T{_Double}
49: ParallelMove rdx <- rcx, rax <- rax
50: StoreIndexed(v17, v39, v335)
52: PushArgument(v17)
52: MoveArgument(v17)
54: v40 <- StaticCall:44( _interpolate@0150898<0> v17,
recognized_kind = StringBaseInterpolate) T{String?}
56: Return:48(v40)
@ -1256,7 +1256,7 @@ main() {
kMatchAndMoveStoreIndexed,
kMatchAndMoveBox,
kMatchAndMoveStoreIndexed,
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
{kMatchAndMoveStaticCall, &string_interpolate},
kMatchReturn,
}));
@ -1329,7 +1329,7 @@ main() {
28: StoreIndexed(v11, v28, v29, NoStoreBarrier)
29: ParallelMove rcx <- S-3
30: StoreIndexed(v11, v30, v9, NoStoreBarrier)
32: PushArgument(v11)
32: MoveArgument(v11)
34: v31 <- StaticCall:20( _interpolate@0150898<0> v11, recognized_kind = StringBaseInterpolate) T{String}
35: ParallelMove rax <- rax
36: Return:24(v31)
@ -1353,7 +1353,7 @@ main() {
kMatchAndMoveStoreIndexed,
kMatchAndMoveStoreIndexed,
kMatchAndMoveStoreIndexed,
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
kMatchAndMoveStaticCall,
kMatchReturn,
}));

View file

@ -1288,7 +1288,7 @@ CompileType ParameterInstr::ComputeType() const {
return CompileType::Dynamic();
}
CompileType PushArgumentInstr::ComputeType() const {
CompileType MoveArgumentInstr::ComputeType() const {
return CompileType::Dynamic();
}

View file

@ -564,12 +564,12 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_NonNullableLoadStaticField) {
RELEASE_ASSERT(cursor.TryMatch({
kMoveGlob,
{kMatchAndMoveLoadStaticField, &load},
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
kMatchAndMoveStaticCall,
kMatchAndMoveUnboxInt64,
kMatchAndMoveBinaryInt64Op,
kMatchAndMoveBoxInt64,
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
kMatchAndMoveStaticCall,
kMatchReturn,
}));
@ -736,10 +736,10 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_RecordFieldAccess) {
{kMatchAndMoveLoadField, &load1},
kMatchAndMoveCheckSmi,
kMatchAndMoveBinarySmiOp,
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
kMatchAndMoveStaticCall,
{kMatchAndMoveLoadField, &load2},
kMatchAndMovePushArgument,
kMatchAndMoveMoveArgument,
kMatchAndMoveStaticCall,
kMatchReturn,
}));

View file

@ -207,7 +207,7 @@ void CallSpecializer::SpecializePolymorphicInstanceCall(
void CallSpecializer::ReplaceCallWithResult(Definition* call,
Instruction* replacement,
Definition* result) {
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
if (result == nullptr) {
ASSERT(replacement->IsDefinition());
call->ReplaceWith(replacement->AsDefinition(), current_iterator());
@ -1268,7 +1268,7 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
// One result only.
AddReceiverCheck(call);
ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
ASSERT(!call->HasPushArguments());
ASSERT(!call->HasMoveArguments());
call->ReplaceUsesWith(bool_const);
ASSERT(current_iterator()->Current() == call);
current_iterator()->RemoveCurrentFromGraph();

View file

@ -546,7 +546,7 @@ COMPILER_PASS(AllocationSinking_DetachMaterializations, {
});
COMPILER_PASS(AllocateRegisters, {
flow_graph->InsertPushArguments();
flow_graph->InsertMoveArguments();
// Ensure loop hierarchy has been computed.
flow_graph->GetLoopHierarchy();
// Perform register allocation on the SSA graph.

View file

@ -1087,8 +1087,7 @@ Fragment BaseFlowGraphBuilder::DebugStepCheck(TokenPosition position) {
Fragment BaseFlowGraphBuilder::CheckNull(TokenPosition position,
LocalVariable* receiver,
const String& function_name,
bool clear_the_temp /* = true */) {
const String& function_name) {
Fragment instructions = LoadLocal(receiver);
CheckNullInstr* check_null = new (Z) CheckNullInstr(
@ -1099,14 +1098,6 @@ Fragment BaseFlowGraphBuilder::CheckNull(TokenPosition position,
// Does not use the redefinition, no `Push(check_null)`.
instructions <<= check_null;
if (clear_the_temp) {
// Null out receiver to make sure it is not saved into the frame before
// doing the call.
instructions += NullConstant();
instructions += StoreLocal(TokenPosition::kNoSource, receiver);
instructions += Drop();
}
return instructions;
}

View file

@ -385,13 +385,11 @@ class BaseFlowGraphBuilder {
// Loads 'receiver' and checks it for null. Throws NoSuchMethod if it is null.
// 'function_name' is a selector which is being called (reported in
// NoSuchMethod message).
// Sets 'receiver' to 'null' after the check if 'clear_the_temp'.
// Note that this does _not_ use the result of the CheckNullInstr, so it does
// not create a data dependency and might break with code motion.
Fragment CheckNull(TokenPosition position,
LocalVariable* receiver,
const String& function_name,
bool clear_the_temp = true);
const String& function_name);
// Pops the top of the stack, checks it for null, and pushes the result on
// the stack to create a data dependency.
@ -423,7 +421,7 @@ class BaseFlowGraphBuilder {
// Builds closure call with given number of arguments. Target closure
// (in bare instructions mode) or closure function (otherwise) is taken from
// top of the stack.
// PushArgument instructions should be already added for arguments.
// MoveArgument instructions should be already added for arguments.
Fragment ClosureCall(TokenPosition position,
intptr_t type_args_len,
intptr_t argument_count,

View file

@ -1522,13 +1522,10 @@ Fragment StreamingFlowGraphBuilder::RedefinitionWithType(
return flow_graph_builder_->RedefinitionWithType(type);
}
Fragment StreamingFlowGraphBuilder::CheckNull(
TokenPosition position,
LocalVariable* receiver,
const String& function_name,
bool clear_the_temp /* = true */) {
return flow_graph_builder_->CheckNull(position, receiver, function_name,
clear_the_temp);
Fragment StreamingFlowGraphBuilder::CheckNull(TokenPosition position,
LocalVariable* receiver,
const String& function_name) {
return flow_graph_builder_->CheckNull(position, receiver, function_name);
}
Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
@ -2171,14 +2168,6 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition* p) {
inferred_type_metadata_helper_.GetInferredType(offset);
Fragment instructions = BuildExpression(); // read receiver.
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
const String& getter_name = ReadNameAsGetterName(); // read name.
SkipDartType(); // read result_type.
const NameIndex itarget_name =
@ -2189,6 +2178,7 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition* p) {
ASSERT(getter_name.ptr() == interface_target.name());
if (direct_call.check_receiver_for_null_) {
auto receiver = MakeTemporary();
instructions += CheckNull(position, receiver, getter_name);
}
@ -2206,10 +2196,6 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition* p) {
Function::null_function(), &result_type);
}
if (direct_call.check_receiver_for_null_) {
instructions += DropTempsPreserveTop(1); // Drop receiver, preserve result.
}
return instructions;
}
@ -2225,20 +2211,7 @@ Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition* p) {
inferred_type_metadata_helper_.GetInferredType(offset);
Fragment instructions = BuildExpression(); // read receiver.
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
const String& getter_name = ReadNameAsGetterName(); // read name.
if (direct_call.check_receiver_for_null_) {
instructions += CheckNull(position, receiver, getter_name);
}
const auto& mangled_name = String::ZoneHandle(
Z, Function::CreateDynamicInvocationForwarderName(getter_name));
const Function* direct_call_target = &direct_call.target_;
@ -2247,6 +2220,11 @@ Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition* p) {
direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
}
if (direct_call.check_receiver_for_null_) {
auto receiver = MakeTemporary();
instructions += CheckNull(position, receiver, getter_name);
}
if (!direct_call_target->IsNull()) {
ASSERT(CompilerState::Current().is_aot());
instructions +=
@ -2261,10 +2239,6 @@ Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition* p) {
Function::null_function(), &result_type);
}
if (direct_call.check_receiver_for_null_) {
instructions += DropTempsPreserveTop(1); // Drop receiver, preserve result.
}
return instructions;
}
@ -2280,14 +2254,6 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition* p) {
inferred_type_metadata_helper_.GetInferredType(offset);
Fragment instructions = BuildExpression(); // read receiver.
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
const String& getter_name = ReadNameAsGetterName(); // read name.
SkipDartType(); // read result_type.
const NameIndex itarget_name =
@ -2297,6 +2263,7 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition* p) {
Z, H.LookupMethodByMember(itarget_name, H.DartMethodName(itarget_name)));
if (direct_call.check_receiver_for_null_) {
const auto receiver = MakeTemporary();
instructions += CheckNull(position, receiver, getter_name);
}
@ -2314,10 +2281,6 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition* p) {
tearoff_interface_target, &result_type);
}
if (direct_call.check_receiver_for_null_) {
instructions += DropTempsPreserveTop(1); // Drop receiver, preserve result.
}
return instructions;
}
@ -2333,14 +2296,8 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionTearOff(TokenPosition* p) {
Fragment instructions = BuildExpression(); // read receiver.
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
if (direct_call.check_receiver_for_null_) {
const auto receiver = MakeTemporary();
instructions += CheckNull(position, receiver, Symbols::GetCall());
}
@ -2358,10 +2315,6 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionTearOff(TokenPosition* p) {
Function::null_function(), &result_type);
}
if (direct_call.check_receiver_for_null_) {
instructions += DropTempsPreserveTop(1); // Drop receiver, preserve result.
}
return instructions;
}
@ -2399,9 +2352,7 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceSet(TokenPosition* p) {
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
const String& setter_name = ReadNameAsSetterName(); // read name.
@ -2442,10 +2393,6 @@ Fragment StreamingFlowGraphBuilder::BuildInstanceSet(TokenPosition* p) {
instructions += Drop(); // Drop result of the setter invocation.
if (direct_call.check_receiver_for_null_) {
instructions += Drop(); // Drop receiver.
}
return instructions;
}
@ -2471,9 +2418,7 @@ Fragment StreamingFlowGraphBuilder::BuildDynamicSet(TokenPosition* p) {
LocalVariable* receiver = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver = MakeTemporary();
instructions += LoadLocal(receiver);
}
const String& setter_name = ReadNameAsSetterName(); // read name.
@ -2514,10 +2459,6 @@ Fragment StreamingFlowGraphBuilder::BuildDynamicSet(TokenPosition* p) {
instructions += Drop(); // Drop result of the setter invocation.
if (direct_call.check_receiver_for_null_) {
instructions += Drop(); // Drop receiver.
}
return instructions;
}
@ -2929,17 +2870,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p,
LocalVariable* receiver_temp = nullptr;
if (direct_call.check_receiver_for_null_) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver_temp = MakeTemporary();
if (type_arguments_temp != nullptr) {
// If call has type arguments then push them before pushing the receiver.
// The stack will contain:
//
// [type_arguments_temp][receiver_temp][type_arguments][receiver] ...
//
instructions += LoadLocal(type_arguments_temp);
}
instructions += LoadLocal(receiver_temp);
}
intptr_t argument_count;
@ -2978,8 +2909,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p,
}
if (direct_call.check_receiver_for_null_) {
instructions += CheckNull(position, receiver_temp, name,
/*clear_temp=*/true);
instructions += CheckNull(position, receiver_temp, name);
}
const String* mangled_name = &name;
@ -3016,14 +2946,6 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p,
result_type.ReceiverNotInt(), is_call_on_this);
}
// Drop temporaries preserving result on the top of the stack.
ASSERT((receiver_temp != nullptr) || (type_arguments_temp == nullptr));
if (receiver_temp != nullptr) {
const intptr_t num_temps = (receiver_temp != nullptr ? 1 : 0) +
(type_arguments_temp != nullptr ? 1 : 0);
instructions += DropTempsPreserveTop(num_temps);
}
// Later optimization passes assume that result of a x.[]=(...) call is not
// used. We must guarantee this invariant because violation will lead to an
// illegal IL once we replace x.[]=(...) with a sequence that does not
@ -3137,8 +3059,7 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionInvocation(TokenPosition* p) {
SkipDartType(); // read function_type.
if (is_unchecked_closure_call) {
instructions += CheckNull(position, receiver_temp, Symbols::call(),
/*clear_temp=*/false);
instructions += CheckNull(position, receiver_temp, Symbols::call());
// Lookup the function in the closure.
instructions += LoadLocal(receiver_temp);
if (!FLAG_precompiled_mode) {
@ -3563,8 +3484,7 @@ Fragment StreamingFlowGraphBuilder::BuildNullCheck(TokenPosition* p) {
TokenPosition operand_position = TokenPosition::kNoSource;
Fragment instructions = BuildExpression(&operand_position);
LocalVariable* expr_temp = MakeTemporary();
instructions += CheckNull(position, expr_temp, String::null_string(),
/* clear_the_temp = */ false);
instructions += CheckNull(position, expr_temp, String::null_string());
return instructions;
}

View file

@ -164,8 +164,7 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
Fragment RedefinitionWithType(const AbstractType& type);
Fragment CheckNull(TokenPosition position,
LocalVariable* receiver,
const String& function_name,
bool clear_the_temp = true);
const String& function_name);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,

View file

@ -46,7 +46,7 @@ namespace dart {
V(ParallelMove, -3) \
V(TempMove, -4) \
V(Constant, -5) \
V(PushArgument, -6) \
V(MoveArgument, -6) \
V(ControlFlow, -7) \
V(Context, -8) \
V(MethodExtractor, -9) \