OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 5463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5474 | 5474 |
5475 | 5475 |
5476 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5476 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5477 comparison()->EmitBranchCode(compiler, this); | 5477 comparison()->EmitBranchCode(compiler, this); |
5478 } | 5478 } |
5479 | 5479 |
5480 | 5480 |
5481 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5481 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5482 bool opt) const { | 5482 bool opt) const { |
5483 const intptr_t kNumInputs = 1; | 5483 const intptr_t kNumInputs = 1; |
5484 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5484 const bool need_mask_temp = IsBitTest(); |
5485 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5485 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5486 LocationSummary* summary = new (zone) | 5486 LocationSummary* summary = new (zone) |
5487 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5487 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5488 summary->set_in(0, Location::RequiresRegister()); | 5488 summary->set_in(0, Location::RequiresRegister()); |
5489 if (!IsNullCheck()) { | 5489 if (!IsNullCheck()) { |
5490 summary->set_temp(0, Location::RequiresRegister()); | 5490 summary->set_temp(0, Location::RequiresRegister()); |
5491 if (need_mask_temp) { | 5491 if (need_mask_temp) { |
5492 summary->set_temp(1, Location::RequiresRegister()); | 5492 summary->set_temp(1, Location::RequiresRegister()); |
5493 } | 5493 } |
5494 } | 5494 } |
5495 return summary; | 5495 return summary; |
5496 } | 5496 } |
5497 | 5497 |
5498 | 5498 |
5499 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5499 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
5500 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, | 5500 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
5501 licm_hoisted_ ? ICData::kHoisted : 0); | 5501 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); |
5502 if (IsNullCheck()) { | 5502 Condition cond = IsDeoptIfNull() ? EQ : NE; |
5503 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5503 __ b(deopt, cond); |
5504 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 5504 return; |
Vyacheslav Egorov (Google)
2017/05/09 21:07:27
any reason for implicit return?
erikcorry
2017/05/10 08:47:43
Gone
| |
5505 Condition cond = DeoptIfNull() ? EQ : NE; | |
5506 __ b(deopt, cond); | |
5507 return; | |
5508 } | |
5509 | |
5510 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | |
5511 (unary_checks().NumberOfChecks() > 1)); | |
5512 const Register value = locs()->in(0).reg(); | |
5513 const Register temp = locs()->temp(0).reg(); | |
5514 Label is_ok; | |
5515 if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) { | |
5516 __ tsti(value, Immediate(kSmiTagMask)); | |
5517 __ b(&is_ok, EQ); | |
5518 } else { | |
5519 __ tsti(value, Immediate(kSmiTagMask)); | |
5520 __ b(deopt, EQ); | |
5521 } | |
5522 Register biased_cid = temp; | |
5523 __ LoadClassId(biased_cid, value); | |
5524 | |
5525 GrowableArray<CidRangeTarget> sorted_ic_data; | |
5526 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, | |
5527 /* drop_smi = */ true); | |
5528 | |
5529 if (IsDenseSwitch()) { | |
5530 ASSERT(cids_[0] < cids_[cids_.length() - 1]); | |
5531 __ AddImmediate(biased_cid, biased_cid, -cids_[0]); | |
5532 __ CompareImmediate(biased_cid, cids_[cids_.length() - 1] - cids_[0]); | |
5533 __ b(deopt, HI); | |
5534 | |
5535 intptr_t mask = ComputeCidMask(); | |
5536 if (!IsDenseMask(mask)) { | |
5537 // Only need mask if there are missing numbers in the range. | |
5538 ASSERT(cids_.length() > 2); | |
5539 Register mask_reg = locs()->temp(1).reg(); | |
5540 __ LoadImmediate(mask_reg, 1); | |
5541 __ lslv(mask_reg, mask_reg, biased_cid); | |
5542 __ TestImmediate(mask_reg, mask); | |
5543 __ b(deopt, EQ); | |
5544 } | |
5545 | |
5546 } else { | |
5547 const intptr_t num_checks = sorted_ic_data.length(); | |
5548 int bias = 0; | |
5549 for (intptr_t i = 0; i < num_checks; i++) { | |
5550 const intptr_t cid_start = sorted_ic_data[i].cid_start; | |
5551 const intptr_t cid_end = sorted_ic_data[i].cid_end; | |
5552 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid); | |
5553 Condition no_match, match; | |
5554 if (cid_start == cid_end) { | |
5555 __ CompareImmediate(biased_cid, cid_start - bias); | |
5556 no_match = NE; | |
5557 match = EQ; | |
5558 } else { | |
5559 // For class ID ranges use a subtract followed by an unsigned | |
5560 // comparison to check both ends of the ranges with one comparison. | |
5561 __ AddImmediate(biased_cid, biased_cid, bias - cid_start); | |
5562 bias = cid_start; | |
5563 __ CompareImmediate(biased_cid, cid_end - cid_start); | |
5564 no_match = HI; // Unsigned higher. | |
5565 match = LS; // Unsigned lower or same. | |
5566 } | |
5567 if (i == (num_checks - 1)) { | |
5568 __ b(deopt, no_match); | |
5569 } else { | |
5570 __ b(&is_ok, match); | |
5571 } | |
5572 } | |
5573 } | |
5574 __ Bind(&is_ok); | |
5575 } | 5505 } |
5576 | 5506 |
5577 | 5507 |
5508 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | |
5509 intptr_t min, | |
5510 intptr_t max, | |
5511 intptr_t mask, | |
5512 Label* deopt) { | |
5513 Register biased_cid = locs()->temp(0).reg(); | |
5514 __ AddImmediate(biased_cid, biased_cid, -min); | |
5515 __ CompareImmediate(biased_cid, max - min); | |
5516 __ b(deopt, HI); | |
5517 | |
5518 Register bit_reg = locs()->temp(1).reg(); | |
5519 __ LoadImmediate(bit_reg, 1); | |
5520 __ lslv(bit_reg, bit_reg, biased_cid); | |
5521 __ TestImmediate(bit_reg, mask); | |
5522 __ b(deopt, EQ); | |
5523 } | |
5524 | |
5525 | |
5526 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | |
5527 int bias, | |
5528 intptr_t cid_start, | |
5529 intptr_t cid_end, | |
5530 bool is_last, | |
5531 Label* is_ok, | |
5532 Label* deopt, | |
5533 bool use_near_jump) { | |
5534 Register biased_cid = locs()->temp(0).reg(); | |
5535 Condition no_match, match; | |
5536 if (cid_start == cid_end) { | |
5537 __ CompareImmediate(biased_cid, cid_start - bias); | |
5538 no_match = NE; | |
5539 match = EQ; | |
5540 } else { | |
5541 // For class ID ranges use a subtract followed by an unsigned | |
5542 // comparison to check both ends of the ranges with one comparison. | |
5543 __ AddImmediate(biased_cid, biased_cid, bias - cid_start); | |
5544 bias = cid_start; | |
5545 __ CompareImmediate(biased_cid, cid_end - cid_start); | |
5546 no_match = HI; // Unsigned higher. | |
5547 match = LS; // Unsigned lower or same. | |
5548 } | |
5549 if (is_last) { | |
5550 __ b(deopt, no_match); | |
5551 } else { | |
5552 __ b(is_ok, match); | |
5553 } | |
5554 return bias; | |
5555 } | |
5556 | |
5557 | |
5578 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5558 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5579 bool opt) const { | 5559 bool opt) const { |
5580 const intptr_t kNumInputs = 1; | 5560 const intptr_t kNumInputs = 1; |
5581 const intptr_t kNumTemps = 0; | 5561 const intptr_t kNumTemps = 0; |
5582 LocationSummary* summary = new (zone) | 5562 LocationSummary* summary = new (zone) |
5583 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5563 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5584 summary->set_in(0, Location::RequiresRegister()); | 5564 summary->set_in(0, Location::RequiresRegister()); |
5585 return summary; | 5565 return summary; |
5586 } | 5566 } |
5587 | 5567 |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6112 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 6092 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6113 kGrowRegExpStackRuntimeEntry, 1, locs()); | 6093 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6114 __ Drop(1); | 6094 __ Drop(1); |
6115 __ Pop(result); | 6095 __ Pop(result); |
6116 } | 6096 } |
6117 | 6097 |
6118 | 6098 |
6119 } // namespace dart | 6099 } // namespace dart |
6120 | 6100 |
6121 #endif // defined TARGET_ARCH_ARM64 | 6101 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |