Chromium Code Reviews| 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 |