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_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((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ) || | |
| 211 (kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)); | |
| 212 | |
| 213 Location left = locs()->in(0); | |
| 214 Location right = locs()->in(1); | |
| 215 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 216 | |
| 217 // Clear upper part of the out register. We are going to use setcc on it | |
| 218 // which is a byte move. | |
| 219 __ xorq(RDX, RDX); | |
| 220 | |
| 221 // Compare left and right. For now only equality comparison is supported. | |
| 222 // TODO(vegorov): reuse code from the other comparison instructions instead of | |
| 223 // generating it inline here. | |
| 224 if (left.IsConstant()) { | |
| 225 __ CompareObject(right.reg(), left.constant()); | |
| 226 } else if (right.IsConstant()) { | |
| 227 __ CompareObject(left.reg(), right.constant()); | |
| 228 } else { | |
| 229 __ cmpq(left.reg(), right.reg()); | |
| 230 } | |
| 231 | |
| 232 Condition true_condition = | |
| 233 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL | |
| 234 : NOT_EQUAL; | |
| 235 | |
| 236 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | |
| 237 | |
| 238 const intptr_t base = Utils::Minimum(if_true_, if_false_); | |
| 239 | |
| 240 if (if_true_ == base) { | |
| 241 // We need to have zero in EDX on true_condition. | |
|
Florian Schneider
2013/04/10 13:59:50
s/EDX/RDX/
Vyacheslav Egorov (Google)
2013/04/10 14:51:32
Done.
| |
| 242 true_condition = NegateCondition(true_condition); | |
| 243 } | |
| 244 | |
| 245 __ setcc(true_condition, DL); | |
| 246 | |
| 247 if (is_power_of_two_kind) { | |
| 248 const intptr_t shift = | |
| 249 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_)); | |
| 250 __ shll(RDX, Immediate(shift + kSmiTagSize)); | |
|
Florian Schneider
2013/04/10 13:59:50
s/shll/shlq
Vyacheslav Egorov (Google)
2013/04/10 14:51:32
Good catch!
| |
| 251 } else { | |
| 252 ASSERT(kSmiTagSize == 1); | |
| 253 __ leaq(RDX, Address(RDX, TIMES_2, base << kSmiTagSize)); | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 | |
| 116 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 258 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 117 const intptr_t kNumInputs = 0; | 259 const intptr_t kNumInputs = 0; |
| 118 const intptr_t kNumTemps = 1; | 260 const intptr_t kNumTemps = 1; |
| 119 LocationSummary* result = | 261 LocationSummary* result = |
| 120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 262 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 121 result->set_out(Location::RegisterLocation(RAX)); | 263 result->set_out(Location::RegisterLocation(RAX)); |
| 122 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 264 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| 123 return result; | 265 return result; |
| 124 } | 266 } |
| 125 | 267 |
| (...skipping 2963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3089 } | 3231 } |
| 3090 | 3232 |
| 3091 // We can fall through if the successor is the next block in the list. | 3233 // We can fall through if the successor is the next block in the list. |
| 3092 // Otherwise, we need a jump. | 3234 // Otherwise, we need a jump. |
| 3093 if (!compiler->CanFallThroughTo(successor())) { | 3235 if (!compiler->CanFallThroughTo(successor())) { |
| 3094 __ jmp(compiler->GetJumpLabel(successor())); | 3236 __ jmp(compiler->GetJumpLabel(successor())); |
| 3095 } | 3237 } |
| 3096 } | 3238 } |
| 3097 | 3239 |
| 3098 | 3240 |
| 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, | 3241 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 3120 bool value) { | 3242 bool value) { |
| 3121 if (value && !compiler->CanFallThroughTo(true_successor())) { | 3243 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 3122 __ jmp(compiler->GetJumpLabel(true_successor())); | 3244 __ jmp(compiler->GetJumpLabel(true_successor())); |
| 3123 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | 3245 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 3124 __ jmp(compiler->GetJumpLabel(false_successor())); | 3246 __ jmp(compiler->GetJumpLabel(false_successor())); |
| 3125 } | 3247 } |
| 3126 } | 3248 } |
| 3127 | 3249 |
| 3128 | 3250 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3356 PcDescriptors::kOther, | 3478 PcDescriptors::kOther, |
| 3357 locs()); | 3479 locs()); |
| 3358 __ Drop(2); // Discard type arguments and receiver. | 3480 __ Drop(2); // Discard type arguments and receiver. |
| 3359 } | 3481 } |
| 3360 | 3482 |
| 3361 } // namespace dart | 3483 } // namespace dart |
| 3362 | 3484 |
| 3363 #undef __ | 3485 #undef __ |
| 3364 | 3486 |
| 3365 #endif // defined TARGET_ARCH_X64 | 3487 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |