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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 102 |
103 // No need to generate NOP instructions so that the debugger can patch the | 103 // No need to generate NOP instructions so that the debugger can patch the |
104 // return pattern (3 instructions) with a call to the debug stub (also 3 | 104 // return pattern (3 instructions) with a call to the debug stub (also 3 |
105 // instructions). | 105 // instructions). |
106 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 106 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
107 Isolate::kNoDeoptId, | 107 Isolate::kNoDeoptId, |
108 token_pos()); | 108 token_pos()); |
109 } | 109 } |
110 | 110 |
111 | 111 |
112 bool IfThenElseInstr::IsSupported() { | 112 static Condition NegateCondition(Condition condition) { |
113 return false; | 113 switch (condition) { |
| 114 case EQ: return NE; |
| 115 case NE: return EQ; |
| 116 case LT: return GE; |
| 117 case LE: return GT; |
| 118 case GT: return LE; |
| 119 case GE: return LT; |
| 120 case CC: return CS; |
| 121 case LS: return HI; |
| 122 case HI: return LS; |
| 123 case CS: return CC; |
| 124 default: |
| 125 UNREACHABLE(); |
| 126 return EQ; |
| 127 } |
| 128 } |
| 129 |
| 130 |
| 131 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { |
| 132 if (!val->BindsToConstant()) { |
| 133 return false; |
| 134 } |
| 135 |
| 136 const Object& bound_constant = val->BoundConstant(); |
| 137 if (!bound_constant.IsSmi()) { |
| 138 return false; |
| 139 } |
| 140 |
| 141 *smi_value = Smi::Cast(bound_constant).Value(); |
| 142 return true; |
| 143 } |
| 144 |
| 145 |
| 146 // Detect pattern when one value is zero and another is a power of 2. |
| 147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
114 } | 150 } |
115 | 151 |
116 | 152 |
117 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | 153 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
118 Value* v1, | 154 Value* v1, |
119 Value* v2) { | 155 Value* v2) { |
120 UNREACHABLE(); | 156 if (!(comparison->IsStrictCompare() && |
121 return false; | 157 !comparison->AsStrictCompare()->needs_number_check()) && |
| 158 !(comparison->IsEqualityCompare() && |
| 159 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) { |
| 160 return false; |
| 161 } |
| 162 |
| 163 intptr_t v1_value, v2_value; |
| 164 |
| 165 if (!BindsToSmiConstant(v1, &v1_value) || |
| 166 !BindsToSmiConstant(v2, &v2_value)) { |
| 167 return false; |
| 168 } |
| 169 |
| 170 return true; |
122 } | 171 } |
123 | 172 |
124 | 173 |
125 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { | 174 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
126 UNREACHABLE(); | 175 const intptr_t kNumInputs = 2; |
127 return NULL; | 176 const intptr_t kNumTemps = 0; |
| 177 LocationSummary* locs = |
| 178 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 179 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 180 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 181 locs->set_out(Location::RequiresRegister()); |
| 182 return locs; |
128 } | 183 } |
129 | 184 |
130 | 185 |
131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 186 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
132 UNREACHABLE(); | 187 const Register result = locs()->out().reg(); |
| 188 ASSERT(Token::IsEqualityOperator(kind())); |
| 189 |
| 190 Location left = locs()->in(0); |
| 191 Location right = locs()->in(1); |
| 192 if (left.IsConstant() && right.IsConstant()) { |
| 193 // TODO(srdjan): Determine why this instruction was not eliminated. |
| 194 bool res = (left.constant().raw() == right.constant().raw()); |
| 195 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) { |
| 196 res = !res; |
| 197 } |
| 198 __ LoadImmediate(locs()->out().reg(), |
| 199 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_))); |
| 200 return; |
| 201 } |
| 202 |
| 203 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 204 |
| 205 // Clear out register. |
| 206 __ eor(result, result, ShifterOperand(result)); |
| 207 |
| 208 // Compare left and right. For now only equality comparison is supported. |
| 209 // TODO(vegorov): reuse code from the other comparison instructions instead of |
| 210 // generating it inline here. |
| 211 if (left.IsConstant()) { |
| 212 __ CompareObject(right.reg(), left.constant()); |
| 213 } else if (right.IsConstant()) { |
| 214 __ CompareObject(left.reg(), right.constant()); |
| 215 } else { |
| 216 __ cmp(left.reg(), ShifterOperand(right.reg())); |
| 217 } |
| 218 |
| 219 Condition true_condition = |
| 220 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE; |
| 221 |
| 222 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 223 |
| 224 intptr_t true_value = if_true_; |
| 225 intptr_t false_value = if_false_; |
| 226 |
| 227 if (is_power_of_two_kind) { |
| 228 if (true_value == 0) { |
| 229 // We need to have zero in result on true_condition. |
| 230 true_condition = NegateCondition(true_condition); |
| 231 } |
| 232 } else { |
| 233 if (true_value == 0) { |
| 234 // Swap values so that false_value is zero. |
| 235 intptr_t temp = true_value; |
| 236 true_value = false_value; |
| 237 false_value = temp; |
| 238 } else { |
| 239 true_condition = NegateCondition(true_condition); |
| 240 } |
| 241 } |
| 242 |
| 243 __ mov(result, ShifterOperand(1), true_condition); |
| 244 |
| 245 if (is_power_of_two_kind) { |
| 246 const intptr_t shift = |
| 247 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 248 __ Lsl(result, result, shift + kSmiTagSize); |
| 249 } else { |
| 250 __ sub(result, result, ShifterOperand(1)); |
| 251 const int32_t val = |
| 252 Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 253 __ AndImmediate(result, result, val); |
| 254 if (false_value != 0) { |
| 255 __ AddImmediate(result, Smi::RawValue(false_value)); |
| 256 } |
| 257 } |
133 } | 258 } |
134 | 259 |
135 | 260 |
136 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 261 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
137 const intptr_t kNumInputs = 0; | 262 const intptr_t kNumInputs = 0; |
138 const intptr_t kNumTemps = 1; | 263 const intptr_t kNumTemps = 1; |
139 LocationSummary* result = | 264 LocationSummary* result = |
140 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 265 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
141 result->set_out(Location::RegisterLocation(R0)); | 266 result->set_out(Location::RegisterLocation(R0)); |
142 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor. | 267 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor. |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 if (value_is_smi == NULL) { | 457 if (value_is_smi == NULL) { |
333 __ b(&done, EQ); | 458 __ b(&done, EQ); |
334 } else { | 459 } else { |
335 __ b(value_is_smi, EQ); | 460 __ b(value_is_smi, EQ); |
336 } | 461 } |
337 __ LoadClassId(value_cid_reg, value_reg); | 462 __ LoadClassId(value_cid_reg, value_reg); |
338 __ Bind(&done); | 463 __ Bind(&done); |
339 } | 464 } |
340 | 465 |
341 | 466 |
342 static Condition NegateCondition(Condition condition) { | |
343 switch (condition) { | |
344 case EQ: return NE; | |
345 case NE: return EQ; | |
346 case LT: return GE; | |
347 case LE: return GT; | |
348 case GT: return LE; | |
349 case GE: return LT; | |
350 case CC: return CS; | |
351 case LS: return HI; | |
352 case HI: return LS; | |
353 case CS: return CC; | |
354 default: | |
355 UNREACHABLE(); | |
356 return EQ; | |
357 } | |
358 } | |
359 | |
360 | |
361 static Condition FlipCondition(Condition condition) { | 467 static Condition FlipCondition(Condition condition) { |
362 switch (condition) { | 468 switch (condition) { |
363 case EQ: return EQ; | 469 case EQ: return EQ; |
364 case NE: return NE; | 470 case NE: return NE; |
365 case LT: return GT; | 471 case LT: return GT; |
366 case LE: return GE; | 472 case LE: return GE; |
367 case GT: return LT; | 473 case GT: return LT; |
368 case GE: return LE; | 474 case GE: return LE; |
369 case CC: return HI; | 475 case CC: return HI; |
370 case LS: return CS; | 476 case LS: return CS; |
(...skipping 4065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4436 compiler->GenerateCall(token_pos(), | 4542 compiler->GenerateCall(token_pos(), |
4437 &label, | 4543 &label, |
4438 PcDescriptors::kOther, | 4544 PcDescriptors::kOther, |
4439 locs()); | 4545 locs()); |
4440 __ Drop(2); // Discard type arguments and receiver. | 4546 __ Drop(2); // Discard type arguments and receiver. |
4441 } | 4547 } |
4442 | 4548 |
4443 } // namespace dart | 4549 } // namespace dart |
4444 | 4550 |
4445 #endif // defined TARGET_ARCH_ARM | 4551 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |