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..bd7d0a1ea1679c2d0dbadf6c063d6d69ddc3b6cd 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 = IsBitTest(); |
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; |
Vyacheslav Egorov (Google)
2017/05/09 21:07:28
ditto
erikcorry
2017/05/10 08:47:43
Done.
|
+} |
- 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::EmitBitTest(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; |
} |