| Index: runtime/vm/intermediate_language_x64.cc
|
| diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
|
| index 644e8b2e9d12f8b49d6835765cb11ef9061f1571..318251bac134e4bcbdbbb358e21d1d5cdc882dca 100644
|
| --- a/runtime/vm/intermediate_language_x64.cc
|
| +++ b/runtime/vm/intermediate_language_x64.cc
|
| @@ -5807,7 +5807,7 @@ void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone,
|
| bool opt) const {
|
| const intptr_t kNumInputs = 1;
|
| - const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask());
|
| + const bool need_mask_temp = IsDenseSwitch();
|
| const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0;
|
| LocationSummary* summary = new (zone)
|
| LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| @@ -5822,84 +5822,65 @@ LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone,
|
| }
|
|
|
|
|
| -void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass,
|
| - licm_hoisted_ ? ICData::kHoisted : 0);
|
| - if (IsNullCheck()) {
|
| - __ CompareObject(locs()->in(0).reg(), Object::null_object());
|
| - Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL;
|
| - __ j(cond, deopt);
|
| - return;
|
| - }
|
| +void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) {
|
| + __ CompareObject(locs()->in(0).reg(), Object::null_object());
|
| + Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL;
|
| + __ j(cond, deopt);
|
| + return;
|
| +}
|
|
|
| - ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
|
| - (unary_checks().NumberOfChecks() > 1));
|
| - Register value = locs()->in(0).reg();
|
| - Register temp = locs()->temp(0).reg();
|
| - Label is_ok;
|
| - if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
|
| - __ testq(value, Immediate(kSmiTagMask));
|
| - __ j(ZERO, &is_ok);
|
| - } else {
|
| - __ testq(value, Immediate(kSmiTagMask));
|
| - __ j(ZERO, deopt);
|
| - }
|
| - __ LoadClassId(temp, value);
|
| -
|
| - GrowableArray<CidRangeTarget> sorted_ic_data;
|
| - FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data,
|
| - /* drop_smi = */ true);
|
| -
|
| - if (IsDenseSwitch()) {
|
| - ASSERT(cids_[0] < cids_[cids_.length() - 1]);
|
| - __ subq(temp, Immediate(cids_[0]));
|
| - __ cmpq(temp, Immediate(cids_[cids_.length() - 1] - cids_[0]));
|
| - __ j(ABOVE, deopt);
|
| -
|
| - intptr_t mask = ComputeCidMask();
|
| - if (!IsDenseMask(mask)) {
|
| - // Only need mask if there are missing numbers in the range.
|
| - ASSERT(cids_.length() > 2);
|
| - Register mask_reg = locs()->temp(1).reg();
|
| - __ movq(mask_reg, Immediate(mask));
|
| - __ btq(mask_reg, temp);
|
| - __ j(NOT_CARRY, deopt);
|
| - }
|
| +
|
| +void CheckClassInstr::EmitDenseSwitch(FlowGraphCompiler* compiler,
|
| + intptr_t min,
|
| + intptr_t max,
|
| + intptr_t mask,
|
| + Label* deopt) {
|
| + Register biased_cid = locs()->temp(0).reg();
|
| + __ subq(biased_cid, Immediate(min));
|
| + __ cmpq(biased_cid, Immediate(max - min));
|
| + __ j(ABOVE, deopt);
|
| +
|
| + Register mask_reg = locs()->temp(1).reg();
|
| + __ movq(mask_reg, Immediate(mask));
|
| + __ btq(mask_reg, biased_cid);
|
| + __ j(NOT_CARRY, deopt);
|
| +}
|
| +
|
| +
|
| +int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler,
|
| + int bias,
|
| + intptr_t cid_start,
|
| + intptr_t cid_end,
|
| + bool is_last,
|
| + Label* is_ok,
|
| + Label* deopt,
|
| + bool use_near_jump) {
|
| + Register biased_cid = locs()->temp(0).reg();
|
| + Condition no_match, match;
|
| + if (cid_start == cid_end) {
|
| + __ cmpl(biased_cid, Immediate(cid_start - bias));
|
| + no_match = NOT_EQUAL;
|
| + match = EQUAL;
|
| } else {
|
| - const intptr_t num_checks = sorted_ic_data.length();
|
| - const bool use_near_jump = num_checks < 5;
|
| - int bias = 0;
|
| - for (intptr_t i = 0; i < num_checks; i++) {
|
| - const intptr_t cid_start = sorted_ic_data[i].cid_start;
|
| - const intptr_t cid_end = sorted_ic_data[i].cid_end;
|
| - ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
|
| - Condition no_match, match;
|
| - if (cid_start == cid_end) {
|
| - __ cmpl(temp, Immediate(cid_start - bias));
|
| - no_match = NOT_EQUAL;
|
| - match = EQUAL;
|
| - } else {
|
| - // For class ID ranges use a subtract followed by an unsigned
|
| - // comparison to check both ends of the ranges with one comparison.
|
| - __ addl(temp, Immediate(bias - cid_start));
|
| - bias = cid_start;
|
| - __ cmpl(temp, Immediate(cid_end - cid_start));
|
| - no_match = ABOVE;
|
| - match = BELOW_EQUAL;
|
| - }
|
| + // For class ID ranges use a subtract followed by an unsigned
|
| + // comparison to check both ends of the ranges with one comparison.
|
| + __ addl(biased_cid, Immediate(bias - cid_start));
|
| + bias = cid_start;
|
| + __ cmpl(biased_cid, Immediate(cid_end - cid_start));
|
| + no_match = ABOVE;
|
| + match = BELOW_EQUAL;
|
| + }
|
|
|
| - if (i == num_checks - 1) {
|
| - __ j(no_match, deopt);
|
| - } else {
|
| - if (use_near_jump) {
|
| - __ j(match, &is_ok, Assembler::kNearJump);
|
| - } else {
|
| - __ j(match, &is_ok);
|
| - }
|
| - }
|
| + if (is_last) {
|
| + __ j(no_match, deopt);
|
| + } else {
|
| + if (use_near_jump) {
|
| + __ j(match, is_ok, Assembler::kNearJump);
|
| + } else {
|
| + __ j(match, is_ok);
|
| }
|
| }
|
| - __ Bind(&is_ok);
|
| + return bias;
|
| }
|
|
|
|
|
|
|