[vm, compiler] Make UnboxedConstant more like Constant.
TEST=ci Bug: https://github.com/dart-lang/sdk/issues/45555 Change-Id: Ib396b0281d4e138cc252baacaac18e42057d7bb6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194502 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
1c86b2f5f6
commit
571908fbec
@@ -183,16 +183,24 @@ GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder(
|
||||
: &reverse_postorder_;
|
||||
}
|
||||
|
||||
ConstantInstr* FlowGraph::GetExistingConstant(const Object& object) const {
|
||||
return constant_instr_pool_.LookupValue(object);
|
||||
ConstantInstr* FlowGraph::GetExistingConstant(
|
||||
const Object& object,
|
||||
Representation representation) const {
|
||||
return constant_instr_pool_.LookupValue(
|
||||
ConstantAndRepresentation{object, representation});
|
||||
}
|
||||
|
||||
ConstantInstr* FlowGraph::GetConstant(const Object& object) {
|
||||
ConstantInstr* constant = GetExistingConstant(object);
|
||||
ConstantInstr* FlowGraph::GetConstant(const Object& object,
|
||||
Representation representation) {
|
||||
ConstantInstr* constant = GetExistingConstant(object, representation);
|
||||
if (constant == nullptr) {
|
||||
// Otherwise, allocate and add it to the pool.
|
||||
constant =
|
||||
new (zone()) ConstantInstr(Object::ZoneHandle(zone(), object.ptr()));
|
||||
const Object& zone_object = Object::ZoneHandle(zone(), object.ptr());
|
||||
if (representation == kTagged) {
|
||||
constant = new (zone()) ConstantInstr(zone_object);
|
||||
} else {
|
||||
constant = new (zone()) UnboxedConstantInstr(zone_object, representation);
|
||||
}
|
||||
constant->set_ssa_temp_index(alloc_ssa_temp_index());
|
||||
if (NeedsPairLocation(constant->representation())) {
|
||||
alloc_ssa_temp_index();
|
||||
@@ -236,28 +244,21 @@ bool FlowGraph::IsConstantRepresentable(const Object& value,
|
||||
Definition* FlowGraph::TryCreateConstantReplacementFor(Definition* op,
|
||||
const Object& value) {
|
||||
// Check that representation of the constant matches expected representation.
|
||||
const auto representation = op->representation();
|
||||
if (!IsConstantRepresentable(
|
||||
value, op->representation(),
|
||||
value, representation,
|
||||
/*tagged_value_must_be_smi=*/op->Type()->IsNullableSmi())) {
|
||||
return op;
|
||||
}
|
||||
|
||||
Definition* result = GetConstant(value);
|
||||
if (op->representation() != kTagged) {
|
||||
// We checked above that constant can be safely unboxed.
|
||||
result = UnboxInstr::Create(op->representation(), new Value(result),
|
||||
DeoptId::kNone, Instruction::kNotSpeculative);
|
||||
// If the current instruction is a phi we need to insert the replacement
|
||||
// into the block which contains this phi - because phis exist separately
|
||||
// from all other instructions.
|
||||
if (auto phi = op->AsPhi()) {
|
||||
InsertAfter(phi->GetBlock(), result, nullptr, FlowGraph::kValue);
|
||||
} else {
|
||||
InsertBefore(op, result, nullptr, FlowGraph::kValue);
|
||||
}
|
||||
if (representation == kUnboxedDouble && value.IsInteger()) {
|
||||
// Convert the boxed constant from int to double.
|
||||
return GetConstant(Double::Handle(Double::NewCanonical(
|
||||
Integer::Cast(value).AsDoubleValue())),
|
||||
kUnboxedDouble);
|
||||
}
|
||||
|
||||
return result;
|
||||
return GetConstant(value, representation);
|
||||
}
|
||||
|
||||
void FlowGraph::AddToGraphInitialDefinitions(Definition* defn) {
|
||||
|
||||
@@ -49,34 +49,42 @@ class BlockIterator : public ValueObject {
|
||||
intptr_t current_;
|
||||
};
|
||||
|
||||
struct ConstantAndRepresentation {
|
||||
const Object& constant;
|
||||
Representation representation;
|
||||
};
|
||||
|
||||
struct ConstantPoolTrait {
|
||||
typedef ConstantInstr* Value;
|
||||
typedef const Object& Key;
|
||||
typedef ConstantAndRepresentation Key;
|
||||
typedef ConstantInstr* Pair;
|
||||
|
||||
static Key KeyOf(Pair kv) { return kv->value(); }
|
||||
static Key KeyOf(Pair kv) {
|
||||
return ConstantAndRepresentation{kv->value(), kv->representation()};
|
||||
}
|
||||
|
||||
static Value ValueOf(Pair kv) { return kv; }
|
||||
|
||||
static inline uword Hash(Key key) {
|
||||
if (key.IsSmi()) {
|
||||
return Smi::Cast(key).Value();
|
||||
if (key.constant.IsSmi()) {
|
||||
return Smi::Cast(key.constant).Value();
|
||||
}
|
||||
if (key.IsDouble()) {
|
||||
if (key.constant.IsDouble()) {
|
||||
return static_cast<intptr_t>(bit_cast<int32_t, float>(
|
||||
static_cast<float>(Double::Cast(key).value())));
|
||||
static_cast<float>(Double::Cast(key.constant).value())));
|
||||
}
|
||||
if (key.IsMint()) {
|
||||
return static_cast<intptr_t>(Mint::Cast(key).value());
|
||||
if (key.constant.IsMint()) {
|
||||
return static_cast<intptr_t>(Mint::Cast(key.constant).value());
|
||||
}
|
||||
if (key.IsString()) {
|
||||
return String::Cast(key).Hash();
|
||||
if (key.constant.IsString()) {
|
||||
return String::Cast(key.constant).Hash();
|
||||
}
|
||||
return key.GetClassId();
|
||||
return key.constant.GetClassId();
|
||||
}
|
||||
|
||||
static inline bool IsKeyEqual(Pair kv, Key key) {
|
||||
return kv->value().ptr() == key.ptr();
|
||||
return (kv->value().ptr() == key.constant.ptr()) &&
|
||||
(kv->representation() == key.representation);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -264,11 +272,14 @@ class FlowGraph : public ZoneAllocated {
|
||||
|
||||
// Returns the definition for the object from the constant pool if
|
||||
// one exists, otherwise returns nullptr.
|
||||
ConstantInstr* GetExistingConstant(const Object& object) const;
|
||||
ConstantInstr* GetExistingConstant(
|
||||
const Object& object,
|
||||
Representation representation = kTagged) const;
|
||||
|
||||
// Always returns a definition for the object from the constant pool,
|
||||
// allocating one if it doesn't already exist.
|
||||
ConstantInstr* GetConstant(const Object& object);
|
||||
ConstantInstr* GetConstant(const Object& object,
|
||||
Representation representation = kTagged);
|
||||
|
||||
void AddToGraphInitialDefinitions(Definition* defn);
|
||||
void AddToInitialDefinitions(BlockEntryWithInitialDefs* entry,
|
||||
|
||||
@@ -966,10 +966,12 @@ void FlowGraphCompiler::EmitMove(Location destination,
|
||||
if (destination.IsFpuRegister() || destination.IsDoubleStackSlot() ||
|
||||
destination.IsStackSlot()) {
|
||||
Register tmp = allocator->AllocateTemporary();
|
||||
source.constant_instruction()->EmitMoveToLocation(this, destination, tmp);
|
||||
source.constant_instruction()->EmitMoveToLocation(this, destination, tmp,
|
||||
source.pair_index());
|
||||
allocator->ReleaseTemporary();
|
||||
} else {
|
||||
source.constant_instruction()->EmitMoveToLocation(this, destination);
|
||||
source.constant_instruction()->EmitMoveToLocation(
|
||||
this, destination, kNoRegister, source.pair_index());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,7 +918,8 @@ void FlowGraphCompiler::EmitMove(Location destination,
|
||||
}
|
||||
} else {
|
||||
ASSERT(source.IsConstant());
|
||||
source.constant_instruction()->EmitMoveToLocation(this, destination);
|
||||
source.constant_instruction()->EmitMoveToLocation(
|
||||
this, destination, kNoRegister, source.pair_index());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3207,21 +3207,14 @@ Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||
}
|
||||
|
||||
if (representation() == kUnboxedDouble && value()->BindsToConstant()) {
|
||||
UnboxedConstantInstr* uc = NULL;
|
||||
|
||||
const Object& val = value()->BoundConstant();
|
||||
if (val.IsInteger()) {
|
||||
const Double& double_val = Double::ZoneHandle(
|
||||
flow_graph->zone(),
|
||||
Double::NewCanonical(Integer::Cast(val).AsDoubleValue()));
|
||||
uc = new UnboxedConstantInstr(double_val, kUnboxedDouble);
|
||||
return flow_graph->GetConstant(double_val, kUnboxedDouble);
|
||||
} else if (val.IsDouble()) {
|
||||
uc = new UnboxedConstantInstr(val, kUnboxedDouble);
|
||||
}
|
||||
|
||||
if (uc != NULL) {
|
||||
flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
||||
return uc;
|
||||
return flow_graph->GetConstant(val, kUnboxedDouble);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3283,13 +3276,7 @@ Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
|
||||
}
|
||||
}
|
||||
|
||||
UnboxedConstantInstr* uc =
|
||||
new UnboxedConstantInstr(c->value(), kUnboxedInt32);
|
||||
if (c->range() != NULL) {
|
||||
uc->set_range(*c->range());
|
||||
}
|
||||
flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
||||
return uc;
|
||||
return flow_graph->GetConstant(c->value(), kUnboxedInt32);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -3304,14 +3291,8 @@ Definition* UnboxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
|
||||
// Currently we perform this only on 64-bit architectures.
|
||||
if (compiler::target::kBitsPerWord == 64) {
|
||||
ConstantInstr* c = value()->definition()->AsConstant();
|
||||
if (c != NULL && (c->value().IsSmi() || c->value().IsMint())) {
|
||||
UnboxedConstantInstr* uc =
|
||||
new UnboxedConstantInstr(c->value(), kUnboxedInt64);
|
||||
if (c->range() != NULL) {
|
||||
uc->set_range(*c->range());
|
||||
}
|
||||
flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
||||
return uc;
|
||||
if (c != NULL && c->value().IsInteger()) {
|
||||
return flow_graph->GetConstant(c->value(), kUnboxedInt64);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3561,7 +3561,8 @@ class ConstantInstr : public TemplateDefinition<0, NoThrow, Pure> {
|
||||
|
||||
void EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
const Location& destination,
|
||||
Register tmp = kNoRegister);
|
||||
Register tmp = kNoRegister,
|
||||
intptr_t pair_index = 0);
|
||||
|
||||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
||||
@@ -5657,6 +5658,7 @@ class LoadIndexedInstr : public TemplateDefinition<2, NoThrow> {
|
||||
intptr_t class_id() const { return class_id_; }
|
||||
bool aligned() const { return alignment_ == kAlignedAccess; }
|
||||
|
||||
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
|
||||
virtual bool ComputeCanDeoptimize() const {
|
||||
return GetDeoptId() != DeoptId::kNone;
|
||||
}
|
||||
@@ -6586,6 +6588,7 @@ class LoadFieldInstr : public TemplateDefinition<1, Throws> {
|
||||
DECLARE_INSTRUCTION(LoadField)
|
||||
virtual CompileType ComputeType() const;
|
||||
|
||||
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
|
||||
virtual bool ComputeCanDeoptimize() const { return false; }
|
||||
virtual bool ComputeCanDeoptimizeAfterCall() const {
|
||||
return calls_initializer() && !CompilerState::Current().is_aot();
|
||||
|
||||
@@ -664,7 +664,8 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
const Location& destination,
|
||||
Register tmp) {
|
||||
Register tmp,
|
||||
intptr_t pair_index) {
|
||||
if (destination.IsRegister()) {
|
||||
if (RepresentationUtils::IsUnboxedInteger(representation())) {
|
||||
int64_t v;
|
||||
@@ -675,7 +676,9 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
// Smi untagging, which means the resulting value may be unexpected.
|
||||
ASSERT(v >= 0);
|
||||
}
|
||||
__ LoadImmediate(destination.reg(), v);
|
||||
__ LoadImmediate(destination.reg(), pair_index == 0
|
||||
? Utils::Low32Bits(v)
|
||||
: Utils::High32Bits(v));
|
||||
} else {
|
||||
ASSERT(representation() == kTagged);
|
||||
__ LoadObject(destination.reg(), value_);
|
||||
@@ -708,7 +711,8 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
int64_t v;
|
||||
const bool ok = compiler::HasIntegerValue(value_, &v);
|
||||
RELEASE_ASSERT(ok);
|
||||
__ LoadImmediate(tmp, v);
|
||||
__ LoadImmediate(
|
||||
tmp, pair_index == 0 ? Utils::Low32Bits(v) : Utils::High32Bits(v));
|
||||
} else {
|
||||
__ LoadObject(tmp, value_);
|
||||
}
|
||||
|
||||
@@ -580,7 +580,9 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
const Location& destination,
|
||||
Register tmp) {
|
||||
Register tmp,
|
||||
intptr_t pair_index) {
|
||||
ASSERT(pair_index == 0); // No pair representation needed on 64-bit.
|
||||
if (destination.IsRegister()) {
|
||||
if (representation() == kUnboxedInt32 ||
|
||||
representation() == kUnboxedUint32 ||
|
||||
|
||||
@@ -398,7 +398,8 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
const Location& destination,
|
||||
Register tmp) {
|
||||
Register tmp,
|
||||
intptr_t pair_index) {
|
||||
if (destination.IsRegister()) {
|
||||
if (RepresentationUtils::IsUnboxedInteger(representation())) {
|
||||
int64_t v;
|
||||
@@ -409,7 +410,9 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
// Smi untagging, which means the resulting value may be unexpected.
|
||||
ASSERT(v >= 0);
|
||||
}
|
||||
__ movl(destination.reg(), compiler::Immediate(v));
|
||||
__ movl(destination.reg(),
|
||||
compiler::Immediate(pair_index == 0 ? Utils::Low32Bits(v)
|
||||
: Utils::High32Bits(v)));
|
||||
} else {
|
||||
ASSERT(representation() == kTagged);
|
||||
__ LoadObjectSafely(destination.reg(), value_);
|
||||
@@ -444,10 +447,13 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
__ movsd(LocationToStackSlotAddress(destination), FpuTMP);
|
||||
} else {
|
||||
ASSERT(destination.IsStackSlot());
|
||||
if (value_.IsSmi() &&
|
||||
RepresentationUtils::IsUnboxedInteger(representation())) {
|
||||
if (RepresentationUtils::IsUnboxedInteger(representation())) {
|
||||
int64_t v;
|
||||
const bool ok = compiler::HasIntegerValue(value_, &v);
|
||||
RELEASE_ASSERT(ok);
|
||||
__ movl(LocationToStackSlotAddress(destination),
|
||||
compiler::Immediate(Smi::Cast(value_).Value()));
|
||||
compiler::Immediate(pair_index == 0 ? Utils::Low32Bits(v)
|
||||
: Utils::High32Bits(v)));
|
||||
} else {
|
||||
if (compiler::Assembler::IsSafeSmi(value_) || value_.IsNull()) {
|
||||
__ movl(LocationToStackSlotAddress(destination),
|
||||
|
||||
@@ -529,7 +529,9 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
|
||||
const Location& destination,
|
||||
Register tmp) {
|
||||
Register tmp,
|
||||
intptr_t pair_index) {
|
||||
ASSERT(pair_index == 0); // No pair representation needed on 64-bit.
|
||||
if (destination.IsRegister()) {
|
||||
if (RepresentationUtils::IsUnboxedInteger(representation())) {
|
||||
const int64_t value = Integer::Cast(value_).AsInt64Value();
|
||||
|
||||
@@ -216,15 +216,15 @@ ISOLATE_UNIT_TEST_CASE(Inliner_List_generate) {
|
||||
ILMatcher cursor(flow_graph, entry, /*trace=*/true,
|
||||
ParallelMovesHandling::kSkip);
|
||||
|
||||
Instruction* unbox1 = nullptr;
|
||||
Instruction* unbox2 = nullptr;
|
||||
|
||||
RELEASE_ASSERT(cursor.TryMatch({
|
||||
kMoveGlob,
|
||||
kMatchAndMoveCreateArray,
|
||||
{kMoveAny, &unbox1},
|
||||
kMatchAndMoveUnboxInt64,
|
||||
{kMoveAny, &unbox2},
|
||||
#if defined(TARGET_ARCH_IS_32_BIT)
|
||||
// TODO(rmacnak): Implement missing ops to allow 32-bit architectures in
|
||||
// UnboxInt64Instr::Canonicalize.
|
||||
kMatchAndMoveUnboxInt64,
|
||||
#endif
|
||||
kMatchAndMoveGoto,
|
||||
|
||||
// Loop header
|
||||
@@ -249,9 +249,6 @@ ISOLATE_UNIT_TEST_CASE(Inliner_List_generate) {
|
||||
kMatchAndMoveTargetEntry,
|
||||
kMatchReturn,
|
||||
}));
|
||||
|
||||
EXPECT(unbox1->IsUnboxedConstant() || unbox1->IsUnboxInt64());
|
||||
EXPECT(unbox2->IsUnboxedConstant() || unbox2->IsUnboxInt64());
|
||||
}
|
||||
|
||||
#endif // defined(DART_PRECOMPILER)
|
||||
|
||||
@@ -642,7 +642,14 @@ void FlowGraphAllocator::BuildLiveRanges() {
|
||||
GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
|
||||
for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
|
||||
Definition* defn = (*graph_entry->initial_definitions())[i];
|
||||
ASSERT(!defn->HasPairRepresentation());
|
||||
if (defn->HasPairRepresentation()) {
|
||||
// The lower bits are pushed after the higher bits
|
||||
LiveRange* range = GetLiveRange(ToSecondPairVreg(defn->ssa_temp_index()));
|
||||
range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
|
||||
range->DefineAt(graph_entry->start_pos());
|
||||
ProcessInitialDefinition(defn, range, graph_entry,
|
||||
/*second_location_for_definition=*/true);
|
||||
}
|
||||
LiveRange* range = GetLiveRange(defn->ssa_temp_index());
|
||||
range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
|
||||
range->DefineAt(graph_entry->start_pos());
|
||||
@@ -724,8 +731,9 @@ void FlowGraphAllocator::ProcessInitialDefinition(
|
||||
} else {
|
||||
ConstantInstr* constant = defn->AsConstant();
|
||||
ASSERT(constant != NULL);
|
||||
range->set_assigned_location(Location::Constant(constant));
|
||||
range->set_spill_slot(Location::Constant(constant));
|
||||
const intptr_t pair_index = second_location_for_definition ? 1 : 0;
|
||||
range->set_assigned_location(Location::Constant(constant, pair_index));
|
||||
range->set_spill_slot(Location::Constant(constant, pair_index));
|
||||
}
|
||||
AssignSafepoints(defn, range);
|
||||
range->finger()->Initialize(range);
|
||||
@@ -823,7 +831,11 @@ Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves(
|
||||
|
||||
ConstantInstr* constant = val->definition()->AsConstant();
|
||||
if (constant != NULL) {
|
||||
move->set_src(Location::Constant(constant));
|
||||
move->set_src(Location::Constant(constant, /*pair_index*/ 0));
|
||||
if (val->definition()->HasPairRepresentation()) {
|
||||
move = parallel_move->MoveOperandsAt(move_index++);
|
||||
move->set_src(Location::Constant(constant, /*pair_index*/ 1));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2926,7 +2938,10 @@ void FlowGraphAllocator::CollectRepresentations() {
|
||||
Definition* def = (*initial_definitions)[i];
|
||||
value_representations_[def->ssa_temp_index()] =
|
||||
RepresentationForRange(def->representation());
|
||||
ASSERT(!def->HasPairRepresentation());
|
||||
if (def->HasPairRepresentation()) {
|
||||
value_representations_[ToSecondPairVreg(def->ssa_temp_index())] =
|
||||
RepresentationForRange(def->representation());
|
||||
}
|
||||
}
|
||||
|
||||
for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); !it.Done();
|
||||
|
||||
@@ -145,21 +145,21 @@ class Location : public ValueObject {
|
||||
// allocated by a register allocator. Each unallocated location has
|
||||
// a policy that specifies what kind of location is suitable. Payload
|
||||
// contains register allocation policy.
|
||||
kUnallocated = 3,
|
||||
kUnallocated = 1 << 2,
|
||||
|
||||
// Spill slots allocated by the register allocator. Payload contains
|
||||
// a spill index.
|
||||
kStackSlot = 4, // Word size slot.
|
||||
kDoubleStackSlot = 7, // 64bit stack slot.
|
||||
kQuadStackSlot = 11, // 128bit stack slot.
|
||||
kStackSlot = 2 << 2, // Word size slot.
|
||||
kDoubleStackSlot = 3 << 2, // 64bit stack slot.
|
||||
kQuadStackSlot = 4 << 2, // 128bit stack slot.
|
||||
|
||||
// Register location represents a fixed register. Payload contains
|
||||
// register code.
|
||||
kRegister = 8,
|
||||
kRegister = 5 << 2,
|
||||
|
||||
// FpuRegister location represents a fixed fpu register. Payload contains
|
||||
// its code.
|
||||
kFpuRegister = 12,
|
||||
kFpuRegister = 6 << 2,
|
||||
};
|
||||
|
||||
Location() : value_(kInvalidLocation) {
|
||||
@@ -204,14 +204,21 @@ class Location : public ValueObject {
|
||||
bool IsInvalid() const { return value_ == kInvalidLocation; }
|
||||
|
||||
// Constants.
|
||||
bool IsConstant() const {
|
||||
return (value_ & kLocationTagMask) == kConstantTag;
|
||||
bool IsConstant() const { return (value_ & kConstantTag) == kConstantTag; }
|
||||
|
||||
static Location Constant(const ConstantInstr* obj, int pair_index = 0) {
|
||||
ASSERT((pair_index == 0) || (pair_index == 1));
|
||||
Location loc(reinterpret_cast<uword>(obj) |
|
||||
(pair_index != 0 ? kPairLocationTag : 0) |
|
||||
kConstantTag);
|
||||
ASSERT(obj == loc.constant_instruction());
|
||||
ASSERT(loc.pair_index() == pair_index);
|
||||
return loc;
|
||||
}
|
||||
|
||||
static Location Constant(const ConstantInstr* obj) {
|
||||
Location loc(reinterpret_cast<uword>(obj) | kConstantTag);
|
||||
ASSERT(obj == loc.constant_instruction());
|
||||
return loc;
|
||||
intptr_t pair_index() const {
|
||||
ASSERT(IsConstant());
|
||||
return (value_ & kPairLocationTag) != 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
ConstantInstr* constant_instruction() const {
|
||||
|
||||
@@ -1150,47 +1150,48 @@ main() {
|
||||
/* Flow graph to match:
|
||||
|
||||
4: CheckStackOverflow:8(stack=0, loop=0)
|
||||
6: v590 <- UnboxedConstant(#1.0 double) T{_Double}
|
||||
8: v592 <- UnboxedConstant(#2.0 double) T{_Double}
|
||||
9: ParallelMove r0 <- S+2
|
||||
10: CheckClass:14(v2 Cids[1: _Double@0150898 etc. cid 52])
|
||||
12: v526 <- Unbox:14(v2 T{_Double}) T{_Double}
|
||||
14: v352 <- BinaryDoubleOp:22(+, v590, v526) T{_Double}
|
||||
15: ParallelMove DS-9 <- q3
|
||||
16: v363 <- BinaryDoubleOp:34(+, v592, v526) T{_Double}
|
||||
17: ParallelMove DS-7 <- q0
|
||||
18: v21 <- BinaryDoubleOp:28(+, v352, v363) T{_Double}
|
||||
19: ParallelMove r1 <- C, r2 <- C, DS-5 <- q1
|
||||
20: v24 <- CreateArray:30(v0, v23) T{_List}
|
||||
21: ParallelMove r2 <- r0
|
||||
22: ParallelMove S-3 <- r2
|
||||
22: StoreIndexed(v24, v6, v26, NoStoreBarrier)
|
||||
24: StoreIndexed(v24, v7, v7, NoStoreBarrier)
|
||||
26: StoreIndexed(v24, v3, v29, NoStoreBarrier)
|
||||
28: StoreIndexed(v24, v30, v8, NoStoreBarrier)
|
||||
30: StoreIndexed(v24, v33, v34, NoStoreBarrier)
|
||||
32: StoreIndexed(v24, v35, v9, NoStoreBarrier)
|
||||
34: StoreIndexed(v24, v38, v29, NoStoreBarrier)
|
||||
36: StoreIndexed(v24, v39, v10, NoStoreBarrier)
|
||||
38: StoreIndexed(v24, v42, v43, NoStoreBarrier)
|
||||
39: ParallelMove q0 <- DS-9
|
||||
40: v586 <- Box(v352) T{_Double}
|
||||
41: ParallelMove r1 <- r2, r0 <- r0
|
||||
42: StoreIndexed(v24, v44, v586)
|
||||
44: StoreIndexed(v24, v47, v29, NoStoreBarrier)
|
||||
45: ParallelMove q0 <- DS-7
|
||||
46: v588 <- Box(v363) T{_Double}
|
||||
47: ParallelMove r1 <- r2, r0 <- r0
|
||||
48: StoreIndexed(v24, v48, v588)
|
||||
50: StoreIndexed(v24, v51, v52, NoStoreBarrier)
|
||||
51: ParallelMove q0 <- DS-5
|
||||
52: v580 <- Box(v21) T{_Double}
|
||||
53: ParallelMove r1 <- r2, r0 <- r0
|
||||
54: StoreIndexed(v24, v53, v580)
|
||||
55: ParallelMove r0 <- r2
|
||||
56: v54 <- StringInterpolate:44(v24) T{String}
|
||||
57: ParallelMove r0 <- r0
|
||||
58: Return:48(v54)
|
||||
5: ParallelMove rax <- S+2
|
||||
6: CheckClass:14(v2 Cids[1: _Double@0150898 etc. cid 52])
|
||||
8: v526 <- Unbox:14(v2 T{_Double}) T{_Double}
|
||||
10: ParallelMove xmm1 <- C
|
||||
10: v352 <- BinaryDoubleOp:22(+, v590, v526) T{_Double}
|
||||
11: ParallelMove DS-6 <- xmm1
|
||||
12: ParallelMove xmm2 <- C
|
||||
12: v363 <- BinaryDoubleOp:34(+, v591, v526) T{_Double}
|
||||
13: ParallelMove DS-5 <- xmm2
|
||||
14: ParallelMove xmm0 <- xmm1
|
||||
14: v21 <- BinaryDoubleOp:28(+, v352, v363) T{_Double}
|
||||
15: ParallelMove rbx <- C, r10 <- C, DS-4 <- xmm0
|
||||
16: v24 <- CreateArray:30(v0, v23) T{_List}
|
||||
17: ParallelMove rcx <- rax
|
||||
18: ParallelMove S-3 <- rcx
|
||||
18: StoreIndexed(v24, v6, v26, NoStoreBarrier)
|
||||
20: StoreIndexed(v24, v7, v7, NoStoreBarrier)
|
||||
22: StoreIndexed(v24, v3, v29, NoStoreBarrier)
|
||||
24: StoreIndexed(v24, v30, v8, NoStoreBarrier)
|
||||
26: StoreIndexed(v24, v33, v34, NoStoreBarrier)
|
||||
28: StoreIndexed(v24, v35, v9, NoStoreBarrier)
|
||||
30: StoreIndexed(v24, v38, v29, NoStoreBarrier)
|
||||
32: StoreIndexed(v24, v39, v10, NoStoreBarrier)
|
||||
34: StoreIndexed(v24, v42, v43, NoStoreBarrier)
|
||||
35: ParallelMove xmm0 <- DS-6
|
||||
36: v586 <- Box(v352) T{_Double}
|
||||
37: ParallelMove rdx <- rcx, rax <- rax
|
||||
38: StoreIndexed(v24, v44, v586)
|
||||
40: StoreIndexed(v24, v47, v29, NoStoreBarrier)
|
||||
41: ParallelMove xmm0 <- DS-5
|
||||
42: v588 <- Box(v363) T{_Double}
|
||||
43: ParallelMove rdx <- rcx, rax <- rax
|
||||
44: StoreIndexed(v24, v48, v588)
|
||||
46: StoreIndexed(v24, v51, v52, NoStoreBarrier)
|
||||
47: ParallelMove xmm0 <- DS-4
|
||||
48: v580 <- Box(v21) T{_Double}
|
||||
49: ParallelMove rdx <- rcx, rax <- rax
|
||||
50: StoreIndexed(v24, v53, v580)
|
||||
51: ParallelMove rax <- rcx
|
||||
52: v54 <- StringInterpolate:44(v24) T{String}
|
||||
53: ParallelMove rax <- rax
|
||||
54: Return:48(v54)
|
||||
*/
|
||||
|
||||
CreateArrayInstr* create_array = nullptr;
|
||||
@@ -1201,8 +1202,6 @@ main() {
|
||||
RELEASE_ASSERT(cursor.TryMatch({
|
||||
kMatchAndMoveFunctionEntry,
|
||||
kMatchAndMoveCheckStackOverflow,
|
||||
kMatchAndMoveUnboxedConstant,
|
||||
kMatchAndMoveUnboxedConstant,
|
||||
kMatchAndMoveCheckClass,
|
||||
kMatchAndMoveUnbox,
|
||||
kMatchAndMoveBinaryDoubleOp,
|
||||
|
||||
Reference in New Issue
Block a user