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 |