[vm/compiler] Let Parameter carry its location

Previously we would specify parameter offset and base register and
use SpecialParameter instruction to represent values passed in
registers.

This CL simplifies and merges these concepts: now every Parameter
instruction simply carries around its Location.

This CL also tweaks printing of stack slot locations so that they
are easier to read: `S+1` becomes `fp[1]` or `sp[1]` depending on the
base register, DS+1 becomes `dword fp[1]` / `dword sp[1]` and `QS+1`
expands to `qword fp[1]`/`qword sp[1]`.

Additionally we clean `BlockBuilder` API a bit - instead of
passing `with_frame` to `AddParameter` we make this the
property of the builder itself, set at construction time.

Issue https://github.com/dart-lang/sdk/issues/54955
Closes https://github.com/dart-lang/sdk/issues/31956

TEST=ci

Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-release-arm64-try,vm-aot-linux-release-simarm_x64-try,vm-ffi-qemu-linux-release-arm-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-linux-product-x64-try,vm-aot-mac-release-x64-try
Change-Id: Ie24dc6b6c47b3a45db722813218bc53c3a06c91d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353081
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
Vyacheslav Egorov 2024-02-20 23:54:08 +00:00 committed by Commit Queue
parent ac39be3eed
commit 9fe6571a75
22 changed files with 304 additions and 432 deletions

View file

