| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 __ nop(1); | 106 __ nop(1); |
| 107 __ nop(1); | 107 __ nop(1); |
| 108 __ nop(1); | 108 __ nop(1); |
| 109 __ nop(1); | 109 __ nop(1); |
| 110 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 110 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 111 Isolate::kNoDeoptId, | 111 Isolate::kNoDeoptId, |
| 112 token_pos()); | 112 token_pos()); |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 static Condition NegateCondition(Condition condition) { |
| 117 switch (condition) { |
| 118 case EQUAL: return NOT_EQUAL; |
| 119 case NOT_EQUAL: return EQUAL; |
| 120 case LESS: return GREATER_EQUAL; |
| 121 case LESS_EQUAL: return GREATER; |
| 122 case GREATER: return LESS_EQUAL; |
| 123 case GREATER_EQUAL: return LESS; |
| 124 case BELOW: return ABOVE_EQUAL; |
| 125 case BELOW_EQUAL: return ABOVE; |
| 126 case ABOVE: return BELOW_EQUAL; |
| 127 case ABOVE_EQUAL: return BELOW; |
| 128 default: |
| 129 OS::Print("Error %d\n", condition); |
| 130 UNIMPLEMENTED(); |
| 131 return EQUAL; |
| 132 } |
| 133 } |
| 134 |
| 135 |
| 136 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { |
| 137 if (!val->BindsToConstant()) { |
| 138 return false; |
| 139 } |
| 140 |
| 141 const Object& bound_constant = val->BoundConstant(); |
| 142 if (!bound_constant.IsSmi()) { |
| 143 return false; |
| 144 } |
| 145 |
| 146 *smi_value = Smi::Cast(bound_constant).Value(); |
| 147 return true; |
| 148 } |
| 149 |
| 150 |
| 151 // Detect pattern when one value is zero and another is a power of 2. |
| 152 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 153 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 154 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 155 } |
| 156 |
| 157 |
| 158 // Detect pattern when one value is increment of another. |
| 159 static bool IsIncrementKind(intptr_t v1, intptr_t v2) { |
| 160 return ((v1 == v2 + 1) || (v1 + 1 == v2)); |
| 161 } |
| 162 |
| 163 |
| 164 bool IfThenElseInstr::IsSupported() { |
| 165 return true; |
| 166 } |
| 167 |
| 168 |
| 169 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
| 170 Value* v1, |
| 171 Value* v2) { |
| 172 if (!(comparison->IsStrictCompare() && |
| 173 !comparison->AsStrictCompare()->needs_number_check()) && |
| 174 !(comparison->IsEqualityCompare() && |
| 175 (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) { |
| 176 return false; |
| 177 } |
| 178 |
| 179 intptr_t v1_value, v2_value; |
| 180 |
| 181 if (!BindsToSmiConstant(v1, &v1_value) || |
| 182 !BindsToSmiConstant(v2, &v2_value)) { |
| 183 return false; |
| 184 } |
| 185 |
| 186 if (IsPowerOfTwoKind(v1_value, v2_value) || |
| 187 IsIncrementKind(v1_value, v2_value)) { |
| 188 return true; |
| 189 } |
| 190 |
| 191 return false; |
| 192 } |
| 193 |
| 194 |
| 195 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 196 const intptr_t kNumInputs = 2; |
| 197 const intptr_t kNumTemps = 0; |
| 198 LocationSummary* locs = |
| 199 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 200 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 201 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 202 // TODO(vegorov): support byte register constraints in the register allocator. |
| 203 locs->set_out(Location::RegisterLocation(RDX)); |
| 204 return locs; |
| 205 } |
| 206 |
| 207 |
| 208 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 209 ASSERT(locs()->out().reg() == RDX); |
| 210 ASSERT(Token::IsEqualityOperator(kind())); |
| 211 |
| 212 Location left = locs()->in(0); |
| 213 Location right = locs()->in(1); |
| 214 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 215 |
| 216 // Clear upper part of the out register. We are going to use setcc on it |
| 217 // which is a byte move. |
| 218 __ xorq(RDX, RDX); |
| 219 |
| 220 // Compare left and right. For now only equality comparison is supported. |
| 221 // TODO(vegorov): reuse code from the other comparison instructions instead of |
| 222 // generating it inline here. |
| 223 if (left.IsConstant()) { |
| 224 __ CompareObject(right.reg(), left.constant()); |
| 225 } else if (right.IsConstant()) { |
| 226 __ CompareObject(left.reg(), right.constant()); |
| 227 } else { |
| 228 __ cmpq(left.reg(), right.reg()); |
| 229 } |
| 230 |
| 231 Condition true_condition = |
| 232 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL |
| 233 : NOT_EQUAL; |
| 234 |
| 235 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 236 |
| 237 const intptr_t base = Utils::Minimum(if_true_, if_false_); |
| 238 |
| 239 if (if_true_ == base) { |
| 240 // We need to have zero in RDX on true_condition. |
| 241 true_condition = NegateCondition(true_condition); |
| 242 } |
| 243 |
| 244 __ setcc(true_condition, DL); |
| 245 |
| 246 if (is_power_of_two_kind) { |
| 247 const intptr_t shift = |
| 248 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_)); |
| 249 __ shlq(RDX, Immediate(shift + kSmiTagSize)); |
| 250 } else { |
| 251 ASSERT(kSmiTagSize == 1); |
| 252 __ leaq(RDX, Address(RDX, TIMES_2, base << kSmiTagSize)); |
| 253 } |
| 254 } |
| 255 |
| 256 |
| 116 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 257 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 117 const intptr_t kNumInputs = 0; | 258 const intptr_t kNumInputs = 0; |
| 118 const intptr_t kNumTemps = 1; | 259 const intptr_t kNumTemps = 1; |
| 119 LocationSummary* result = | 260 LocationSummary* result = |
| 120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 121 result->set_out(Location::RegisterLocation(RAX)); | 262 result->set_out(Location::RegisterLocation(RAX)); |
| 122 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 263 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| 123 return result; | 264 return result; |
| 124 } | 265 } |
| 125 | 266 |
| (...skipping 2963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3089 } | 3230 } |
| 3090 | 3231 |
| 3091 // We can fall through if the successor is the next block in the list. | 3232 // We can fall through if the successor is the next block in the list. |
| 3092 // Otherwise, we need a jump. | 3233 // Otherwise, we need a jump. |
| 3093 if (!compiler->CanFallThroughTo(successor())) { | 3234 if (!compiler->CanFallThroughTo(successor())) { |
| 3094 __ jmp(compiler->GetJumpLabel(successor())); | 3235 __ jmp(compiler->GetJumpLabel(successor())); |
| 3095 } | 3236 } |
| 3096 } | 3237 } |
| 3097 | 3238 |
| 3098 | 3239 |
| 3099 static Condition NegateCondition(Condition condition) { | |
| 3100 switch (condition) { | |
| 3101 case EQUAL: return NOT_EQUAL; | |
| 3102 case NOT_EQUAL: return EQUAL; | |
| 3103 case LESS: return GREATER_EQUAL; | |
| 3104 case LESS_EQUAL: return GREATER; | |
| 3105 case GREATER: return LESS_EQUAL; | |
| 3106 case GREATER_EQUAL: return LESS; | |
| 3107 case BELOW: return ABOVE_EQUAL; | |
| 3108 case BELOW_EQUAL: return ABOVE; | |
| 3109 case ABOVE: return BELOW_EQUAL; | |
| 3110 case ABOVE_EQUAL: return BELOW; | |
| 3111 default: | |
| 3112 OS::Print("Error %d\n", condition); | |
| 3113 UNIMPLEMENTED(); | |
| 3114 return EQUAL; | |
| 3115 } | |
| 3116 } | |
| 3117 | |
| 3118 | |
| 3119 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | 3240 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 3120 bool value) { | 3241 bool value) { |
| 3121 if (value && !compiler->CanFallThroughTo(true_successor())) { | 3242 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 3122 __ jmp(compiler->GetJumpLabel(true_successor())); | 3243 __ jmp(compiler->GetJumpLabel(true_successor())); |
| 3123 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | 3244 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 3124 __ jmp(compiler->GetJumpLabel(false_successor())); | 3245 __ jmp(compiler->GetJumpLabel(false_successor())); |
| 3125 } | 3246 } |
| 3126 } | 3247 } |
| 3127 | 3248 |
| 3128 | 3249 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3356 PcDescriptors::kOther, | 3477 PcDescriptors::kOther, |
| 3357 locs()); | 3478 locs()); |
| 3358 __ Drop(2); // Discard type arguments and receiver. | 3479 __ Drop(2); // Discard type arguments and receiver. |
| 3359 } | 3480 } |
| 3360 | 3481 |
| 3361 } // namespace dart | 3482 } // namespace dart |
| 3362 | 3483 |
| 3363 #undef __ | 3484 #undef __ |
| 3364 | 3485 |
| 3365 #endif // defined TARGET_ARCH_X64 | 3486 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |