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 |