@ -191,8 +191,8 @@ void matchIL$testUnboxedRecordInTryCatch(FlowGraph graph) {
]),
'B2' <<
match.block('CatchBlock', [
'e' << match.SpecialParameter(),
'st' << match.SpecialParameter(),
'e' << match.Parameter(index: 2),
'st' << match.Parameter(index: 3),
match.MoveArgument('e'),
match.StaticCall(),
match.Goto('B3'),

View file

@ -18,13 +18,16 @@ namespace compiler {
// Helper class for building basic blocks in SSA form.
class BlockBuilder : public ValueObject {
public:
BlockBuilder(FlowGraph* flow_graph, BlockEntryInstr* entry)
BlockBuilder(FlowGraph* flow_graph,
BlockEntryInstr* entry,
bool with_frame = true)
: flow_graph_(flow_graph),
source_(InstructionSource(flow_graph_->function().token_pos(),
flow_graph->inlining_id())),
entry_(entry),
current_(entry),
dummy_env_(new Environment(0, 0, 0, flow_graph->function(), nullptr)) {
dummy_env_(new Environment(0, 0, 0, flow_graph->function(), nullptr)),
with_frame_(with_frame) {
// Some graph transformations use environments from block entries.
entry->SetEnvironment(dummy_env_);
}
@ -69,22 +72,23 @@ class BlockBuilder : public ValueObject {
return instr;
}
Definition* AddParameter(intptr_t index, bool with_frame) {
Definition* AddParameter(intptr_t index) {
const auto& function = flow_graph_->function();
const intptr_t param_offset = FlowGraph::ParameterOffsetAt(function, index);
const auto loc = FlowGraph::ParameterLocationAt(function, index);
const auto representation =
FlowGraph::ParameterRepresentationAt(function, index);
return AddParameter(index, param_offset, with_frame, representation);
return AddParameter(index, representation,
with_frame_ ? loc : loc.ToEntrySpRelative());
}
Definition* AddParameter(intptr_t index,
intptr_t param_offset,
bool with_frame,
Representation representation) {
Representation representation,
Location location = Location()) {
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
return AddToInitialDefinitions(new ParameterInstr(
/*env_index=*/index, /*param_index=*/index, param_offset, normal_entry,
representation, with_frame ? FPREG : SPREG));
return AddToInitialDefinitions(
new ParameterInstr(normal_entry,
/*env_index=*/index,
/*param_index=*/index, location, representation));
}
TokenPosition TokenPos() const { return source_.token_pos; }
@ -162,6 +166,7 @@ class BlockBuilder : public ValueObject {
BlockEntryInstr* entry_;
Instruction* current_;
Environment* dummy_env_;
const bool with_frame_;
};
} // namespace compiler

View file

@ -476,10 +476,6 @@ void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
}
}
void ConstantPropagator::VisitSpecialParameter(SpecialParameterInstr* instr) {
SetValue(instr, non_constant_);
}
void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) {
SetValue(instr, non_constant_);
}

View file

@ -150,8 +150,7 @@ static void ConstantPropagatorUnboxedOpTest(
{
BlockBuilder builder(H.flow_graph(), b1);
auto v0 = builder.AddParameter(/*index=*/0, /*param_offset=*/0,
/*with_frame=*/true, kTagged);
auto v0 = builder.AddParameter(/*index=*/0, kTagged);
builder.AddBranch(
new StrictCompareInstr(
InstructionSource(), Token::kEQ_STRICT, new Value(H.IntConstant(1)),

View file

@ -72,6 +72,46 @@ void FlowGraph::EnsureSSATempIndex(Definition* defn, Definition* replacement) {
}
}
// When updating this check also [ParameterOffsetAt] and
// [PopulateEnvironmentFromFunctionEntry]
Location FlowGraph::ParameterLocationAt(const Function& function,
intptr_t index) {
ASSERT(index <= function.NumParameters());
intptr_t offset_in_words_from_caller_sp = 0;
for (intptr_t i = function.NumParameters() - 1; i > index; i--) {
if (function.is_unboxed_integer_parameter_at(i)) {
offset_in_words_from_caller_sp += compiler::target::kIntSpillFactor;
} else if (function.is_unboxed_double_parameter_at(i)) {
offset_in_words_from_caller_sp += compiler::target::kDoubleSpillFactor;
} else {
ASSERT(!function.is_unboxed_parameter_at(i));
// Boxed parameters occupy one word.
offset_in_words_from_caller_sp++;
}
}
const auto offset_in_words_from_fp =
offset_in_words_from_caller_sp +
compiler::target::frame_layout.param_end_from_fp + 1;
if (function.is_unboxed_double_parameter_at(index)) {
return Location::DoubleStackSlot(offset_in_words_from_fp, FPREG);
} else if (function.is_unboxed_integer_parameter_at(index)) {
if (compiler::target::kIntSpillFactor == 1) {
return Location::StackSlot(offset_in_words_from_fp, FPREG);
} else {
ASSERT(compiler::target::kIntSpillFactor == 2);
return Location::Pair(
Location::StackSlot(offset_in_words_from_fp, FPREG),
Location::StackSlot(offset_in_words_from_fp + 1, FPREG));
}
} else {
return Location::StackSlot(offset_in_words_from_fp, FPREG);
}
}
// When updating this check also [ParameterLocationAt] and
// [PopulateEnvironmentFromFunctionEntry]
intptr_t FlowGraph::ParameterOffsetAt(const Function& function,
intptr_t index,
bool last_slot /*=true*/) {
@ -84,7 +124,7 @@ intptr_t FlowGraph::ParameterOffsetAt(const Function& function,
param_offset += compiler::target::kDoubleSpillFactor;
} else {
ASSERT(!function.is_unboxed_parameter_at(i));
// Unboxed parameters always occupy one word
// Boxed parameters occupy one word.
param_offset++;
}
}
@ -1203,6 +1243,8 @@ void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
#endif // defined(DEBUG)
}
// When updating this check also [ParameterLocationAt] and
// [ParameterOffsetAt].
void FlowGraph::PopulateEnvironmentFromFunctionEntry(
FunctionEntryInstr* function_entry,
GrowableArray<Definition*>* env,
@ -1218,32 +1260,44 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
ASSERT(variable_count() == env->length());
ASSERT(direct_parameter_count <= env->length());
intptr_t param_offset = 0;
intptr_t offset_in_words_from_fp =
(compiler::target::frame_layout.param_end_from_fp + 1) +
direct_parameters_size_;
for (intptr_t i = 0; i < direct_parameter_count; i++) {
ASSERT(FLAG_precompiled_mode || !function().is_unboxed_parameter_at(i));
ParameterInstr* param;
const intptr_t index = (function().IsFactory() ? (i - 1) : i);
Representation rep;
Location location;
if (index >= 0 && function().is_unboxed_integer_parameter_at(index)) {
constexpr intptr_t kCorrection = compiler::target::kIntSpillFactor - 1;
param = new (zone()) ParameterInstr(/*env_index=*/i, /*param_index=*/i,
param_offset + kCorrection,
function_entry, kUnboxedInt64);
param_offset += compiler::target::kIntSpillFactor;
rep = kUnboxedInt64;
offset_in_words_from_fp -= compiler::target::kIntSpillFactor;
if (compiler::target::kIntSpillFactor == 1) {
location = Location::StackSlot(offset_in_words_from_fp, FPREG);
} else {
ASSERT(compiler::target::kIntSpillFactor == 2);
location = Location::Pair(
Location::StackSlot(offset_in_words_from_fp, FPREG),
Location::StackSlot(offset_in_words_from_fp + 1, FPREG));
}
} else if (index >= 0 && function().is_unboxed_double_parameter_at(index)) {
constexpr intptr_t kCorrection = compiler::target::kDoubleSpillFactor - 1;
param = new (zone()) ParameterInstr(/*env_index=*/i, /*param_index=*/i,
param_offset + kCorrection,
function_entry, kUnboxedDouble);
param_offset += compiler::target::kDoubleSpillFactor;
rep = kUnboxedDouble;
offset_in_words_from_fp -= compiler::target::kDoubleSpillFactor;
location = Location::DoubleStackSlot(offset_in_words_from_fp, FPREG);
} else {
ASSERT(index < 0 || !function().is_unboxed_parameter_at(index));
param =
new (zone()) ParameterInstr(/*env_index=*/i, /*param_index=*/i,
param_offset, function_entry, kTagged);
param_offset++;
rep = kTagged;
offset_in_words_from_fp -= 1;
location = Location::StackSlot(offset_in_words_from_fp, FPREG);
}
auto param = new (zone()) ParameterInstr(function_entry,
/*env_index=*/i,
/*param_index=*/i, location, rep);
AllocateSSAIndex(param);
AddToInitialDefinitions(function_entry, param);
(*env)[i] = param;
@ -1296,9 +1350,10 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
// Replace the argument descriptor slot with a special parameter.
if (parsed_function().has_arg_desc_var()) {
Definition* defn =
new (Z) SpecialParameterInstr(SpecialParameterInstr::kArgDescriptor,
DeoptId::kNone, function_entry);
auto defn = new (Z)
ParameterInstr(function_entry, ArgumentDescriptorEnvIndex(),
ParameterInstr::kNotFunctionParameter,
Location::RegisterLocation(ARGS_DESC_REG), kTagged);
AllocateSSAIndex(defn);
AddToInitialDefinitions(function_entry, defn);
(*env)[ArgumentDescriptorEnvIndex()] = defn;
@ -1306,6 +1361,14 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
}
}
static Location EnvIndexToStackLocation(intptr_t num_direct_parameters,
intptr_t env_index) {
return Location::StackSlot(
compiler::target::frame_layout.FrameSlotForVariableIndex(
num_direct_parameters - env_index),
FPREG);
}
void FlowGraph::PopulateEnvironmentFromOsrEntry(
OsrEntryInstr* osr_entry,
GrowableArray<Definition*>* env) {
@ -1319,8 +1382,9 @@ void FlowGraph::PopulateEnvironmentFromOsrEntry(
const intptr_t param_index = (i < num_direct_parameters())
? i
: ParameterInstr::kNotFunctionParameter;
ParameterInstr* param = new (zone())
ParameterInstr(/*env_index=*/i, param_index, i, osr_entry, kTagged);
ParameterInstr* param = new (zone()) ParameterInstr(
osr_entry, /*env_index=*/i, param_index,
EnvIndexToStackLocation(num_direct_parameters(), i), kTagged);
AllocateSSAIndex(param);
AddToInitialDefinitions(osr_entry, param);
(*env)[i] = param;
@ -1342,21 +1406,19 @@ void FlowGraph::PopulateEnvironmentFromCatchEntry(
// Add real definitions for all locals and parameters.
ASSERT(variable_count() == env->length());
for (intptr_t i = 0, n = variable_count(); i < n; ++i) {
// Replace usages of the raw exception/stacktrace variables with
// [SpecialParameterInstr]s.
Definition* param = nullptr;
// Local variables will arive on the stack while exception and
// stack trace will be passed in fixed registers.
Location loc;
if (raw_exception_var_envindex == i) {
param = new (Z) SpecialParameterInstr(SpecialParameterInstr::kException,
DeoptId::kNone, catch_entry);
loc = LocationExceptionLocation();
} else if (raw_stacktrace_var_envindex == i) {
param = new (Z) SpecialParameterInstr(SpecialParameterInstr::kStackTrace,
DeoptId::kNone, catch_entry);
loc = LocationStackTraceLocation();
} else {
param = new (Z)
ParameterInstr(/*env_index=*/i,
/*param_index=*/ParameterInstr::kNotFunctionParameter,
i, catch_entry, kTagged);
loc = EnvIndexToStackLocation(num_direct_parameters(), i);
}
auto param = new (Z) ParameterInstr(
catch_entry, /*env_index=*/i,
/*param_index=*/ParameterInstr::kNotFunctionParameter, loc, kTagged);
AllocateSSAIndex(param); // New SSA temp.
(*env)[i] = param;

View file

@ -151,6 +151,7 @@ class FlowGraph : public ZoneAllocated {
static intptr_t ParameterOffsetAt(const Function& function,
intptr_t index,
bool last_slot = true);
static Location ParameterLocationAt(const Function& function, intptr_t index);
static Representation ParameterRepresentationAt(const Function& function,
intptr_t index);

View file

@ -181,9 +181,7 @@ void FlowGraphChecker::VisitInstructions(BlockEntryInstr* block) {
if (auto entry = block->AsBlockEntryWithInitialDefs()) {
for (auto def : *entry->initial_definitions()) {
ASSERT(def != nullptr);
ASSERT1(
def->IsConstant() || def->IsParameter() || def->IsSpecialParameter(),
def);
ASSERT1(def->IsConstant() || def->IsParameter(), def);
// Make sure block lookup agrees.
ASSERT1(def->GetBlock() == entry, def);
// Initial definitions are partially linked into graph.
@ -360,8 +358,7 @@ void FlowGraphChecker::VisitUseDef(Instruction* instruction,
// Phis are never linked into graph.
ASSERT1(def->next() == nullptr, def);
ASSERT1(def->previous() == nullptr, def);
} else if (def->IsConstant() || def->IsParameter() ||
def->IsSpecialParameter()) {
} else if (def->IsConstant() || def->IsParameter()) {
// Initial definitions are partially linked into graph, but some
// constants are fully linked into graph (so no next() assert).
ASSERT1(def->previous() != nullptr, def);

View file

@ -38,7 +38,7 @@ ISOLATE_UNIT_TEST_CASE(FlowGraph_UnboxInt64Phi) {
{
BlockBuilder builder(H.flow_graph(), normal_entry);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
builder.AddInstruction(new GotoInstr(loop_header, S.GetNextDeoptId()));
}

View file

@ -4917,42 +4917,6 @@ void MaterializeObjectInstr::RemapRegisters(intptr_t* cpu_reg_slots,
}
}
const char* SpecialParameterInstr::KindToCString(SpecialParameterKind k) {
switch (k) {
#define KIND_CASE(Name) \
case SpecialParameterKind::k##Name: \
return #Name;
FOR_EACH_SPECIAL_PARAMETER_KIND(KIND_CASE)
#undef KIND_CASE
}
return nullptr;
}
bool SpecialParameterInstr::ParseKind(const char* str,
SpecialParameterKind* out) {
ASSERT(str != nullptr && out != nullptr);
#define KIND_CASE(Name) \
if (strcmp(str, #Name) == 0) { \
*out = SpecialParameterKind::k##Name; \
return true; \
}
FOR_EACH_SPECIAL_PARAMETER_KIND(KIND_CASE)
#undef KIND_CASE
return false;
}
LocationSummary* SpecialParameterInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
// Only appears in initial definitions, never in normal code.
UNREACHABLE();
return nullptr;
}
void SpecialParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Only appears in initial definitions, never in normal code.
UNREACHABLE();
}
LocationSummary* MakeTempInstr::MakeLocationSummary(Zone* zone,
bool optimizing) const {
ASSERT(!optimizing);

View file

@ -433,7 +433,6 @@ struct InstrAttrs {
M(AssertAssignable, _) \
M(AssertSubtype, _) \
M(AssertBoolean, _) \
M(SpecialParameter, kNoGC) \
M(ClosureCall, _) \
M(FfiCall, _) \
M(CCall, kNoGC) \
@ -2867,27 +2866,32 @@ class PhiInstr : public VariadicDefinition {
// This instruction represents an incoming parameter for a function entry,
// or incoming value for OSR entry or incoming value for a catch entry.
//
// [env_index] is a position of the parameter in the flow graph environment.
// [param_index] is a position of the function parameter, or -1 if
// this instruction doesn't correspond to a real function parameter.
//
// [param_index] is a position of the function parameter, or
// kNotFunctionParameter if this instruction doesn't correspond to a real
// function parameter.
//
// [loc] specifies where where the incomming value is located on entry to
// the block. Note: for compound values (e.g. unboxed integers on 32-bit
// values) this will be a Pair location.
class ParameterInstr : public TemplateDefinition<0, NoThrow> {
public:
// [param_index] when ParameterInstr doesn't correspond to
// a function parameter.
static constexpr intptr_t kNotFunctionParameter = -1;
ParameterInstr(intptr_t env_index,
ParameterInstr(BlockEntryInstr* block,
intptr_t env_index,
intptr_t param_index,
intptr_t param_offset,
BlockEntryInstr* block,
Representation representation,
Register base_reg = FPREG)
const Location& loc,
Representation representation)
: env_index_(env_index),
param_index_(param_index),
param_offset_(param_offset),
base_reg_(base_reg),
representation_(representation),
block_(block) {}
block_(block),
location_(loc) {}
DECLARE_INSTRUCTION(Parameter)
DECLARE_ATTRIBUTE(index())
@ -2900,8 +2904,7 @@ class ParameterInstr : public TemplateDefinition<0, NoThrow> {
// (between 0 and function.NumParameters()), or -1.
intptr_t param_index() const { return param_index_; }
intptr_t param_offset() const { return param_offset_; }
Register base_reg() const { return base_reg_; }
const Location& location() const { return location_; }
// Get the block entry for that instruction.
virtual BlockEntryInstr* GetBlock() { return block_; }
@ -2930,21 +2933,17 @@ class ParameterInstr : public TemplateDefinition<0, NoThrow> {
#define FIELD_LIST(F) \
F(const intptr_t, env_index_) \
F(const intptr_t, param_index_) \
/* The offset (in words) of the last slot of the parameter, relative */ \
/* to the first parameter. */ \
/* It is used in the FlowGraphAllocator when it sets the assigned */ \
/* location and spill slot for the parameter definition. */ \
F(const intptr_t, param_offset_) \
F(const Register, base_reg_) \
F(const Representation, representation_)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ParameterInstr,
TemplateDefinition,
FIELD_LIST)
DECLARE_EXTRA_SERIALIZATION
#undef FIELD_LIST
private:
BlockEntryInstr* block_ = nullptr;
Location location_;
DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
};
@ -4436,68 +4435,6 @@ class AssertBooleanInstr : public TemplateDefinition<1, Throws, Pure> {
DISALLOW_COPY_AND_ASSIGN(AssertBooleanInstr);
};
// Denotes a special parameter, currently either the context of a closure,
// the type arguments of a generic function or an arguments descriptor.
class SpecialParameterInstr : public TemplateDefinition<0, NoThrow> {
public:
#define FOR_EACH_SPECIAL_PARAMETER_KIND(M) \
M(Context) \
M(TypeArgs) \
M(ArgDescriptor) \
M(Exception) \
M(StackTrace)
#define KIND_DECL(name) k##name,
enum SpecialParameterKind { FOR_EACH_SPECIAL_PARAMETER_KIND(KIND_DECL) };
#undef KIND_DECL
// Defined as a static intptr_t instead of inside the enum since some
// switch statements depend on the exhaustibility checking.
#define KIND_INC(name) +1
static constexpr intptr_t kNumKinds =
0 FOR_EACH_SPECIAL_PARAMETER_KIND(KIND_INC);
#undef KIND_INC
static const char* KindToCString(SpecialParameterKind k);
static bool ParseKind(const char* str, SpecialParameterKind* out);
SpecialParameterInstr(SpecialParameterKind kind,
intptr_t deopt_id,
BlockEntryInstr* block)
: TemplateDefinition(deopt_id), kind_(kind), block_(block) {}
DECLARE_INSTRUCTION(SpecialParameter)
virtual BlockEntryInstr* GetBlock() { return block_; }
virtual CompileType ComputeType() const;
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool HasUnknownSideEffects() const { return false; }
virtual bool AttributesEqual(const Instruction& other) const {
return kind() == other.AsSpecialParameter()->kind();
}
SpecialParameterKind kind() const { return kind_; }
const char* ToCString() const;
PRINT_OPERANDS_TO_SUPPORT
#define FIELD_LIST(F) F(const SpecialParameterKind, kind_)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(SpecialParameterInstr,
TemplateDefinition,
FIELD_LIST)
#undef FIELD_LIST
DECLARE_EXTRA_SERIALIZATION
private:
BlockEntryInstr* block_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(SpecialParameterInstr);
};
struct ArgumentsInfo {
ArgumentsInfo(intptr_t type_args_len,
intptr_t count_with_type_args,

View file

@ -1321,18 +1321,7 @@ void BitCastInstr::PrintOperandsTo(BaseTextBuffer* f) const {
}
void ParameterInstr::PrintOperandsTo(BaseTextBuffer* f) const {
f->Printf("%" Pd, env_index());
}
void SpecialParameterInstr::PrintOperandsTo(BaseTextBuffer* f) const {
f->Printf("%s", KindToCString(kind()));
}
const char* SpecialParameterInstr::ToCString() const {
char buffer[1024];
BufferFormatter bf(buffer, 1024);
PrintTo(&bf);
return Thread::Current()->zone()->MakeCopyOfString(buffer);
f->Printf("%" Pd " @%s", env_index(), location().ToCString());
}
void CheckStackOverflowInstr::PrintOperandsTo(BaseTextBuffer* f) const {

View file

@ -2171,6 +2171,16 @@ void ParallelMoveInstr::ReadExtra(FlowGraphDeserializer* d) {
move_schedule_ = d->Read<const MoveSchedule*>();
}
void ParameterInstr::WriteExtra(FlowGraphSerializer* s) {
TemplateDefinition::WriteExtra(s);
location_.Write(s);
}
void ParameterInstr::ReadExtra(FlowGraphDeserializer* d) {
TemplateDefinition::ReadExtra(d);
location_ = Location::Read(d);
}
void PhiInstr::WriteTo(FlowGraphSerializer* s) {
VariadicDefinition::WriteTo(s);
s->Write<Representation>(representation_);
@ -2409,16 +2419,6 @@ FlowGraphDeserializer::ReadTrait<const compiler::TableSelector*>::Read(
#endif
}
void SpecialParameterInstr::WriteExtra(FlowGraphSerializer* s) {
TemplateDefinition::WriteExtra(s);
s->WriteRef<BlockEntryInstr*>(block_);
}
void SpecialParameterInstr::ReadExtra(FlowGraphDeserializer* d) {
TemplateDefinition::ReadExtra(d);
block_ = d->ReadRef<BlockEntryInstr*>();
}
template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::WriteExtra(FlowGraphSerializer* s) {
VariadicDefinition::WriteExtra(s);

View file

@ -23,11 +23,6 @@ ISOLATE_UNIT_TEST_CASE(InstructionTests) {
new TargetEntryInstr(1, kInvalidTryIndex, DeoptId::kNone);
EXPECT(target_instr->IsBlockEntry());
EXPECT(!target_instr->IsDefinition());
SpecialParameterInstr* context = new SpecialParameterInstr(
SpecialParameterInstr::kContext, DeoptId::kNone, target_instr);
EXPECT(context->IsDefinition());
EXPECT(!context->IsBlockEntry());
EXPECT(context->GetBlock() == target_instr);
}
ISOLATE_UNIT_TEST_CASE(OptimizationTests) {
@ -218,7 +213,7 @@ bool TestIntConverterCanonicalizationRule(Thread* thread,
{
BlockBuilder builder(H.flow_graph(), normal_entry);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, initial);
v0 = builder.AddParameter(0, initial);
v0->set_range(Range(RangeBoundary::FromConstant(min_value),
RangeBoundary::FromConstant(max_value)));
auto conv1 = builder.AddDefinition(new IntConverterInstr(
@ -290,7 +285,7 @@ ISOLATE_UNIT_TEST_CASE(IL_PhiCanonicalization) {
{
BlockBuilder builder(H.flow_graph(), normal_entry);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
builder.AddInstruction(new GotoInstr(b2, S.GetNextDeoptId()));
}
@ -343,10 +338,8 @@ ISOLATE_UNIT_TEST_CASE(IL_UnboxIntegerCanonicalization) {
Definition* int_type =
H.flow_graph()->GetConstant(Type::Handle(Type::IntType()));
Definition* float64_array =
builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
Definition* int64_array =
builder.AddParameter(1, 1, /*with_frame=*/true, kTagged);
Definition* float64_array = builder.AddParameter(0, kTagged);
Definition* int64_array = builder.AddParameter(1, kTagged);
Definition* load_indexed = builder.AddDefinition(new LoadIndexedInstr(
new Value(float64_array), new Value(index),
@ -416,10 +409,8 @@ static void TestNullAwareEqualityCompareCanonicalization(
EqualityCompareInstr* compare = nullptr;
{
BlockBuilder builder(H.flow_graph(), normal_entry);
Definition* v0 =
builder.AddParameter(0, 0, /*with_frame=*/true, kUnboxedInt64);
Definition* v1 =
builder.AddParameter(1, 1, /*with_frame=*/true, kUnboxedInt64);
Definition* v0 = builder.AddParameter(0, kUnboxedInt64);
Definition* v1 = builder.AddParameter(1, kUnboxedInt64);
Definition* box0 = builder.AddDefinition(new BoxInt64Instr(new Value(v0)));
Definition* box1 = builder.AddDefinition(new BoxInt64Instr(new Value(v1)));
@ -1391,7 +1382,7 @@ static void TestRepresentationChangeDuringCanonicalization(
Definition* add = nullptr;
{
BlockBuilder builder(H.flow_graph(), normal_entry);
param = builder.AddParameter(0, 0, /*with_frame=*/true, kUnboxedInt64);
param = builder.AddParameter(0, kUnboxedInt64);
InputsArray args;
args.Add(new Value(H.flow_graph()->constant_null()));
@ -1586,8 +1577,7 @@ static void TestTestRangeCanonicalize(const AbstractType& type,
ReturnInstr* ret;
{
BlockBuilder builder(H.flow_graph(), normal_entry);
Definition* param =
builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
Definition* param = builder.AddParameter(0, kTagged);
Definition* load_cid =
builder.AddDefinition(new LoadClassIdInstr(new Value(param)));
Definition* test_range = builder.AddDefinition(new TestRangeInstr(

View file

@ -982,46 +982,18 @@ static void ReplaceParameterStubs(Zone* zone,
defns = callee_graph->graph_entry()->normal_entry()->initial_definitions();
for (intptr_t i = 0; i < defns->length(); ++i) {
ConstantInstr* constant = (*defns)[i]->AsConstant();
if (constant != nullptr && constant->HasUses()) {
auto defn = (*defns)[i];
if (!defn->HasUses()) continue;
if (auto constant = defn->AsConstant()) {
constant->ReplaceUsesWith(caller_graph->GetConstant(
constant->value(), constant->representation()));
}
SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter();
if (param != nullptr && param->HasUses()) {
switch (param->kind()) {
case SpecialParameterInstr::kContext: {
ASSERT(!is_polymorphic);
// We do not support polymorphic inlining of closure calls.
ASSERT(call_data->call->IsClosureCall());
LoadFieldInstr* context_load = new (zone) LoadFieldInstr(
new Value((*arguments)[first_arg_index]->definition()),
Slot::Closure_context(), call_data->call->source());
caller_graph->AllocateSSAIndex(context_load);
context_load->InsertBefore(callee_entry->next());
param->ReplaceUsesWith(context_load);
break;
}
case SpecialParameterInstr::kTypeArgs: {
Definition* type_args;
if (first_arg_index > 0) {
type_args = (*arguments)[0]->definition();
} else {
type_args = caller_graph->constant_null();
}
param->ReplaceUsesWith(type_args);
break;
}
case SpecialParameterInstr::kArgDescriptor: {
if (auto param = defn->AsParameter()) {
if (param->location().Equals(Location::RegisterLocation(ARGS_DESC_REG))) {
param->ReplaceUsesWith(
caller_graph->GetConstant(call_data->arguments_descriptor));
break;
}
default: {
UNREACHABLE();
break;
}
}
}
}
@ -1169,8 +1141,8 @@ class CallSiteInliner : public ValueObject {
return graph->GetConstant(constant->value());
}
ParameterInstr* param = new (Z) ParameterInstr(
/*env_index=*/i, /*param_index=*/i,
/*param_offset=*/-1, graph->graph_entry(), kNoRepresentation);
graph->graph_entry(),
/*env_index=*/i, /*param_index=*/i, Location(), kNoRepresentation);
if (i >= 0) {
// Compute initial parameter type using static and inferred types
// and combine it with an argument type from the caller.

View file

@ -778,60 +778,25 @@ void FlowGraphAllocator::ProcessInitialDefinition(
// Save the range end because it may change below.
const intptr_t range_end = range->End();
// TODO(31956): Clean up this code and factor common functionality out.
// Consider also making a separate [ProcessInitialDefinition] for
// [CatchBlockEntry]'s.
if (block->IsCatchBlockEntry()) {
if (SpecialParameterInstr* param = defn->AsSpecialParameter()) {
Location loc;
switch (param->kind()) {
case SpecialParameterInstr::kException:
loc = LocationExceptionLocation();
break;
case SpecialParameterInstr::kStackTrace:
loc = LocationStackTraceLocation();
break;
default:
UNREACHABLE();
}
range->set_assigned_location(loc);
CompleteRange(defn, range);
range->finger()->Initialize(range);
SplitInitialDefinitionAt(range, GetLifetimePosition(block) + 1);
ConvertAllUses(range);
// We have exception/stacktrace in a register and need to
// ensure this register is not available for register allocation during
// the [CatchBlockEntry] to ensure it's not overwritten.
if (loc.IsRegister()) {
BlockLocation(loc, GetLifetimePosition(block),
GetLifetimePosition(block) + 1);
}
return;
}
}
if (auto param = defn->AsParameter()) {
const auto location =
ComputeParameterLocation(block, param, param->base_reg(),
second_location_for_definition ? 1 : 0);
auto location = param->location();
RELEASE_ASSERT(!location.IsInvalid());
if (location.IsPairLocation()) {
location =
location.AsPairLocation()->At(second_location_for_definition ? 1 : 0);
}
range->set_assigned_location(location);
range->set_spill_slot(location);
} else if (defn->IsSpecialParameter()) {
SpecialParameterInstr* param = defn->AsSpecialParameter();
ASSERT(param->kind() == SpecialParameterInstr::kArgDescriptor);
Location loc;
loc = Location::RegisterLocation(ARGS_DESC_REG);
range->set_assigned_location(loc);
if (loc.IsRegister()) {
if (location.IsRegister()) {
CompleteRange(defn, range);
if (range->End() > (GetLifetimePosition(block) + 2)) {
SplitInitialDefinitionAt(range, GetLifetimePosition(block) + 2);
if (range->End() > (GetLifetimePosition(block) + 1)) {
SplitInitialDefinitionAt(range, GetLifetimePosition(block) + 1);
}
ConvertAllUses(range);
BlockLocation(loc, GetLifetimePosition(block),
GetLifetimePosition(block) + 2);
BlockLocation(location, GetLifetimePosition(block),
GetLifetimePosition(block) + 1);
return;
} else {
range->set_spill_slot(location);
}
} else {
ConstantInstr* constant = defn->AsConstant();
@ -3202,46 +3167,6 @@ void FlowGraphAllocator::CollectRepresentations() {
}
}
Location FlowGraphAllocator::ComputeParameterLocation(BlockEntryInstr* block,
ParameterInstr* param,
Register base_reg,
intptr_t pair_index) {
ASSERT(pair_index == 0 || param->HasPairRepresentation());
// Only function entries may have unboxed parameters, possibly making the
// parameters size different from the number of parameters on 32-bit
// architectures.
const intptr_t parameters_size = block->IsFunctionEntry()
? flow_graph_.direct_parameters_size()
: flow_graph_.num_direct_parameters();
intptr_t slot_index = param->param_offset() - pair_index;
ASSERT(slot_index >= 0);
if (base_reg == FPREG) {
// Slot index for the rightmost fixed parameter is -1.
slot_index -= parameters_size;
} else {
// Slot index for a "frameless" parameter is reversed.
ASSERT(base_reg == SPREG);
ASSERT(slot_index < parameters_size);
slot_index = parameters_size - 1 - slot_index;
}
if (base_reg == FPREG) {
slot_index =
compiler::target::frame_layout.FrameSlotForVariableIndex(-slot_index);
} else {
ASSERT(base_reg == SPREG);
slot_index += compiler::target::frame_layout.last_param_from_entry_sp;
}
if (param->representation() == kUnboxedInt64 ||
param->representation() == kTagged) {
return Location::StackSlot(slot_index, base_reg);
} else {
ASSERT(param->representation() == kUnboxedDouble);
return Location::DoubleStackSlot(slot_index, base_reg);
}
}
void FlowGraphAllocator::RemoveFrameIfNotNeeded() {
// Intrinsic functions are naturally frameless.
@ -3326,10 +3251,18 @@ void FlowGraphAllocator::RemoveFrameIfNotNeeded() {
// Fix location of parameters to use SP as their base register instead of FP.
auto fix_location_for = [&](BlockEntryInstr* block, ParameterInstr* param,
intptr_t vreg, intptr_t pair_index) {
auto fp_relative =
ComputeParameterLocation(block, param, FPREG, pair_index);
auto sp_relative =
ComputeParameterLocation(block, param, SPREG, pair_index);
auto location = param->location();
if (location.IsPairLocation()) {
ASSERT(param->HasPairRepresentation());
location = location.AsPairLocation()->At(pair_index);
}
if (!location.HasStackIndex() || location.base_reg() != FPREG) {
return;
}
const auto fp_relative = location;
const auto sp_relative = fp_relative.ToEntrySpRelative();
for (LiveRange* range = GetLiveRange(vreg); range != nullptr;
range = range->next_sibling()) {
if (range->assigned_location().Equals(fp_relative)) {

View file

@ -285,11 +285,6 @@ class FlowGraphAllocator : public ValueObject {
void PrintLiveRanges();
Location ComputeParameterLocation(BlockEntryInstr* block,
ParameterInstr* param,
Register base_reg,
intptr_t pair_index);
// Assign locations for each outgoing argument. Outgoing argumenst are
// currently stored at the top of the stack in direct order (last argument
// at the top of the stack).

View file

@ -250,6 +250,31 @@ void LocationSummary::set_out(intptr_t index, Location loc) {
output_location_ = loc;
}
Location Location::ToSpRelative(intptr_t fp_to_sp_delta) const {
if (IsPairLocation()) {
auto pair = AsPairLocation();
return Pair(pair->At(0).ToSpRelative(fp_to_sp_delta),
pair->At(1).ToSpRelative(fp_to_sp_delta));
}
if (HasStackIndex()) {
ASSERT(base_reg() == FPREG);
uword payload = StackSlotBaseField::encode(SPREG) |
StackIndexField::encode(
EncodeStackIndex(stack_index() - fp_to_sp_delta));
return Location(kind(), payload);
}
return *this;
}
Location Location::ToEntrySpRelative() const {
const auto fp_to_entry_sp_delta =
(compiler::target::frame_layout.param_end_from_fp + 1) -
compiler::target::frame_layout.last_param_from_entry_sp;
return ToSpRelative(fp_to_entry_sp_delta);
}
Location Location::Pair(Location first, Location second) {
PairLocation* pair_location = new PairLocation();
ASSERT((reinterpret_cast<intptr_t>(pair_location) & kLocationTagMask) == 0);
@ -403,12 +428,16 @@ void Location::PrintTo(BaseTextBuffer* f) const {
if (!FLAG_support_il_printer) {
return;
}
if (kind() == kStackSlot) {
f->Printf("S%+" Pd "", stack_index());
} else if (kind() == kDoubleStackSlot) {
f->Printf("DS%+" Pd "", stack_index());
if (kind() == kStackSlot || kind() == kDoubleStackSlot ||
kind() == kQuadStackSlot) {
const char* suffix = "";
if (kind() == kDoubleStackSlot) {
suffix = " f64";
} else if (kind() == kQuadStackSlot) {
f->Printf("QS%+" Pd "", stack_index());
suffix = " f128";
}
f->Printf("%s[%" Pd "] %s", base_reg() == FPREG ? "fp" : "sp",
stack_index(), suffix);
} else if (IsPairLocation()) {
f->AddString("(");
AsPairLocation()->At(0).PrintTo(f);
@ -428,8 +457,16 @@ const char* Location::ToCString() const {
}
void Location::Print() const {
if (kind() == kStackSlot) {
THR_Print("S%+" Pd "", stack_index());
if (kind() == kStackSlot || kind() == kDoubleStackSlot ||
kind() == kQuadStackSlot) {
const char* suffix = "";
if (kind() == kDoubleStackSlot) {
suffix = " f64";
} else if (kind() == kQuadStackSlot) {
suffix = " f128";
}
THR_Print("%s[%" Pd "] %s", base_reg() == FPREG ? "fp" : "sp",
stack_index(), suffix);
} else {
THR_Print("%s", Name());
}

View file

@ -449,6 +449,16 @@ class Location : public ValueObject {
// Returns the offset from the frame pointer for stack slot locations.
intptr_t ToStackSlotOffset() const;
// If the given location is FP relative stack location this returns
// corresponding SP relative location assuming that FP-SP is equal to
// |fp_to_sp_delta|.
Location ToSpRelative(intptr_t fp_to_sp_delta) const;
// If the given location is FP relative stack location this returns
// corresponding SP relative location assuming that SP is equal to SP
// at the entry (i.e. no additional frame was setup on the stack).
Location ToEntrySpRelative() const;
const char* Name() const;
void PrintTo(BaseTextBuffer* f) const;
void Print() const;

View file

@ -109,8 +109,17 @@ static void TryCatchOptimizerTest(
// We should only synchronize state for variables from the synchronized list.
for (auto defn : *catch_entry->initial_definitions()) {
if (ParameterInstr* param = defn->AsParameter()) {
if (param->location().IsRegister()) {
EXPECT(param->location().Equals(LocationExceptionLocation()) ||
param->location().Equals(LocationStackTraceLocation()));
continue;
}
EXPECT(0 <= param->env_index() && param->env_index() < env.length());
EXPECT(env[param->env_index()] != nullptr);
if (env[param->env_index()] == nullptr) {
OS::PrintErr("something is wrong with %s\n", param->ToCString());
}
}
}
}
@ -1630,9 +1639,8 @@ ISOLATE_UNIT_TEST_CASE(CSE_Redefinitions) {
{
BlockBuilder builder(H.flow_graph(), b1);
auto& slot = Slot::Get(field, &H.flow_graph()->parsed_function());
auto param0 =
builder.AddParameter(0, 0, /*with_frame=*/true, kUnboxedDouble);
auto param1 = builder.AddParameter(1, 2, /*with_frame=*/true, kTagged);
auto param0 = builder.AddParameter(0, kUnboxedDouble);
auto param1 = builder.AddParameter(1, kTagged);
auto redef0 =
builder.AddDefinition(new RedefinitionInstr(new Value(param0)));
auto redef1 =

View file

@ -1233,8 +1233,6 @@ CompileType ParameterInstr::ComputeType() const {
}
const intptr_t param_index = this->param_index();
ASSERT((param_index >= 0) || block_->IsCatchBlockEntry());
if (param_index >= 0) {
// Parameter is the receiver.
if ((param_index == 0) &&
@ -1433,27 +1431,6 @@ CompileType RelationalOpInstr::ComputeType() const {
return CompileType::Bool();
}
CompileType SpecialParameterInstr::ComputeType() const {
switch (kind()) {
case kContext:
return CompileType::FromCid(kContextCid);
case kTypeArgs:
return CompileType::FromCid(kTypeArgumentsCid);
case kArgDescriptor:
return CompileType::FromCid(kImmutableArrayCid);
case kException:
return CompileType(CompileType::kCannotBeNull,
CompileType::kCannotBeSentinel, kDynamicCid,
&Object::dynamic_type());
case kStackTrace:
// We cannot use [kStackTraceCid] here because any kind of object can be
// used as a stack trace via `new Future.error(..., <obj>)` :-/
return CompileType::Dynamic();
}
UNREACHABLE();
return CompileType::Dynamic();
}
CompileType CloneContextInstr::ComputeType() const {
return CompileType(CompileType::kCannotBeNull, CompileType::kCannotBeSentinel,
kContextCid, &Object::dynamic_type());

View file

@ -50,7 +50,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_RedefinitionAfterStrictCompareWithNull) {
{
BlockBuilder builder(H.flow_graph(), normal_entry);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
builder.AddBranch(
new StrictCompareInstr(
InstructionSource(), Token::kEQ_STRICT, new Value(v0),
@ -117,7 +117,7 @@ ISOLATE_UNIT_TEST_CASE(
{
BlockBuilder builder(H.flow_graph(), b1);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
auto load_cid = builder.AddDefinition(new LoadClassIdInstr(new Value(v0)));
builder.AddBranch(
new StrictCompareInstr(
@ -216,7 +216,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_Refinement) {
{
BlockBuilder builder(H.flow_graph(), b1);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
builder.AddBranch(new StrictCompareInstr(
InstructionSource(), Token::kEQ_STRICT, new Value(v0),
new Value(H.IntConstant(1)),
@ -307,7 +307,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_Regress36156) {
{
BlockBuilder builder(H.flow_graph(), b1);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
v0 = builder.AddParameter(0, kTagged);
builder.AddBranch(new StrictCompareInstr(
InstructionSource(), Token::kEQ_STRICT, new Value(v0),
new Value(H.IntConstant(1)),
@ -509,7 +509,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_RegressFlutter76919) {
{
BlockBuilder builder(H.flow_graph(), normal_entry);
Definition* v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
Definition* v0 = builder.AddParameter(0, kTagged);
auto null_value = builder.AddNullDefinition();
builder.AddDefinition(new AssertAssignableInstr(
InstructionSource(), new Value(v0),

View file

@ -213,10 +213,10 @@ static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
VerifyParameterIsBoxed(&builder, 0);
@ -318,11 +318,11 @@ static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* value = builder.AddParameter(2, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
Definition* value = builder.AddParameter(2);
VerifyParameterIsBoxed(&builder, 0);
VerifyParameterIsBoxed(&builder, 2);
@ -536,10 +536,10 @@ DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array)
static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* str = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* str = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
VerifyParameterIsBoxed(&builder, 0);
@ -608,10 +608,10 @@ static bool BuildSimdOp(FlowGraph* flow_graph, intptr_t cid, Token::Kind kind) {
Zone* zone = flow_graph->zone();
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* left = builder.AddParameter(0, /*with_frame=*/false);
Definition* right = builder.AddParameter(1, /*with_frame=*/false);
Definition* left = builder.AddParameter(0);
Definition* right = builder.AddParameter(1);
VerifyParameterIsBoxed(&builder, 0);
VerifyParameterIsBoxed(&builder, 1);
@ -675,9 +675,9 @@ static bool BuildFloat32x4Get(FlowGraph* flow_graph,
}
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* receiver = builder.AddParameter(0, /*with_frame=*/false);
Definition* receiver = builder.AddParameter(0);
const auto& function = flow_graph->function();
Definition* unboxed_receiver =
@ -715,9 +715,9 @@ bool GraphIntrinsifier::Build_Float32x4GetW(FlowGraph* flow_graph) {
static bool BuildLoadField(FlowGraph* flow_graph, const Slot& field) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
VerifyParameterIsBoxed(&builder, 0);
Definition* length = builder.AddDefinition(
@ -751,9 +751,9 @@ bool GraphIntrinsifier::Build_ByteDataViewLength(FlowGraph* flow_graph) {
bool GraphIntrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
VerifyParameterIsBoxed(&builder, 0);
Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
@ -768,10 +768,10 @@ bool GraphIntrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
bool GraphIntrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
VerifyParameterIsBoxed(&builder, 0);
@ -795,11 +795,11 @@ bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked(
FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* value = builder.AddParameter(2, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
Definition* value = builder.AddParameter(2);
VerifyParameterIsBoxed(&builder, 0);
VerifyParameterIsBoxed(&builder, 2);
@ -823,11 +823,11 @@ bool GraphIntrinsifier::Build_GrowableArraySetIndexedUnchecked(
FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* array = builder.AddParameter(0, /*with_frame=*/false);
Definition* index = builder.AddParameter(1, /*with_frame=*/false);
Definition* value = builder.AddParameter(2, /*with_frame=*/false);
Definition* array = builder.AddParameter(0);
Definition* index = builder.AddParameter(1);
Definition* value = builder.AddParameter(2);
VerifyParameterIsBoxed(&builder, 0);
VerifyParameterIsBoxed(&builder, 2);
@ -853,10 +853,10 @@ bool GraphIntrinsifier::Build_GrowableArraySetIndexedUnchecked(
bool GraphIntrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0, /*with_frame=*/false);
Definition* data = builder.AddParameter(1, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0);
Definition* data = builder.AddParameter(1);
Zone* zone = flow_graph->zone();
VerifyParameterIsBoxed(&builder, 0);
@ -878,10 +878,10 @@ bool GraphIntrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
bool GraphIntrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0, /*with_frame=*/false);
Definition* length = builder.AddParameter(1, /*with_frame=*/false);
Definition* growable_array = builder.AddParameter(0);
Definition* length = builder.AddParameter(1);
VerifyParameterIsBoxed(&builder, 0);
VerifyParameterIsBoxed(&builder, 1);
@ -901,8 +901,8 @@ static bool BuildUnarySmiOp(FlowGraph* flow_graph, Token::Kind op_kind) {
ASSERT(!flow_graph->function().is_unboxed_parameter_at(0));
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
Definition* left = builder.AddParameter(0, /*with_frame=*/false);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* left = builder.AddParameter(0);
builder.AddInstruction(
new CheckSmiInstr(new Value(left), DeoptId::kNone, builder.Source()));
Definition* result = builder.AddDefinition(
@ -925,9 +925,9 @@ static bool BuildBinarySmiOp(FlowGraph* flow_graph, Token::Kind op_kind) {
ASSERT(!flow_graph->function().is_unboxed_parameter_at(1));
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
Definition* left = builder.AddParameter(0, /*with_frame=*/false);
Definition* right = builder.AddParameter(1, /*with_frame=*/false);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* left = builder.AddParameter(0);
Definition* right = builder.AddParameter(1);
builder.AddInstruction(
new CheckSmiInstr(new Value(left), DeoptId::kNone, builder.Source()));
builder.AddInstruction(
@ -1004,9 +1004,9 @@ bool GraphIntrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) {
}
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
auto normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
Definition* receiver = builder.AddParameter(0, /*with_frame=*/false);
Definition* receiver = builder.AddParameter(0);
Definition* unboxed_value = ConvertOrUnboxDoubleParameter(
&builder, receiver, 0, /* is_checked = */ true);
if (unboxed_value == nullptr) {