| Index: runtime/vm/intermediate_language_arm64.cc
|
| diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
|
| index 642bb8f395c823ae447bfc68549008b7b7c2f9b5..98ec6776f6fce0c7f26284173f7c6abe3c7bddbc 100644
|
| --- a/runtime/vm/intermediate_language_arm64.cc
|
| +++ b/runtime/vm/intermediate_language_arm64.cc
|
| @@ -5446,12 +5446,17 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ tsti(value, Immediate(kSmiTagMask));
|
| __ b(deopt, EQ);
|
| }
|
| - __ 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]);
|
| - __ AddImmediate(temp, temp, -cids_[0]);
|
| - __ CompareImmediate(temp, cids_[cids_.length() - 1] - cids_[0]);
|
| + __ AddImmediate(biased_cid, biased_cid, -cids_[0]);
|
| + __ CompareImmediate(biased_cid, cids_[cids_.length() - 1] - cids_[0]);
|
| __ b(deopt, HI);
|
|
|
| intptr_t mask = ComputeCidMask();
|
| @@ -5460,24 +5465,36 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| ASSERT(cids_.length() > 2);
|
| Register mask_reg = locs()->temp(1).reg();
|
| __ LoadImmediate(mask_reg, 1);
|
| - __ lslv(mask_reg, mask_reg, temp);
|
| + __ lslv(mask_reg, mask_reg, biased_cid);
|
| __ TestImmediate(mask_reg, mask);
|
| __ b(deopt, EQ);
|
| }
|
|
|
| } 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);
|
| - __ CompareImmediate(temp, cid);
|
| + 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) {
|
| + __ CompareImmediate(biased_cid, cid_start - bias);
|
| + no_match = NE;
|
| + match = EQ;
|
| + } else {
|
| + // 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;
|
| + __ CompareImmediate(biased_cid, cid_end - cid_start);
|
| + no_match = HI; // Unsigned higher.
|
| + match = LS; // Unsigned lower or same.
|
| + }
|
| if (i == (num_checks - 1)) {
|
| - __ b(deopt, NE);
|
| + __ b(deopt, no_match);
|
| } else {
|
| - __ b(&is_ok, EQ);
|
| + __ b(&is_ok, match);
|
| }
|
| }
|
| }
|
|
|