Index: runtime/vm/intermediate_language_mips.cc |
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc |
index db8627df59e9fb61094d99b07965b151c1e878eb..a9422e1d948311e35cf0d4aadd063a2dbdb6ba3d 100644 |
--- a/runtime/vm/intermediate_language_mips.cc |
+++ b/runtime/vm/intermediate_language_mips.cc |
@@ -5030,14 +5030,19 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
__ andi(CMPRES1, value, Immediate(kSmiTagMask)); |
__ beq(CMPRES1, ZR, deopt); |
} |
- __ LoadClassId(temp, value); |
+ Register biased_cid = temp; |
+ __ LoadClassId(biased_cid, 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]); |
__ LoadImmediate(TMP, cids_[0]); |
- __ subu(temp, temp, TMP); |
+ __ subu(biased_cid, biased_cid, TMP); |
__ LoadImmediate(TMP, cids_[cids_.length() - 1] - cids_[0]); |
- __ BranchUnsignedGreater(temp, TMP, deopt); |
+ __ BranchUnsignedGreater(biased_cid, TMP, deopt); |
intptr_t mask = ComputeCidMask(); |
if (!IsDenseMask(mask)) { |
@@ -5045,24 +5050,40 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
ASSERT(cids_.length() > 2); |
Register mask_reg = locs()->temp(1).reg(); |
__ LoadImmediate(mask_reg, 1); |
- __ sllv(mask_reg, mask_reg, temp); |
+ __ sllv(mask_reg, mask_reg, biased_cid); |
__ AndImmediate(mask_reg, mask_reg, mask); |
__ beq(mask_reg, ZR, deopt); |
} |
} else { |
- GrowableArray<CidTarget> sorted_ic_data; |
- FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
- /* drop_smi = */ true); |
const intptr_t num_checks = sorted_ic_data.length(); |
+ int bias = 0; |
for (intptr_t i = 0; i < num_checks; i++) { |
- const intptr_t cid = sorted_ic_data[i].cid; |
- ASSERT(cid != kSmiCid); |
- __ LoadImmediate(TMP, cid); |
- __ subu(CMPRES1, temp, TMP); |
- if (i == (num_checks - 1)) { |
- __ bne(CMPRES1, ZR, deopt); |
+ 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); |
+ if (cid_start == cid_end) { |
+ __ LoadImmediate(TMP, cid_start - bias); |
+ if (i == (num_checks - 1)) { |
+ __ bne(biased_cid, TMP, deopt); |
+ } else { |
+ __ beq(biased_cid, TMP, &is_ok); |
+ } |
} else { |
- __ beq(CMPRES1, ZR, &is_ok); |
+ // For class ID ranges use a subtract followed by an unsigned |
+ // comparison to check both ends of the ranges with one comparison. |
+ __ AddImmediate(biased_cid, biased_cid, bias - cid_start); |
+ bias = cid_start; |
+ // TODO(erikcorry): We should use sltiu instead of the temporary TMP if |
+ // the range is small enough. |
+ __ LoadImmediate(TMP, cid_end - cid_start); |
+ // Reverse comparison so we get 1 if biased_cid > tmp ie cid is out of |
+ // range. |
+ __ sltu(TMP, TMP, biased_cid); |
+ if (i == (num_checks - 1)) { |
+ __ bne(TMP, ZR, deopt); |
+ } else { |
+ __ beq(TMP, ZR, &is_ok); |
+ } |
} |
} |
} |