| Index: runtime/vm/intermediate_language_x64.cc
|
| diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
|
| index 534ed973105f27805884ad42c497fa4b2142747b..5154230f2d61462fa3fd740dd9c5b729b08716da 100644
|
| --- a/runtime/vm/intermediate_language_x64.cc
|
| +++ b/runtime/vm/intermediate_language_x64.cc
|
| @@ -5807,6 +5807,10 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
| __ 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]));
|
| @@ -5823,21 +5827,35 @@ void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ j(NOT_CARRY, 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();
|
| const bool use_near_jump = num_checks < 5;
|
| + int bias = 0;
|
| for (intptr_t i = 0; i < num_checks; i++) {
|
| - const intptr_t cid = sorted_ic_data[i].cid;
|
| - __ cmpl(temp, Immediate(cid));
|
| - if (i == (num_checks - 1)) {
|
| - __ j(NOT_EQUAL, 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);
|
| + 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;
|
| + }
|
| +
|
| + if (i == num_checks - 1) {
|
| + __ j(no_match, deopt);
|
| } else {
|
| if (use_near_jump) {
|
| - __ j(EQUAL, &is_ok, Assembler::kNearJump);
|
| + __ j(match, &is_ok, Assembler::kNearJump);
|
| } else {
|
| - __ j(EQUAL, &is_ok);
|
| + __ j(match, &is_ok);
|
| }
|
| }
|
| }
|
|
|