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 |