| 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/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 // This sequence is patched by a debugger breakpoint. There is no need for | 104 // This sequence is patched by a debugger breakpoint. There is no need for |
| 105 // extra NOP instructions here because the sequence patched in for a | 105 // extra NOP instructions here because the sequence patched in for a |
| 106 // breakpoint is shorter than the sequence here. | 106 // breakpoint is shorter than the sequence here. |
| 107 __ LeaveDartFrameAndReturn(); | 107 __ LeaveDartFrameAndReturn(); |
| 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 109 Isolate::kNoDeoptId, | 109 Isolate::kNoDeoptId, |
| 110 token_pos()); | 110 token_pos()); |
| 111 } | 111 } |
| 112 | 112 |
| 113 | 113 |
| 114 bool IfThenElseInstr::IsSupported() { | 114 static Condition NegateCondition(Condition condition) { |
| 115 return false; | 115 switch (condition) { |
| 116 case EQ: return NE; |
| 117 case NE: return EQ; |
| 118 case LT: return GE; |
| 119 case LE: return GT; |
| 120 case GT: return LE; |
| 121 case GE: return LT; |
| 122 default: |
| 123 OS::Print("Error: Condition not recognized: %d\n", condition); |
| 124 UNIMPLEMENTED(); |
| 125 return EQ; |
| 126 } |
| 127 } |
| 128 |
| 129 |
| 130 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { |
| 131 if (!val->BindsToConstant()) { |
| 132 return false; |
| 133 } |
| 134 |
| 135 const Object& bound_constant = val->BoundConstant(); |
| 136 if (!bound_constant.IsSmi()) { |
| 137 return false; |
| 138 } |
| 139 |
| 140 *smi_value = Smi::Cast(bound_constant).Value(); |
| 141 return true; |
| 142 } |
| 143 |
| 144 |
| 145 // Detect pattern when one value is zero and another is a power of 2. |
| 146 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 147 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 148 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 116 } | 149 } |
| 117 | 150 |
| 118 | 151 |
| 119 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | 152 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
| 120 Value* v1, | 153 Value* v1, |
| 121 Value* v2) { | 154 Value* v2) { |
| 122 UNREACHABLE(); | 155 if (!(comparison->IsStrictCompare() && |
| 123 return false; | 156 !comparison->AsStrictCompare()->needs_number_check()) && |
| 157 !(comparison->IsEqualityCompare() && |
| 158 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) { |
| 159 return false; |
| 160 } |
| 161 |
| 162 intptr_t v1_value, v2_value; |
| 163 |
| 164 if (!BindsToSmiConstant(v1, &v1_value) || |
| 165 !BindsToSmiConstant(v2, &v2_value)) { |
| 166 return false; |
| 167 } |
| 168 |
| 169 return true; |
| 124 } | 170 } |
| 125 | 171 |
| 126 | 172 |
| 127 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { | 173 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 128 UNREACHABLE(); | 174 const intptr_t kNumInputs = 2; |
| 129 return NULL; | 175 const intptr_t kNumTemps = 0; |
| 176 LocationSummary* locs = |
| 177 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 178 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 179 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 180 locs->set_out(Location::RequiresRegister()); |
| 181 return locs; |
| 130 } | 182 } |
| 131 | 183 |
| 132 | 184 |
| 133 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 185 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 134 UNREACHABLE(); | 186 const Register result = locs()->out().reg(); |
| 187 ASSERT(Token::IsEqualityOperator(kind())); |
| 188 |
| 189 Location left = locs()->in(0); |
| 190 Location right = locs()->in(1); |
| 191 if (left.IsConstant() && right.IsConstant()) { |
| 192 // TODO(srdjan): Determine why this instruction was not eliminated. |
| 193 bool res = (left.constant().raw() == right.constant().raw()); |
| 194 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) { |
| 195 res = !res; |
| 196 } |
| 197 __ LoadImmediate(result, |
| 198 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_))); |
| 199 return; |
| 200 } |
| 201 |
| 202 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 203 |
| 204 // Clear out register. |
| 205 __ mov(result, ZR); |
| 206 |
| 207 // Compare left and right. For now only equality comparison is supported. |
| 208 // TODO(vegorov): reuse code from the other comparison instructions instead of |
| 209 // generating it inline here. |
| 210 if (left.IsConstant()) { |
| 211 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
| 212 } else if (right.IsConstant()) { |
| 213 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
| 214 } else { |
| 215 __ slt(CMPRES1, left.reg(), right.reg()); |
| 216 __ slt(CMPRES2, right.reg(), left.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 if (true_condition == EQ) { |
| 244 __ xor_(result, CMPRES1, CMPRES2); |
| 245 __ xori(result, result, Immediate(1)); |
| 246 } else { |
| 247 ASSERT(true_condition == NE); |
| 248 __ xor_(result, CMPRES1, CMPRES2); |
| 249 } |
| 250 |
| 251 if (is_power_of_two_kind) { |
| 252 const intptr_t shift = |
| 253 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 254 __ sll(result, result, shift + kSmiTagSize); |
| 255 } else { |
| 256 __ AddImmediate(result, result, -1); |
| 257 const int32_t val = |
| 258 Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 259 __ AndImmediate(result, result, val); |
| 260 if (false_value != 0) { |
| 261 __ AddImmediate(result, result, Smi::RawValue(false_value)); |
| 262 } |
| 263 } |
| 135 } | 264 } |
| 136 | 265 |
| 137 | 266 |
| 138 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 267 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 139 const intptr_t kNumInputs = 0; | 268 const intptr_t kNumInputs = 0; |
| 140 const intptr_t kNumTemps = 1; | 269 const intptr_t kNumTemps = 1; |
| 141 LocationSummary* result = | 270 LocationSummary* result = |
| 142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 271 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 143 result->set_out(Location::RegisterLocation(V0)); | 272 result->set_out(Location::RegisterLocation(V0)); |
| 144 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. | 273 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. |
| (...skipping 3395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3540 } | 3669 } |
| 3541 | 3670 |
| 3542 // We can fall through if the successor is the next block in the list. | 3671 // We can fall through if the successor is the next block in the list. |
| 3543 // Otherwise, we need a jump. | 3672 // Otherwise, we need a jump. |
| 3544 if (!compiler->CanFallThroughTo(successor())) { | 3673 if (!compiler->CanFallThroughTo(successor())) { |
| 3545 __ b(compiler->GetJumpLabel(successor())); | 3674 __ b(compiler->GetJumpLabel(successor())); |
| 3546 } | 3675 } |
| 3547 } | 3676 } |
| 3548 | 3677 |
| 3549 | 3678 |
| 3550 static Condition NegateCondition(Condition condition) { | |
| 3551 switch (condition) { | |
| 3552 case EQ: return NE; | |
| 3553 case NE: return EQ; | |
| 3554 case LT: return GE; | |
| 3555 case LE: return GT; | |
| 3556 case GT: return LE; | |
| 3557 case GE: return LT; | |
| 3558 default: | |
| 3559 OS::Print("Error: Condition not recognized: %d\n", condition); | |
| 3560 UNIMPLEMENTED(); | |
| 3561 return EQ; | |
| 3562 } | |
| 3563 } | |
| 3564 | |
| 3565 | |
| 3566 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | 3679 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 3567 bool value) { | 3680 bool value) { |
| 3568 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); | 3681 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); |
| 3569 if (value && !compiler->CanFallThroughTo(true_successor())) { | 3682 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 3570 __ b(compiler->GetJumpLabel(true_successor())); | 3683 __ b(compiler->GetJumpLabel(true_successor())); |
| 3571 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | 3684 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 3572 __ b(compiler->GetJumpLabel(false_successor())); | 3685 __ b(compiler->GetJumpLabel(false_successor())); |
| 3573 } | 3686 } |
| 3574 } | 3687 } |
| 3575 | 3688 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3780 compiler->GenerateCall(token_pos(), | 3893 compiler->GenerateCall(token_pos(), |
| 3781 &label, | 3894 &label, |
| 3782 PcDescriptors::kOther, | 3895 PcDescriptors::kOther, |
| 3783 locs()); | 3896 locs()); |
| 3784 __ Drop(2); // Discard type arguments and receiver. | 3897 __ Drop(2); // Discard type arguments and receiver. |
| 3785 } | 3898 } |
| 3786 | 3899 |
| 3787 } // namespace dart | 3900 } // namespace dart |
| 3788 | 3901 |
| 3789 #endif // defined TARGET_ARCH_MIPS | 3902 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |