mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Cleanup: Make CheckClassId instruction more general so it
can be used uniformly in the polymorphic inliner. R=kustermann@google.com BUG= Review-Url: https://codereview.chromium.org/2891713002 .
This commit is contained in:
parent
bd01ce38ce
commit
4aa5e1d7aa
18 changed files with 142 additions and 75 deletions
|
@ -590,6 +590,12 @@ namespace dart {
|
|||
// If the class id in FP[rA] matches the class id D, then skip the
|
||||
// following instruction.
|
||||
//
|
||||
// - CheckClassIdRange rA, D
|
||||
//
|
||||
// Next instruction is a Nop with S, the size of the class-id range.
|
||||
// If the class id in FP[rA] is between the D D + S, then skip the
|
||||
// following instruction.
|
||||
//
|
||||
// - CheckBitTest rA, D
|
||||
//
|
||||
// Skips the next 3 instructions if the object at FP[rA] is a valid class for
|
||||
|
@ -841,6 +847,7 @@ namespace dart {
|
|||
V(CheckSmi, A, reg, ___, ___) \
|
||||
V(CheckEitherNonSmi, A_D, reg, reg, ___) \
|
||||
V(CheckClassId, A_D, reg, num, ___) \
|
||||
V(CheckClassIdRange, A_D, reg, num, ___) \
|
||||
V(CheckBitTest, A_D, reg, num, ___) \
|
||||
V(CheckCids, A_B_C, reg, num, num) \
|
||||
V(CheckCidsByRange, A_B_C, reg, num, num) \
|
||||
|
|
|
@ -1523,13 +1523,13 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
|
|||
int bias) {
|
||||
intptr_t cid_start = range.cid_start;
|
||||
intptr_t cid_end = range.cid_end;
|
||||
if (cid_start == cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
__ CompareImmediate(R2, cid_start - bias);
|
||||
__ b(next_label, NE);
|
||||
} else {
|
||||
__ AddImmediate(R2, R2, bias - cid_start);
|
||||
bias = cid_start;
|
||||
__ CompareImmediate(R2, cid_end - cid_start);
|
||||
__ CompareImmediate(R2, range.Extent());
|
||||
__ b(next_label, HI); // Unsigned higher.
|
||||
}
|
||||
return bias;
|
||||
|
|
|
@ -1487,13 +1487,13 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
|
|||
int bias) {
|
||||
intptr_t cid_start = range.cid_start;
|
||||
intptr_t cid_end = range.cid_end;
|
||||
if (cid_start == cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
__ CompareImmediate(R2, cid_start - bias);
|
||||
__ b(next_label, NE);
|
||||
} else {
|
||||
__ AddImmediate(R2, bias - cid_start);
|
||||
bias = cid_start;
|
||||
__ CompareImmediate(R2, cid_end - cid_start);
|
||||
__ CompareImmediate(R2, range.Extent());
|
||||
__ b(next_label, HI); // Unsigned higher.
|
||||
}
|
||||
return bias;
|
||||
|
|
|
@ -1457,13 +1457,13 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
|
|||
int bias) {
|
||||
intptr_t cid_start = range.cid_start;
|
||||
intptr_t cid_end = range.cid_end;
|
||||
if (cid_start == cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
__ cmpl(EDI, Immediate(cid_start - bias));
|
||||
__ j(NOT_EQUAL, next_label);
|
||||
} else {
|
||||
__ addl(EDI, Immediate(bias - cid_start));
|
||||
bias = cid_start;
|
||||
__ cmpl(EDI, Immediate(cid_end - cid_start));
|
||||
__ cmpl(EDI, Immediate(range.Extent()));
|
||||
__ j(ABOVE, next_label); // Unsigned higher.
|
||||
}
|
||||
return bias;
|
||||
|
|
|
@ -1558,7 +1558,7 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
|
|||
int bias) {
|
||||
intptr_t cid_start = range.cid_start;
|
||||
intptr_t cid_end = range.cid_end;
|
||||
if (cid_start == cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
__ BranchNotEqual(T2, Immediate(cid_start - bias), next_label);
|
||||
} else {
|
||||
__ AddImmediate(T2, T2, bias - cid_start);
|
||||
|
|
|
@ -1477,13 +1477,13 @@ int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
|
|||
int bias) {
|
||||
intptr_t cid_start = range.cid_start;
|
||||
intptr_t cid_end = range.cid_end;
|
||||
if (cid_start == cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
__ cmpl(RDI, Immediate(cid_start - bias));
|
||||
__ j(NOT_EQUAL, next_label);
|
||||
} else {
|
||||
__ addl(RDI, Immediate(bias - cid_start));
|
||||
bias = cid_start;
|
||||
__ cmpl(RDI, Immediate(cid_end - cid_start));
|
||||
__ cmpl(RDI, Immediate(range.Extent()));
|
||||
__ j(ABOVE, next_label); // Unsigned higher.
|
||||
}
|
||||
return bias;
|
||||
|
|
|
@ -1554,7 +1554,7 @@ bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) {
|
|||
bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) {
|
||||
if ((!FLAG_precompiled_mode ||
|
||||
owner_->inliner_->use_speculative_inlining()) &&
|
||||
target_info.cid_start == target_info.cid_end &&
|
||||
target_info.IsSingleCid() &&
|
||||
TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) {
|
||||
owner_->inlined_ = true;
|
||||
return true;
|
||||
|
@ -1585,7 +1585,7 @@ bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) {
|
|||
RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z));
|
||||
redefinition->set_ssa_temp_index(
|
||||
owner_->caller_graph()->alloc_ssa_temp_index());
|
||||
if (target_info.cid_start == target_info.cid_end) {
|
||||
if (target_info.IsSingleCid()) {
|
||||
redefinition->UpdateType(CompileType::FromCid(target_info.cid_start));
|
||||
}
|
||||
redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry());
|
||||
|
@ -1704,31 +1704,25 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
|||
new (Z) LoadClassIdInstr(new (Z) Value(receiver));
|
||||
load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index());
|
||||
cursor = AppendInstruction(cursor, load_cid);
|
||||
bool follow_with_deopt = false;
|
||||
for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
|
||||
const CidRange& variant = inlined_variants_[i];
|
||||
bool test_is_range = (variant.cid_start != variant.cid_end);
|
||||
bool test_is_range = !variant.IsSingleCid();
|
||||
bool is_last_test = (i == inlined_variants_.length() - 1);
|
||||
// 1. Guard the body with a class id check. We don't need any check if
|
||||
// it's the last test and global analysis has told us that the call is
|
||||
// complete. TODO(erikcorry): Enhance CheckClassIdInstr so it can take an
|
||||
// arbitrary CidRangeTarget. Currently we don't go into this branch if the
|
||||
// last test is a range test - instead we set the follow_with_deopt flag.
|
||||
if (is_last_test && (!test_is_range || call_->complete()) &&
|
||||
non_inlined_variants_->is_empty()) {
|
||||
// complete.
|
||||
if (is_last_test && non_inlined_variants_->is_empty()) {
|
||||
// If it is the last variant use a check class id instruction which can
|
||||
// deoptimize, followed unconditionally by the body. Omit the check if
|
||||
// we know that we have covered all possible classes.
|
||||
if (!call_->complete()) {
|
||||
ASSERT(!test_is_range); // See condition above.
|
||||
RedefinitionInstr* cid_redefinition =
|
||||
new RedefinitionInstr(new (Z) Value(load_cid));
|
||||
cid_redefinition->set_ssa_temp_index(
|
||||
owner_->caller_graph()->alloc_ssa_temp_index());
|
||||
cursor = AppendInstruction(cursor, cid_redefinition);
|
||||
CheckClassIdInstr* check_class_id =
|
||||
new (Z) CheckClassIdInstr(new (Z) Value(cid_redefinition),
|
||||
variant.cid_start, call_->deopt_id());
|
||||
CheckClassIdInstr* check_class_id = new (Z) CheckClassIdInstr(
|
||||
new (Z) Value(cid_redefinition), variant, call_->deopt_id());
|
||||
check_class_id->InheritDeoptTarget(zone(), call_);
|
||||
cursor = AppendInstruction(cursor, check_class_id);
|
||||
}
|
||||
|
@ -1770,7 +1764,6 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
|||
}
|
||||
cursor = NULL;
|
||||
} else {
|
||||
if (is_last_test && test_is_range) follow_with_deopt = true;
|
||||
// For all variants except the last, use a branch on the loaded class
|
||||
// id.
|
||||
const Smi& cid = Smi::ZoneHandle(Smi::New(variant.cid_start));
|
||||
|
@ -1917,14 +1910,6 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
|||
exit_collector_->AddExit(fallback_return);
|
||||
cursor = NULL;
|
||||
} else {
|
||||
if (follow_with_deopt) {
|
||||
DeoptimizeInstr* deopt = new DeoptimizeInstr(
|
||||
ICData::kDeoptPolymorphicInstanceCallTestFail, call_->deopt_id());
|
||||
deopt->InheritDeoptTarget(zone(), call_);
|
||||
cursor = AppendInstruction(cursor, deopt);
|
||||
cursor = NULL;
|
||||
}
|
||||
|
||||
// Remove push arguments of the call.
|
||||
for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) {
|
||||
PushArgumentInstr* push = call_->PushArgumentAt(i);
|
||||
|
|
|
@ -249,8 +249,8 @@ void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) {
|
|||
|
||||
LoadClassIdInstr* load_cid =
|
||||
check->value()->definition()->OriginalDefinition()->AsLoadClassId();
|
||||
if (load_cid != NULL) {
|
||||
SetCid(load_cid->object()->definition(), check->cid());
|
||||
if (load_cid != NULL && check->cids().IsSingleCid()) {
|
||||
SetCid(load_cid->object()->definition(), check->cids().cid_start);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ static void PrintTargetsHelper(BufferFormatter* f,
|
|||
if (i > 0) {
|
||||
f->Print(" | ");
|
||||
}
|
||||
if (range.cid_start == range.cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
const Class& cls =
|
||||
Class::Handle(Isolate::Current()->class_table()->At(range.cid_start));
|
||||
f->Print("%s", String::Handle(cls.Name()).ToCString());
|
||||
|
@ -249,7 +249,7 @@ static void PrintCidsHelper(BufferFormatter* f,
|
|||
const Class& cls =
|
||||
Class::Handle(Isolate::Current()->class_table()->At(range.cid_start));
|
||||
f->Print("%s etc. ", String::Handle(cls.Name()).ToCString());
|
||||
if (range.cid_start == range.cid_end) {
|
||||
if (range.IsSingleCid()) {
|
||||
f->Print(" cid %" Pd, range.cid_start);
|
||||
} else {
|
||||
f->Print(" cid %" Pd "-%" Pd, range.cid_start, range.cid_end);
|
||||
|
@ -1055,8 +1055,17 @@ void CheckClassIdInstr::PrintOperandsTo(BufferFormatter* f) const {
|
|||
value()->PrintTo(f);
|
||||
|
||||
const Class& cls =
|
||||
Class::Handle(Isolate::Current()->class_table()->At(cid()));
|
||||
f->Print(", %s", String::Handle(cls.ScrubbedName()).ToCString());
|
||||
Class::Handle(Isolate::Current()->class_table()->At(cids().cid_start));
|
||||
const String& name = String::Handle(cls.ScrubbedName());
|
||||
if (cids().IsSingleCid()) {
|
||||
f->Print(", %s", name.ToCString());
|
||||
} else {
|
||||
const Class& cls2 =
|
||||
Class::Handle(Isolate::Current()->class_table()->At(cids().cid_end));
|
||||
const String& name2 = String::Handle(cls2.ScrubbedName());
|
||||
f->Print(", cid %" Pd "-%" Pd " %s-%s", cids().cid_start, cids().cid_end,
|
||||
name.ToCString(), name2.ToCString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ bool Value::Equals(Value* other) const {
|
|||
|
||||
static int OrderById(CidRange* const* a, CidRange* const* b) {
|
||||
// Negative if 'a' should sort before 'b'.
|
||||
ASSERT((*a)->cid_start == (*a)->cid_end);
|
||||
ASSERT((*b)->cid_start == (*b)->cid_end);
|
||||
ASSERT((*a)->IsSingleCid());
|
||||
ASSERT((*b)->IsSingleCid());
|
||||
return (*a)->cid_start - (*b)->cid_start;
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ intptr_t Cids::ComputeHighestCid() const {
|
|||
|
||||
bool Cids::HasClassId(intptr_t cid) const {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (cid_ranges_[i]->cid_start <= cid && cid <= cid_ranges_[i]->cid_end) {
|
||||
if (cid_ranges_[i]->Contains(cid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ void Cids::CreateHelper(Zone* zone,
|
|||
|
||||
bool Cids::IsMonomorphic() const {
|
||||
if (length() != 1) return false;
|
||||
return cid_ranges_[0]->cid_start == cid_ranges_[0]->cid_end;
|
||||
return cid_ranges_[0]->IsSingleCid();
|
||||
}
|
||||
|
||||
|
||||
|
@ -301,7 +301,7 @@ CheckClassInstr::CheckClassInstr(Value* value,
|
|||
ASSERT(number_of_checks > 0);
|
||||
SetInputAt(0, value);
|
||||
// Otherwise use CheckSmiInstr.
|
||||
ASSERT(number_of_checks != 1 || cids[0].cid_start != cids[0].cid_end ||
|
||||
ASSERT(number_of_checks != 1 || !cids[0].IsSingleCid() ||
|
||||
cids[0].cid_start != kSmiCid);
|
||||
}
|
||||
|
||||
|
@ -322,8 +322,10 @@ EffectSet CheckClassInstr::Dependencies() const {
|
|||
|
||||
EffectSet CheckClassIdInstr::Dependencies() const {
|
||||
// Externalization of strings via the API can change the class-id.
|
||||
return Field::IsExternalizableCid(cid_) ? EffectSet::Externalization()
|
||||
: EffectSet::None();
|
||||
for (intptr_t i = cids_.cid_start; i <= cids_.cid_end; i++) {
|
||||
if (Field::IsExternalizableCid(i)) return EffectSet::Externalization();
|
||||
}
|
||||
return EffectSet::None();
|
||||
}
|
||||
|
||||
|
||||
|
@ -376,16 +378,14 @@ intptr_t CheckClassInstr::ComputeCidMask() const {
|
|||
intptr_t min = cids_.ComputeLowestCid();
|
||||
intptr_t mask = 0;
|
||||
for (intptr_t i = 0; i < cids_.length(); ++i) {
|
||||
intptr_t cid_start = cids_[i].cid_start;
|
||||
intptr_t cid_end = cids_[i].cid_end;
|
||||
intptr_t run;
|
||||
uintptr_t range = 1ul + cid_end - cid_start;
|
||||
uintptr_t range = 1ul + cids_[i].Extent();
|
||||
if (range >= kBitsPerWord) {
|
||||
run = -1;
|
||||
} else {
|
||||
run = (1 << range) - 1;
|
||||
}
|
||||
mask |= run << (cid_start - min);
|
||||
mask |= run << (cids_[i].cid_start - min);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
@ -2688,7 +2688,8 @@ Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
|
|||
Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||
if (value()->BindsToConstant()) {
|
||||
const Object& constant_value = value()->BoundConstant();
|
||||
if (constant_value.IsSmi() && Smi::Cast(constant_value).Value() == cid_) {
|
||||
if (constant_value.IsSmi() &&
|
||||
cids_.Contains(Smi::Cast(constant_value).Value())) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -557,6 +557,11 @@ struct CidRange : public ZoneAllocated {
|
|||
: ZoneAllocated(), cid_start(o.cid_start), cid_end(o.cid_end) {}
|
||||
CidRange(intptr_t cid_start_arg, intptr_t cid_end_arg)
|
||||
: cid_start(cid_start_arg), cid_end(cid_end_arg) {}
|
||||
|
||||
bool IsSingleCid() const { return cid_start == cid_end; }
|
||||
bool Contains(intptr_t cid) { return cid_start <= cid && cid <= cid_end; }
|
||||
int32_t Extent() const { return cid_end - cid_start; }
|
||||
|
||||
intptr_t cid_start;
|
||||
intptr_t cid_end;
|
||||
};
|
||||
|
@ -7772,13 +7777,13 @@ class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> {
|
|||
|
||||
class CheckClassIdInstr : public TemplateInstruction<1, NoThrow> {
|
||||
public:
|
||||
CheckClassIdInstr(Value* value, intptr_t cid, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id), cid_(cid) {
|
||||
CheckClassIdInstr(Value* value, CidRange cids, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id), cids_(cids) {
|
||||
SetInputAt(0, value);
|
||||
}
|
||||
|
||||
Value* value() const { return inputs_[0]; }
|
||||
intptr_t cid() const { return cid_; }
|
||||
const CidRange& cids() const { return cids_; }
|
||||
|
||||
DECLARE_INSTRUCTION(CheckClassId)
|
||||
|
||||
|
@ -7794,7 +7799,9 @@ class CheckClassIdInstr : public TemplateInstruction<1, NoThrow> {
|
|||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
||||
private:
|
||||
intptr_t cid_;
|
||||
bool Contains(intptr_t cid) const;
|
||||
|
||||
CidRange cids_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CheckClassIdInstr);
|
||||
};
|
||||
|
|
|
@ -6404,7 +6404,8 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
const intptr_t kNumTemps = 0;
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
summary->set_in(0, Location::RequiresRegister());
|
||||
summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
|
||||
: Location::WritableRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -6412,8 +6413,14 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
|
||||
__ CompareImmediate(value, Smi::RawValue(cid_));
|
||||
__ b(deopt, NE);
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ CompareImmediate(value, Smi::RawValue(cids_.cid_start));
|
||||
__ b(deopt, NE);
|
||||
} else {
|
||||
__ AddImmediate(value, -Smi::RawValue(cids_.cid_start));
|
||||
__ CompareImmediate(value, Smi::RawValue(cids_.Extent()));
|
||||
__ b(deopt, HI); // Unsigned higher.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5560,7 +5560,8 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
const intptr_t kNumTemps = 0;
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
summary->set_in(0, Location::RequiresRegister());
|
||||
summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
|
||||
: Location::WritableRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -5568,8 +5569,14 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
|
||||
__ CompareImmediate(value, Smi::RawValue(cid_));
|
||||
__ b(deopt, NE);
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ CompareImmediate(value, Smi::RawValue(cids_.cid_start));
|
||||
__ b(deopt, NE);
|
||||
} else {
|
||||
__ AddImmediate(value, -Smi::RawValue(cids_.cid_start));
|
||||
__ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start));
|
||||
__ b(deopt, HI); // Unsigned higher.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ EMIT_NATIVE_CODE(PolymorphicInstanceCall,
|
|||
}
|
||||
bool using_ranges = false;
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
if (targets_[i].cid_start != targets_[i].cid_end) {
|
||||
if (!targets_[i].IsSingleCid()) {
|
||||
using_ranges = true;
|
||||
break;
|
||||
}
|
||||
|
@ -266,12 +266,10 @@ EMIT_NATIVE_CODE(PolymorphicInstanceCall,
|
|||
}
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
const Function& target = *targets_.TargetAt(i)->target;
|
||||
intptr_t cid_start = targets_[i].cid_start;
|
||||
intptr_t cid_end = targets_[i].cid_end;
|
||||
|
||||
__ Nop(compiler->ToEmbeddableCid(cid_start, this));
|
||||
__ Nop(compiler->ToEmbeddableCid(targets_[i].cid_start, this));
|
||||
if (using_ranges) {
|
||||
__ Nop(compiler->ToEmbeddableCid(1 + cid_end - cid_start, this));
|
||||
__ Nop(compiler->ToEmbeddableCid(1 + targets_[i].Extent(), this));
|
||||
}
|
||||
__ Nop(__ AddConstant(target));
|
||||
}
|
||||
|
@ -1490,7 +1488,14 @@ EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) {
|
|||
|
||||
|
||||
EMIT_NATIVE_CODE(CheckClassId, 1) {
|
||||
__ CheckClassId(locs()->in(0).reg(), compiler->ToEmbeddableCid(cid_, this));
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ CheckClassId(locs()->in(0).reg(),
|
||||
compiler->ToEmbeddableCid(cids_.cid_start, this));
|
||||
} else {
|
||||
__ CheckClassIdRange(locs()->in(0).reg(),
|
||||
compiler->ToEmbeddableCid(cids_.cid_start, this));
|
||||
__ Nop(__ AddConstant(Smi::Handle(Smi::New(cids_.Extent()))));
|
||||
}
|
||||
compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass);
|
||||
}
|
||||
|
||||
|
@ -1523,7 +1528,7 @@ EMIT_NATIVE_CODE(CheckClass, 1) {
|
|||
int smi_adjustment = 0;
|
||||
int length = cids_.length();
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
if (cids_[i].cid_start != cids_[i].cid_end) {
|
||||
if (!cids_[i].IsSingleCid()) {
|
||||
using_ranges = true;
|
||||
} else if (cids_[i].cid_start == kSmiCid) {
|
||||
ASSERT(cids_[i].cid_end == kSmiCid); // We are in the else clause.
|
||||
|
@ -1550,7 +1555,7 @@ EMIT_NATIVE_CODE(CheckClass, 1) {
|
|||
}
|
||||
__ Nop(compiler->ToEmbeddableCid(cid_start, this));
|
||||
if (using_ranges) {
|
||||
__ Nop(compiler->ToEmbeddableCid(1 + cid_end - cid_start, this));
|
||||
__ Nop(compiler->ToEmbeddableCid(1 + cids_[i].Extent(), this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5928,7 +5928,8 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
const intptr_t kNumTemps = 0;
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
summary->set_in(0, Location::RequiresRegister());
|
||||
summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
|
||||
: Location::WritableRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -5936,8 +5937,14 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
|
||||
__ cmpl(value, Immediate(Smi::RawValue(cid_)));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ cmpl(value, Immediate(Smi::RawValue(cids_.cid_start)));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
} else {
|
||||
__ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start)));
|
||||
__ cmpl(value, Immediate(Smi::RawValue(cids_.Extent())));
|
||||
__ j(ABOVE, deopt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5171,7 +5171,9 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
const intptr_t kNumTemps = 0;
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
summary->set_in(0, Location::RequiresRegister());
|
||||
summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
|
||||
: Location::WritableRegister());
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -5179,7 +5181,18 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
|
||||
__ BranchNotEqual(value, Immediate(Smi::RawValue(cid_)), deopt);
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ BranchNotEqual(value, Immediate(Smi::RawValue(cids_.cid_start)), deopt);
|
||||
} else {
|
||||
__ AddImmediate(value, value, -Smi::RawValue(cids_.cid_start));
|
||||
// TODO(erikcorry): We should use sltiu instead of the temporary TMP if
|
||||
// the range is small enough.
|
||||
__ LoadImmediate(TMP, cids_.Extent());
|
||||
// Reverse comparison so we get 1 if biased_cid > tmp ie cid is out of
|
||||
// range.
|
||||
__ sltu(TMP, TMP, value);
|
||||
__ bne(TMP, ZR, deopt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5909,7 +5909,8 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
const intptr_t kNumTemps = 0;
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
summary->set_in(0, Location::RequiresRegister());
|
||||
summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
|
||||
: Location::WritableRegister());
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -5917,8 +5918,14 @@ LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
|
|||
void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
|
||||
__ CompareImmediate(value, Immediate(Smi::RawValue(cid_)));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
if (cids_.IsSingleCid()) {
|
||||
__ CompareImmediate(value, Immediate(Smi::RawValue(cids_.cid_start)));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
} else {
|
||||
__ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start)));
|
||||
__ cmpq(value, Immediate(Smi::RawValue(cids_.Extent())));
|
||||
__ j(ABOVE, deopt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3253,6 +3253,18 @@ RawObject* Simulator::Call(const Code& code,
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(CheckClassIdRange, A_D);
|
||||
const intptr_t actual_cid =
|
||||
reinterpret_cast<intptr_t>(FP[rA]) >> kSmiTagSize;
|
||||
const uintptr_t cid_start = rD;
|
||||
const uintptr_t cid_range = Bytecode::DecodeD(*pc);
|
||||
// Unsigned comparison. Skip either just the nop or both the nop and the
|
||||
// following instruction.
|
||||
pc += (actual_cid - cid_start <= cid_range) ? 2 : 1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(CheckBitTest, A_D);
|
||||
const intptr_t raw_value = reinterpret_cast<intptr_t>(FP[rA]);
|
||||
|
|
Loading…
Reference in a new issue