OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
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 5045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5056 | 5056 |
5057 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5057 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5058 __ Comment("BranchInstr"); | 5058 __ Comment("BranchInstr"); |
5059 comparison()->EmitBranchCode(compiler, this); | 5059 comparison()->EmitBranchCode(compiler, this); |
5060 } | 5060 } |
5061 | 5061 |
5062 | 5062 |
5063 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5063 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5064 bool opt) const { | 5064 bool opt) const { |
5065 const intptr_t kNumInputs = 1; | 5065 const intptr_t kNumInputs = 1; |
5066 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5066 const bool need_mask_temp = IsBitTest(); |
5067 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5067 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5068 LocationSummary* summary = new (zone) | 5068 LocationSummary* summary = new (zone) |
5069 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5069 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5070 summary->set_in(0, Location::RequiresRegister()); | 5070 summary->set_in(0, Location::RequiresRegister()); |
5071 if (!IsNullCheck()) { | 5071 if (!IsNullCheck()) { |
5072 summary->set_temp(0, Location::RequiresRegister()); | 5072 summary->set_temp(0, Location::RequiresRegister()); |
5073 if (need_mask_temp) { | 5073 if (need_mask_temp) { |
5074 summary->set_temp(1, Location::RequiresRegister()); | 5074 summary->set_temp(1, Location::RequiresRegister()); |
5075 } | 5075 } |
5076 } | 5076 } |
5077 return summary; | 5077 return summary; |
5078 } | 5078 } |
5079 | 5079 |
5080 | 5080 |
5081 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5081 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
5082 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, | 5082 if (IsDeoptIfNull()) { |
5083 licm_hoisted_ ? ICData::kHoisted : 0); | 5083 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
5084 if (IsNullCheck()) { | 5084 } else { |
5085 if (DeoptIfNull()) { | 5085 ASSERT(IsDeoptIfNotNull()); |
5086 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); | 5086 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
5087 } else { | |
5088 ASSERT(DeoptIfNotNull()); | |
5089 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); | |
5090 } | |
5091 return; | |
5092 } | 5087 } |
5093 | 5088 return; |
Vyacheslav Egorov (Google)
2017/05/09 21:07:28
remove return (I guess all EmitNullCheck have this
erikcorry
2017/05/10 08:47:43
Done.
| |
5094 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | |
5095 (unary_checks().NumberOfChecks() > 1)); | |
5096 Register value = locs()->in(0).reg(); | |
5097 Register temp = locs()->temp(0).reg(); | |
5098 Label is_ok; | |
5099 if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) { | |
5100 __ andi(CMPRES1, value, Immediate(kSmiTagMask)); | |
5101 __ beq(CMPRES1, ZR, &is_ok); | |
5102 } else { | |
5103 __ andi(CMPRES1, value, Immediate(kSmiTagMask)); | |
5104 __ beq(CMPRES1, ZR, deopt); | |
5105 } | |
5106 Register biased_cid = temp; | |
5107 __ LoadClassId(biased_cid, value); | |
5108 | |
5109 GrowableArray<CidRangeTarget> sorted_ic_data; | |
5110 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, | |
5111 /* drop_smi = */ true); | |
5112 | |
5113 if (IsDenseSwitch()) { | |
5114 ASSERT(cids_[0] < cids_[cids_.length() - 1]); | |
5115 __ LoadImmediate(TMP, cids_[0]); | |
5116 __ subu(biased_cid, biased_cid, TMP); | |
5117 __ LoadImmediate(TMP, cids_[cids_.length() - 1] - cids_[0]); | |
5118 __ BranchUnsignedGreater(biased_cid, TMP, deopt); | |
5119 | |
5120 intptr_t mask = ComputeCidMask(); | |
5121 if (!IsDenseMask(mask)) { | |
5122 // Only need mask if there are missing numbers in the range. | |
5123 ASSERT(cids_.length() > 2); | |
5124 Register mask_reg = locs()->temp(1).reg(); | |
5125 __ LoadImmediate(mask_reg, 1); | |
5126 __ sllv(mask_reg, mask_reg, biased_cid); | |
5127 __ AndImmediate(mask_reg, mask_reg, mask); | |
5128 __ beq(mask_reg, ZR, deopt); | |
5129 } | |
5130 } else { | |
5131 const intptr_t num_checks = sorted_ic_data.length(); | |
5132 int bias = 0; | |
5133 for (intptr_t i = 0; i < num_checks; i++) { | |
5134 const intptr_t cid_start = sorted_ic_data[i].cid_start; | |
5135 const intptr_t cid_end = sorted_ic_data[i].cid_end; | |
5136 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid); | |
5137 if (cid_start == cid_end) { | |
5138 __ LoadImmediate(TMP, cid_start - bias); | |
5139 if (i == (num_checks - 1)) { | |
5140 __ bne(biased_cid, TMP, deopt); | |
5141 } else { | |
5142 __ beq(biased_cid, TMP, &is_ok); | |
5143 } | |
5144 } else { | |
5145 // For class ID ranges use a subtract followed by an unsigned | |
5146 // comparison to check both ends of the ranges with one comparison. | |
5147 __ AddImmediate(biased_cid, biased_cid, bias - cid_start); | |
5148 bias = cid_start; | |
5149 // TODO(erikcorry): We should use sltiu instead of the temporary TMP if | |
5150 // the range is small enough. | |
5151 __ LoadImmediate(TMP, cid_end - cid_start); | |
5152 // Reverse comparison so we get 1 if biased_cid > tmp ie cid is out of | |
5153 // range. | |
5154 __ sltu(TMP, TMP, biased_cid); | |
5155 if (i == (num_checks - 1)) { | |
5156 __ bne(TMP, ZR, deopt); | |
5157 } else { | |
5158 __ beq(TMP, ZR, &is_ok); | |
5159 } | |
5160 } | |
5161 } | |
5162 } | |
5163 __ Bind(&is_ok); | |
5164 } | 5089 } |
5165 | 5090 |
5166 | 5091 |
5092 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | |
5093 intptr_t min, | |
5094 intptr_t max, | |
5095 intptr_t mask, | |
5096 Label* deopt) { | |
5097 Register biased_cid = locs()->temp(0).reg(); | |
5098 __ LoadImmediate(TMP, min); | |
5099 __ subu(biased_cid, biased_cid, TMP); | |
5100 __ LoadImmediate(TMP, max - min); | |
5101 __ BranchUnsignedGreater(biased_cid, TMP, deopt); | |
5102 | |
5103 Register bit_reg = locs()->temp(1).reg(); | |
5104 __ LoadImmediate(bit_reg, 1); | |
5105 __ sllv(bit_reg, bit_reg, biased_cid); | |
5106 __ AndImmediate(bit_reg, bit_reg, mask); | |
5107 __ beq(bit_reg, ZR, deopt); | |
5108 } | |
5109 | |
5110 | |
5111 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | |
5112 int bias, | |
5113 intptr_t cid_start, | |
5114 intptr_t cid_end, | |
5115 bool is_last, | |
5116 Label* is_ok, | |
5117 Label* deopt, | |
5118 bool use_near_jump) { | |
5119 Register biased_cid = locs()->temp(0).reg(); | |
5120 if (cid_start == cid_end) { | |
5121 __ LoadImmediate(TMP, cid_start - bias); | |
5122 if (is_last) { | |
5123 __ bne(biased_cid, TMP, deopt); | |
5124 } else { | |
5125 __ beq(biased_cid, TMP, is_ok); | |
5126 } | |
5127 } else { | |
5128 // For class ID ranges use a subtract followed by an unsigned | |
5129 // comparison to check both ends of the ranges with one comparison. | |
5130 __ AddImmediate(biased_cid, biased_cid, bias - cid_start); | |
5131 bias = cid_start; | |
5132 // TODO(erikcorry): We should use sltiu instead of the temporary TMP if | |
5133 // the range is small enough. | |
5134 __ LoadImmediate(TMP, cid_end - cid_start); | |
5135 // Reverse comparison so we get 1 if biased_cid > tmp ie cid is out of | |
5136 // range. | |
5137 __ sltu(TMP, TMP, biased_cid); | |
5138 if (is_last) { | |
5139 __ bne(TMP, ZR, deopt); | |
5140 } else { | |
5141 __ beq(TMP, ZR, is_ok); | |
5142 } | |
5143 } | |
5144 return bias; | |
5145 } | |
5146 | |
5147 | |
5167 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5148 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5168 bool opt) const { | 5149 bool opt) const { |
5169 const intptr_t kNumInputs = 1; | 5150 const intptr_t kNumInputs = 1; |
5170 const intptr_t kNumTemps = 0; | 5151 const intptr_t kNumTemps = 0; |
5171 LocationSummary* summary = new (zone) | 5152 LocationSummary* summary = new (zone) |
5172 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5153 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5173 summary->set_in(0, Location::RequiresRegister()); | 5154 summary->set_in(0, Location::RequiresRegister()); |
5174 return summary; | 5155 return summary; |
5175 } | 5156 } |
5176 | 5157 |
(...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6108 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 6089 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6109 kGrowRegExpStackRuntimeEntry, 1, locs()); | 6090 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6110 __ lw(result, Address(SP, 1 * kWordSize)); | 6091 __ lw(result, Address(SP, 1 * kWordSize)); |
6111 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 6092 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
6112 } | 6093 } |
6113 | 6094 |
6114 | 6095 |
6115 } // namespace dart | 6096 } // namespace dart |
6116 | 6097 |
6117 #endif // defined TARGET_ARCH_MIPS | 6098 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |