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 "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "vm/symbols.h" | 21 #include "vm/symbols.h" |
22 | 22 |
23 #define __ compiler->assembler()-> | 23 #define __ compiler->assembler()-> |
24 #define Z (compiler->zone()) | 24 #define Z (compiler->zone()) |
25 | 25 |
26 namespace dart { | 26 namespace dart { |
27 | 27 |
28 // Generic summary for call instructions that have all arguments pushed | 28 // Generic summary for call instructions that have all arguments pushed |
29 // on the stack and return the result in a fixed register RAX. | 29 // on the stack and return the result in a fixed register RAX. |
30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
31 LocationSummary* result = new(zone) LocationSummary( | 31 LocationSummary* result = |
32 zone, 0, 0, LocationSummary::kCall); | 32 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
33 result->set_out(0, Location::RegisterLocation(RAX)); | 33 result->set_out(0, Location::RegisterLocation(RAX)); |
34 return result; | 34 return result; |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
39 bool opt) const { | 39 bool opt) const { |
40 const intptr_t kNumInputs = 1; | 40 const intptr_t kNumInputs = 1; |
41 const intptr_t kNumTemps = 0; | 41 const intptr_t kNumTemps = 0; |
42 LocationSummary* locs = new(zone) LocationSummary( | 42 LocationSummary* locs = new (zone) |
43 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
44 locs->set_in(0, Location::AnyOrConstant(value())); | 44 locs->set_in(0, Location::AnyOrConstant(value())); |
45 return locs; | 45 return locs; |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
51 // where PushArgument is handled by BindInstr::EmitNativeCode. | 51 // where PushArgument is handled by BindInstr::EmitNativeCode. |
52 if (compiler->is_optimizing()) { | 52 if (compiler->is_optimizing()) { |
53 Location value = locs()->in(0); | 53 Location value = locs()->in(0); |
54 if (value.IsRegister()) { | 54 if (value.IsRegister()) { |
55 __ pushq(value.reg()); | 55 __ pushq(value.reg()); |
56 } else if (value.IsConstant()) { | 56 } else if (value.IsConstant()) { |
57 __ PushObject(value.constant()); | 57 __ PushObject(value.constant()); |
58 } else { | 58 } else { |
59 ASSERT(value.IsStackSlot()); | 59 ASSERT(value.IsStackSlot()); |
60 __ pushq(value.ToStackSlotAddress()); | 60 __ pushq(value.ToStackSlotAddress()); |
61 } | 61 } |
62 } | 62 } |
63 } | 63 } |
64 | 64 |
65 | 65 |
66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
67 bool opt) const { | |
68 const intptr_t kNumInputs = 1; | 67 const intptr_t kNumInputs = 1; |
69 const intptr_t kNumTemps = 0; | 68 const intptr_t kNumTemps = 0; |
70 LocationSummary* locs = new(zone) LocationSummary( | 69 LocationSummary* locs = new (zone) |
71 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
72 locs->set_in(0, Location::RegisterLocation(RAX)); | 71 locs->set_in(0, Location::RegisterLocation(RAX)); |
73 return locs; | 72 return locs; |
74 } | 73 } |
75 | 74 |
76 | 75 |
77 // Attempt optimized compilation at return instruction instead of at the entry. | 76 // Attempt optimized compilation at return instruction instead of at the entry. |
78 // The entry needs to be patchable, no inlined objects are allowed in the area | 77 // The entry needs to be patchable, no inlined objects are allowed in the area |
79 // that will be overwritten by the patch instruction: a jump). | 78 // that will be overwritten by the patch instruction: a jump). |
80 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 79 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
81 Register result = locs()->in(0).reg(); | 80 Register result = locs()->in(0).reg(); |
(...skipping 22 matching lines...) Expand all Loading... |
104 __ LeaveDartFrame(); // Disallows constant pool use. | 103 __ LeaveDartFrame(); // Disallows constant pool use. |
105 __ ret(); | 104 __ ret(); |
106 // This ReturnInstr may be emitted out of order by the optimizer. The next | 105 // This ReturnInstr may be emitted out of order by the optimizer. The next |
107 // block may be a target expecting a properly set constant pool pointer. | 106 // block may be a target expecting a properly set constant pool pointer. |
108 __ set_constant_pool_allowed(true); | 107 __ set_constant_pool_allowed(true); |
109 } | 108 } |
110 | 109 |
111 | 110 |
112 static Condition NegateCondition(Condition condition) { | 111 static Condition NegateCondition(Condition condition) { |
113 switch (condition) { | 112 switch (condition) { |
114 case EQUAL: return NOT_EQUAL; | 113 case EQUAL: |
115 case NOT_EQUAL: return EQUAL; | 114 return NOT_EQUAL; |
116 case LESS: return GREATER_EQUAL; | 115 case NOT_EQUAL: |
117 case LESS_EQUAL: return GREATER; | 116 return EQUAL; |
118 case GREATER: return LESS_EQUAL; | 117 case LESS: |
119 case GREATER_EQUAL: return LESS; | 118 return GREATER_EQUAL; |
120 case BELOW: return ABOVE_EQUAL; | 119 case LESS_EQUAL: |
121 case BELOW_EQUAL: return ABOVE; | 120 return GREATER; |
122 case ABOVE: return BELOW_EQUAL; | 121 case GREATER: |
123 case ABOVE_EQUAL: return BELOW; | 122 return LESS_EQUAL; |
124 case PARITY_EVEN: return PARITY_ODD; | 123 case GREATER_EQUAL: |
125 case PARITY_ODD: return PARITY_EVEN; | 124 return LESS; |
| 125 case BELOW: |
| 126 return ABOVE_EQUAL; |
| 127 case BELOW_EQUAL: |
| 128 return ABOVE; |
| 129 case ABOVE: |
| 130 return BELOW_EQUAL; |
| 131 case ABOVE_EQUAL: |
| 132 return BELOW; |
| 133 case PARITY_EVEN: |
| 134 return PARITY_ODD; |
| 135 case PARITY_ODD: |
| 136 return PARITY_EVEN; |
126 default: | 137 default: |
127 UNIMPLEMENTED(); | 138 UNIMPLEMENTED(); |
128 return EQUAL; | 139 return EQUAL; |
129 } | 140 } |
130 } | 141 } |
131 | 142 |
132 | 143 |
133 // Detect pattern when one value is zero and another is a power of 2. | 144 // Detect pattern when one value is zero and another is a power of 2. |
134 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 145 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
135 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 146 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
(...skipping 11 matching lines...) Expand all Loading... |
147 | 158 |
148 | 159 |
149 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
150 ASSERT(locs()->out(0).reg() == RDX); | 161 ASSERT(locs()->out(0).reg() == RDX); |
151 | 162 |
152 // Clear upper part of the out register. We are going to use setcc on it | 163 // Clear upper part of the out register. We are going to use setcc on it |
153 // which is a byte move. | 164 // which is a byte move. |
154 __ xorq(RDX, RDX); | 165 __ xorq(RDX, RDX); |
155 | 166 |
156 // Emit comparison code. This must not overwrite the result register. | 167 // Emit comparison code. This must not overwrite the result register. |
157 BranchLabels labels = { NULL, NULL, NULL }; | 168 BranchLabels labels = {NULL, NULL, NULL}; |
158 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
159 | 170 |
160 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
161 | 172 |
162 intptr_t true_value = if_true_; | 173 intptr_t true_value = if_true_; |
163 intptr_t false_value = if_false_; | 174 intptr_t false_value = if_false_; |
164 | 175 |
165 if (is_power_of_two_kind) { | 176 if (is_power_of_two_kind) { |
166 if (true_value == 0) { | 177 if (true_value == 0) { |
167 // We need to have zero in RDX on true_condition. | 178 // We need to have zero in RDX on true_condition. |
(...skipping 11 matching lines...) Expand all Loading... |
179 } | 190 } |
180 | 191 |
181 __ setcc(true_condition, DL); | 192 __ setcc(true_condition, DL); |
182 | 193 |
183 if (is_power_of_two_kind) { | 194 if (is_power_of_two_kind) { |
184 const intptr_t shift = | 195 const intptr_t shift = |
185 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 196 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
186 __ shlq(RDX, Immediate(shift + kSmiTagSize)); | 197 __ shlq(RDX, Immediate(shift + kSmiTagSize)); |
187 } else { | 198 } else { |
188 __ decq(RDX); | 199 __ decq(RDX); |
189 __ AndImmediate(RDX, | 200 __ AndImmediate( |
190 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 201 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
191 if (false_value != 0) { | 202 if (false_value != 0) { |
192 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); | 203 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); |
193 } | 204 } |
194 } | 205 } |
195 } | 206 } |
196 | 207 |
197 | 208 |
198 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 209 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
199 bool opt) const { | 210 bool opt) const { |
200 const intptr_t kNumInputs = 0; | 211 const intptr_t kNumInputs = 0; |
201 const intptr_t stack_index = (local().index() < 0) | 212 const intptr_t stack_index = (local().index() < 0) |
202 ? kFirstLocalSlotFromFp - local().index() | 213 ? kFirstLocalSlotFromFp - local().index() |
203 : kParamEndSlotFromFp - local().index(); | 214 : kParamEndSlotFromFp - local().index(); |
204 return LocationSummary::Make(zone, | 215 return LocationSummary::Make(zone, kNumInputs, |
205 kNumInputs, | |
206 Location::StackSlot(stack_index), | 216 Location::StackSlot(stack_index), |
207 LocationSummary::kNoCall); | 217 LocationSummary::kNoCall); |
208 } | 218 } |
209 | 219 |
210 | 220 |
211 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 221 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
212 ASSERT(!compiler->is_optimizing()); | 222 ASSERT(!compiler->is_optimizing()); |
213 // Nothing to do. | 223 // Nothing to do. |
214 } | 224 } |
215 | 225 |
216 | 226 |
217 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 227 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
218 bool opt) const { | 228 bool opt) const { |
219 const intptr_t kNumInputs = 1; | 229 const intptr_t kNumInputs = 1; |
220 return LocationSummary::Make(zone, | 230 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
221 kNumInputs, | |
222 Location::SameAsFirstInput(), | |
223 LocationSummary::kNoCall); | 231 LocationSummary::kNoCall); |
224 } | 232 } |
225 | 233 |
226 | 234 |
227 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 235 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
228 Register value = locs()->in(0).reg(); | 236 Register value = locs()->in(0).reg(); |
229 Register result = locs()->out(0).reg(); | 237 Register result = locs()->out(0).reg(); |
230 ASSERT(result == value); // Assert that register assignment is correct. | 238 ASSERT(result == value); // Assert that register assignment is correct. |
231 __ movq(Address(RBP, local().index() * kWordSize), value); | 239 __ movq(Address(RBP, local().index() * kWordSize), value); |
232 } | 240 } |
233 | 241 |
234 | 242 |
235 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 243 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
236 bool opt) const { | 244 bool opt) const { |
237 const intptr_t kNumInputs = 0; | 245 const intptr_t kNumInputs = 0; |
238 return LocationSummary::Make(zone, | 246 return LocationSummary::Make(zone, kNumInputs, |
239 kNumInputs, | |
240 Assembler::IsSafe(value()) | 247 Assembler::IsSafe(value()) |
241 ? Location::Constant(this) | 248 ? Location::Constant(this) |
242 : Location::RequiresRegister(), | 249 : Location::RequiresRegister(), |
243 LocationSummary::kNoCall); | 250 LocationSummary::kNoCall); |
244 } | 251 } |
245 | 252 |
246 | 253 |
247 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 254 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
248 // The register allocator drops constant definitions that have no uses. | 255 // The register allocator drops constant definitions that have no uses. |
249 Location out = locs()->out(0); | 256 Location out = locs()->out(0); |
250 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 257 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
251 if (out.IsRegister()) { | 258 if (out.IsRegister()) { |
252 Register result = out.reg(); | 259 Register result = out.reg(); |
253 __ LoadObject(result, value()); | 260 __ LoadObject(result, value()); |
254 } | 261 } |
255 } | 262 } |
256 | 263 |
257 | 264 |
258 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 265 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
259 bool opt) const { | 266 bool opt) const { |
260 const intptr_t kNumInputs = 0; | 267 const intptr_t kNumInputs = 0; |
261 const intptr_t kNumTemps = 0; | 268 const intptr_t kNumTemps = 0; |
262 LocationSummary* locs = new(zone) LocationSummary( | 269 LocationSummary* locs = new (zone) |
263 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 270 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
264 switch (representation()) { | 271 switch (representation()) { |
265 case kUnboxedDouble: | 272 case kUnboxedDouble: |
266 locs->set_out(0, Location::RequiresFpuRegister()); | 273 locs->set_out(0, Location::RequiresFpuRegister()); |
267 break; | 274 break; |
268 case kUnboxedInt32: | 275 case kUnboxedInt32: |
269 locs->set_out(0, Location::RequiresRegister()); | 276 locs->set_out(0, Location::RequiresRegister()); |
270 break; | 277 break; |
271 default: | 278 default: |
272 UNREACHABLE(); | 279 UNREACHABLE(); |
273 break; | 280 break; |
(...skipping 24 matching lines...) Expand all Loading... |
298 UNREACHABLE(); | 305 UNREACHABLE(); |
299 } | 306 } |
300 } | 307 } |
301 } | 308 } |
302 | 309 |
303 | 310 |
304 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 311 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
305 bool opt) const { | 312 bool opt) const { |
306 const intptr_t kNumInputs = 2; | 313 const intptr_t kNumInputs = 2; |
307 const intptr_t kNumTemps = 0; | 314 const intptr_t kNumTemps = 0; |
308 LocationSummary* summary = new(zone) LocationSummary( | 315 LocationSummary* summary = new (zone) |
309 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 316 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
310 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 317 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
311 summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments. | 318 summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments. |
312 summary->set_out(0, Location::RegisterLocation(RAX)); | 319 summary->set_out(0, Location::RegisterLocation(RAX)); |
313 return summary; | 320 return summary; |
314 } | 321 } |
315 | 322 |
316 | 323 |
317 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 324 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
318 bool opt) const { | 325 bool opt) const { |
319 const intptr_t kNumInputs = 1; | 326 const intptr_t kNumInputs = 1; |
320 const intptr_t kNumTemps = 0; | 327 const intptr_t kNumTemps = 0; |
321 LocationSummary* locs = new(zone) LocationSummary( | 328 LocationSummary* locs = new (zone) |
322 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
323 locs->set_in(0, Location::RegisterLocation(RAX)); | 330 locs->set_in(0, Location::RegisterLocation(RAX)); |
324 locs->set_out(0, Location::RegisterLocation(RAX)); | 331 locs->set_out(0, Location::RegisterLocation(RAX)); |
325 return locs; | 332 return locs; |
326 } | 333 } |
327 | 334 |
328 | 335 |
329 static void EmitAssertBoolean(Register reg, | 336 static void EmitAssertBoolean(Register reg, |
330 TokenPosition token_pos, | 337 TokenPosition token_pos, |
331 intptr_t deopt_id, | 338 intptr_t deopt_id, |
332 LocationSummary* locs, | 339 LocationSummary* locs, |
333 FlowGraphCompiler* compiler) { | 340 FlowGraphCompiler* compiler) { |
334 // Check that the type of the value is allowed in conditional context. | 341 // Check that the type of the value is allowed in conditional context. |
335 // Call the runtime if the object is not bool::true or bool::false. | 342 // Call the runtime if the object is not bool::true or bool::false. |
336 ASSERT(locs->always_calls()); | 343 ASSERT(locs->always_calls()); |
337 Label done; | 344 Label done; |
338 | 345 |
339 if (Isolate::Current()->type_checks()) { | 346 if (Isolate::Current()->type_checks()) { |
340 __ CompareObject(reg, Bool::True()); | 347 __ CompareObject(reg, Bool::True()); |
341 __ j(EQUAL, &done, Assembler::kNearJump); | 348 __ j(EQUAL, &done, Assembler::kNearJump); |
342 __ CompareObject(reg, Bool::False()); | 349 __ CompareObject(reg, Bool::False()); |
343 __ j(EQUAL, &done, Assembler::kNearJump); | 350 __ j(EQUAL, &done, Assembler::kNearJump); |
344 } else { | 351 } else { |
345 ASSERT(Isolate::Current()->asserts()); | 352 ASSERT(Isolate::Current()->asserts()); |
346 __ CompareObject(reg, Object::null_instance()); | 353 __ CompareObject(reg, Object::null_instance()); |
347 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 354 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
348 } | 355 } |
349 | 356 |
350 __ pushq(reg); // Push the source object. | 357 __ pushq(reg); // Push the source object. |
351 compiler->GenerateRuntimeCall(token_pos, | 358 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
352 deopt_id, | 359 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
353 kNonBoolTypeErrorRuntimeEntry, | |
354 1, | |
355 locs); | |
356 // We should never return here. | 360 // We should never return here. |
357 __ int3(); | 361 __ int3(); |
358 __ Bind(&done); | 362 __ Bind(&done); |
359 } | 363 } |
360 | 364 |
361 | 365 |
362 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 366 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
363 Register obj = locs()->in(0).reg(); | 367 Register obj = locs()->in(0).reg(); |
364 Register result = locs()->out(0).reg(); | 368 Register result = locs()->out(0).reg(); |
365 | 369 |
366 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 370 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
367 ASSERT(obj == result); | 371 ASSERT(obj == result); |
368 } | 372 } |
369 | 373 |
370 | 374 |
371 static Condition TokenKindToIntCondition(Token::Kind kind) { | 375 static Condition TokenKindToIntCondition(Token::Kind kind) { |
372 switch (kind) { | 376 switch (kind) { |
373 case Token::kEQ: return EQUAL; | 377 case Token::kEQ: |
374 case Token::kNE: return NOT_EQUAL; | 378 return EQUAL; |
375 case Token::kLT: return LESS; | 379 case Token::kNE: |
376 case Token::kGT: return GREATER; | 380 return NOT_EQUAL; |
377 case Token::kLTE: return LESS_EQUAL; | 381 case Token::kLT: |
378 case Token::kGTE: return GREATER_EQUAL; | 382 return LESS; |
| 383 case Token::kGT: |
| 384 return GREATER; |
| 385 case Token::kLTE: |
| 386 return LESS_EQUAL; |
| 387 case Token::kGTE: |
| 388 return GREATER_EQUAL; |
379 default: | 389 default: |
380 UNREACHABLE(); | 390 UNREACHABLE(); |
381 return OVERFLOW; | 391 return OVERFLOW; |
382 } | 392 } |
383 } | 393 } |
384 | 394 |
385 | 395 |
386 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 396 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
387 bool opt) const { | 397 bool opt) const { |
388 const intptr_t kNumInputs = 2; | 398 const intptr_t kNumInputs = 2; |
389 if (operation_cid() == kMintCid) { | 399 if (operation_cid() == kMintCid) { |
390 const intptr_t kNumTemps = 0; | 400 const intptr_t kNumTemps = 0; |
391 LocationSummary* locs = new(zone) LocationSummary( | 401 LocationSummary* locs = new (zone) |
392 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 402 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
393 locs->set_in(0, Location::RequiresRegister()); | 403 locs->set_in(0, Location::RequiresRegister()); |
394 locs->set_in(1, Location::RequiresRegister()); | 404 locs->set_in(1, Location::RequiresRegister()); |
395 locs->set_out(0, Location::RequiresRegister()); | 405 locs->set_out(0, Location::RequiresRegister()); |
396 return locs; | 406 return locs; |
397 } | 407 } |
398 if (operation_cid() == kDoubleCid) { | 408 if (operation_cid() == kDoubleCid) { |
399 const intptr_t kNumTemps = 0; | 409 const intptr_t kNumTemps = 0; |
400 LocationSummary* locs = new(zone) LocationSummary( | 410 LocationSummary* locs = new (zone) |
401 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 411 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
402 locs->set_in(0, Location::RequiresFpuRegister()); | 412 locs->set_in(0, Location::RequiresFpuRegister()); |
403 locs->set_in(1, Location::RequiresFpuRegister()); | 413 locs->set_in(1, Location::RequiresFpuRegister()); |
404 locs->set_out(0, Location::RequiresRegister()); | 414 locs->set_out(0, Location::RequiresRegister()); |
405 return locs; | 415 return locs; |
406 } | 416 } |
407 if (operation_cid() == kSmiCid) { | 417 if (operation_cid() == kSmiCid) { |
408 const intptr_t kNumTemps = 0; | 418 const intptr_t kNumTemps = 0; |
409 LocationSummary* locs = new(zone) LocationSummary( | 419 LocationSummary* locs = new (zone) |
410 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 420 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
411 locs->set_in(0, Location::RegisterOrConstant(left())); | 421 locs->set_in(0, Location::RegisterOrConstant(left())); |
412 // Only one input can be a constant operand. The case of two constant | 422 // Only one input can be a constant operand. The case of two constant |
413 // operands should be handled by constant propagation. | 423 // operands should be handled by constant propagation. |
414 // Only right can be a stack slot. | 424 // Only right can be a stack slot. |
415 locs->set_in(1, locs->in(0).IsConstant() | 425 locs->set_in(1, locs->in(0).IsConstant() |
416 ? Location::RequiresRegister() | 426 ? Location::RequiresRegister() |
417 : Location::RegisterOrConstant(right())); | 427 : Location::RegisterOrConstant(right())); |
418 locs->set_out(0, Location::RequiresRegister()); | 428 locs->set_out(0, Location::RequiresRegister()); |
419 return locs; | 429 return locs; |
420 } | 430 } |
(...skipping 16 matching lines...) Expand all Loading... |
437 } else { | 447 } else { |
438 __ j(ZERO, value_is_smi); | 448 __ j(ZERO, value_is_smi); |
439 } | 449 } |
440 __ LoadClassId(value_cid_reg, value_reg); | 450 __ LoadClassId(value_cid_reg, value_reg); |
441 __ Bind(&done); | 451 __ Bind(&done); |
442 } | 452 } |
443 | 453 |
444 | 454 |
445 static Condition FlipCondition(Condition condition) { | 455 static Condition FlipCondition(Condition condition) { |
446 switch (condition) { | 456 switch (condition) { |
447 case EQUAL: return EQUAL; | 457 case EQUAL: |
448 case NOT_EQUAL: return NOT_EQUAL; | 458 return EQUAL; |
449 case LESS: return GREATER; | 459 case NOT_EQUAL: |
450 case LESS_EQUAL: return GREATER_EQUAL; | 460 return NOT_EQUAL; |
451 case GREATER: return LESS; | 461 case LESS: |
452 case GREATER_EQUAL: return LESS_EQUAL; | 462 return GREATER; |
453 case BELOW: return ABOVE; | 463 case LESS_EQUAL: |
454 case BELOW_EQUAL: return ABOVE_EQUAL; | 464 return GREATER_EQUAL; |
455 case ABOVE: return BELOW; | 465 case GREATER: |
456 case ABOVE_EQUAL: return BELOW_EQUAL; | 466 return LESS; |
| 467 case GREATER_EQUAL: |
| 468 return LESS_EQUAL; |
| 469 case BELOW: |
| 470 return ABOVE; |
| 471 case BELOW_EQUAL: |
| 472 return ABOVE_EQUAL; |
| 473 case ABOVE: |
| 474 return BELOW; |
| 475 case ABOVE_EQUAL: |
| 476 return BELOW_EQUAL; |
457 default: | 477 default: |
458 UNIMPLEMENTED(); | 478 UNIMPLEMENTED(); |
459 return EQUAL; | 479 return EQUAL; |
460 } | 480 } |
461 } | 481 } |
462 | 482 |
463 | 483 |
464 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 484 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
465 Condition true_condition, | 485 Condition true_condition, |
466 BranchLabels labels) { | 486 BranchLabels labels) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 518 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
499 } else { | 519 } else { |
500 __ cmpq(left.reg(), right.reg()); | 520 __ cmpq(left.reg(), right.reg()); |
501 } | 521 } |
502 return true_condition; | 522 return true_condition; |
503 } | 523 } |
504 | 524 |
505 | 525 |
506 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 526 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
507 switch (kind) { | 527 switch (kind) { |
508 case Token::kEQ: return EQUAL; | 528 case Token::kEQ: |
509 case Token::kNE: return NOT_EQUAL; | 529 return EQUAL; |
510 case Token::kLT: return BELOW; | 530 case Token::kNE: |
511 case Token::kGT: return ABOVE; | 531 return NOT_EQUAL; |
512 case Token::kLTE: return BELOW_EQUAL; | 532 case Token::kLT: |
513 case Token::kGTE: return ABOVE_EQUAL; | 533 return BELOW; |
| 534 case Token::kGT: |
| 535 return ABOVE; |
| 536 case Token::kLTE: |
| 537 return BELOW_EQUAL; |
| 538 case Token::kGTE: |
| 539 return ABOVE_EQUAL; |
514 default: | 540 default: |
515 UNREACHABLE(); | 541 UNREACHABLE(); |
516 return OVERFLOW; | 542 return OVERFLOW; |
517 } | 543 } |
518 } | 544 } |
519 | 545 |
520 | 546 |
521 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 547 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
522 const LocationSummary& locs, | 548 const LocationSummary& locs, |
523 Token::Kind kind, | 549 Token::Kind kind, |
524 BranchLabels labels) { | 550 BranchLabels labels) { |
525 XmmRegister left = locs.in(0).fpu_reg(); | 551 XmmRegister left = locs.in(0).fpu_reg(); |
526 XmmRegister right = locs.in(1).fpu_reg(); | 552 XmmRegister right = locs.in(1).fpu_reg(); |
527 | 553 |
528 __ comisd(left, right); | 554 __ comisd(left, right); |
529 | 555 |
530 Condition true_condition = TokenKindToDoubleCondition(kind); | 556 Condition true_condition = TokenKindToDoubleCondition(kind); |
531 Label* nan_result = (true_condition == NOT_EQUAL) | 557 Label* nan_result = |
532 ? labels.true_label : labels.false_label; | 558 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
533 __ j(PARITY_EVEN, nan_result); | 559 __ j(PARITY_EVEN, nan_result); |
534 return true_condition; | 560 return true_condition; |
535 } | 561 } |
536 | 562 |
537 | 563 |
538 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 564 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
539 BranchLabels labels) { | 565 BranchLabels labels) { |
540 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 566 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
541 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 567 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
542 } else { | 568 } else { |
543 ASSERT(operation_cid() == kDoubleCid); | 569 ASSERT(operation_cid() == kDoubleCid); |
544 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 570 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
545 } | 571 } |
546 } | 572 } |
547 | 573 |
548 | 574 |
549 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 575 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
550 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 576 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
551 | 577 |
552 Label is_true, is_false; | 578 Label is_true, is_false; |
553 BranchLabels labels = { &is_true, &is_false, &is_false }; | 579 BranchLabels labels = {&is_true, &is_false, &is_false}; |
554 Condition true_condition = EmitComparisonCode(compiler, labels); | 580 Condition true_condition = EmitComparisonCode(compiler, labels); |
555 EmitBranchOnCondition(compiler, true_condition, labels); | 581 EmitBranchOnCondition(compiler, true_condition, labels); |
556 | 582 |
557 Register result = locs()->out(0).reg(); | 583 Register result = locs()->out(0).reg(); |
558 Label done; | 584 Label done; |
559 __ Bind(&is_false); | 585 __ Bind(&is_false); |
560 __ LoadObject(result, Bool::False()); | 586 __ LoadObject(result, Bool::False()); |
561 __ jmp(&done); | 587 __ jmp(&done); |
562 __ Bind(&is_true); | 588 __ Bind(&is_true); |
563 __ LoadObject(result, Bool::True()); | 589 __ LoadObject(result, Bool::True()); |
564 __ Bind(&done); | 590 __ Bind(&done); |
565 } | 591 } |
566 | 592 |
567 | 593 |
568 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 594 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
569 BranchInstr* branch) { | 595 BranchInstr* branch) { |
570 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 596 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
571 | 597 |
572 BranchLabels labels = compiler->CreateBranchLabels(branch); | 598 BranchLabels labels = compiler->CreateBranchLabels(branch); |
573 Condition true_condition = EmitComparisonCode(compiler, labels); | 599 Condition true_condition = EmitComparisonCode(compiler, labels); |
574 EmitBranchOnCondition(compiler, true_condition, labels); | 600 EmitBranchOnCondition(compiler, true_condition, labels); |
575 } | 601 } |
576 | 602 |
577 | 603 |
578 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 604 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
579 bool opt) const { | |
580 const intptr_t kNumInputs = 2; | 605 const intptr_t kNumInputs = 2; |
581 const intptr_t kNumTemps = 0; | 606 const intptr_t kNumTemps = 0; |
582 LocationSummary* locs = new(zone) LocationSummary( | 607 LocationSummary* locs = new (zone) |
583 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 608 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
584 locs->set_in(0, Location::RequiresRegister()); | 609 locs->set_in(0, Location::RequiresRegister()); |
585 // Only one input can be a constant operand. The case of two constant | 610 // Only one input can be a constant operand. The case of two constant |
586 // operands should be handled by constant propagation. | 611 // operands should be handled by constant propagation. |
587 locs->set_in(1, Location::RegisterOrConstant(right())); | 612 locs->set_in(1, Location::RegisterOrConstant(right())); |
588 return locs; | 613 return locs; |
589 } | 614 } |
590 | 615 |
591 | 616 |
592 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 617 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
593 BranchLabels labels) { | 618 BranchLabels labels) { |
594 Register left_reg = locs()->in(0).reg(); | 619 Register left_reg = locs()->in(0).reg(); |
595 Location right = locs()->in(1); | 620 Location right = locs()->in(1); |
596 if (right.IsConstant()) { | 621 if (right.IsConstant()) { |
597 ASSERT(right.constant().IsSmi()); | 622 ASSERT(right.constant().IsSmi()); |
598 const int64_t imm = | 623 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
599 reinterpret_cast<int64_t>(right.constant().raw()); | |
600 __ TestImmediate(left_reg, Immediate(imm)); | 624 __ TestImmediate(left_reg, Immediate(imm)); |
601 } else { | 625 } else { |
602 __ testq(left_reg, right.reg()); | 626 __ testq(left_reg, right.reg()); |
603 } | 627 } |
604 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 628 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
605 return true_condition; | 629 return true_condition; |
606 } | 630 } |
607 | 631 |
608 | 632 |
609 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 633 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
610 // Never emitted outside of the BranchInstr. | 634 // Never emitted outside of the BranchInstr. |
611 UNREACHABLE(); | 635 UNREACHABLE(); |
612 } | 636 } |
613 | 637 |
614 | 638 |
615 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 639 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
616 BranchInstr* branch) { | 640 BranchInstr* branch) { |
617 BranchLabels labels = compiler->CreateBranchLabels(branch); | 641 BranchLabels labels = compiler->CreateBranchLabels(branch); |
618 Condition true_condition = EmitComparisonCode(compiler, labels); | 642 Condition true_condition = EmitComparisonCode(compiler, labels); |
619 EmitBranchOnCondition(compiler, true_condition, labels); | 643 EmitBranchOnCondition(compiler, true_condition, labels); |
620 } | 644 } |
621 | 645 |
622 | 646 |
623 | |
624 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 647 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
625 bool opt) const { | 648 bool opt) const { |
626 const intptr_t kNumInputs = 1; | 649 const intptr_t kNumInputs = 1; |
627 const intptr_t kNumTemps = 1; | 650 const intptr_t kNumTemps = 1; |
628 LocationSummary* locs = new(zone) LocationSummary( | 651 LocationSummary* locs = new (zone) |
629 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 652 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
630 locs->set_in(0, Location::RequiresRegister()); | 653 locs->set_in(0, Location::RequiresRegister()); |
631 locs->set_temp(0, Location::RequiresRegister()); | 654 locs->set_temp(0, Location::RequiresRegister()); |
632 locs->set_out(0, Location::RequiresRegister()); | 655 locs->set_out(0, Location::RequiresRegister()); |
633 return locs; | 656 return locs; |
634 } | 657 } |
635 | 658 |
636 | 659 |
637 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 660 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
638 BranchLabels labels) { | 661 BranchLabels labels) { |
639 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 662 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
640 Register val_reg = locs()->in(0).reg(); | 663 Register val_reg = locs()->in(0).reg(); |
641 Register cid_reg = locs()->temp(0).reg(); | 664 Register cid_reg = locs()->temp(0).reg(); |
642 | 665 |
643 Label* deopt = CanDeoptimize() | 666 Label* deopt = |
644 ? compiler->AddDeoptStub(deopt_id(), | 667 CanDeoptimize() |
645 ICData::kDeoptTestCids, | 668 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
646 licm_hoisted_ ? ICData::kHoisted : 0) | 669 licm_hoisted_ ? ICData::kHoisted : 0) |
647 : NULL; | 670 : NULL; |
648 | 671 |
649 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 672 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
650 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 673 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
651 ASSERT(data[0] == kSmiCid); | 674 ASSERT(data[0] == kSmiCid); |
652 bool result = data[1] == true_result; | 675 bool result = data[1] == true_result; |
653 __ testq(val_reg, Immediate(kSmiTagMask)); | 676 __ testq(val_reg, Immediate(kSmiTagMask)); |
654 __ j(ZERO, result ? labels.true_label : labels.false_label); | 677 __ j(ZERO, result ? labels.true_label : labels.false_label); |
655 __ LoadClassId(cid_reg, val_reg); | 678 __ LoadClassId(cid_reg, val_reg); |
656 for (intptr_t i = 2; i < data.length(); i += 2) { | 679 for (intptr_t i = 2; i < data.length(); i += 2) { |
657 const intptr_t test_cid = data[i]; | 680 const intptr_t test_cid = data[i]; |
658 ASSERT(test_cid != kSmiCid); | 681 ASSERT(test_cid != kSmiCid); |
659 result = data[i + 1] == true_result; | 682 result = data[i + 1] == true_result; |
660 __ cmpq(cid_reg, Immediate(test_cid)); | 683 __ cmpq(cid_reg, Immediate(test_cid)); |
661 __ j(EQUAL, result ? labels.true_label : labels.false_label); | 684 __ j(EQUAL, result ? labels.true_label : labels.false_label); |
662 } | 685 } |
663 // No match found, deoptimize or false. | 686 // No match found, deoptimize or false. |
664 if (deopt == NULL) { | 687 if (deopt == NULL) { |
665 Label* target = result ? labels.false_label : labels.true_label; | 688 Label* target = result ? labels.false_label : labels.true_label; |
666 if (target != labels.fall_through) { | 689 if (target != labels.fall_through) { |
667 __ jmp(target); | 690 __ jmp(target); |
668 } | 691 } |
669 } else { | 692 } else { |
670 __ jmp(deopt); | 693 __ jmp(deopt); |
671 } | 694 } |
672 // Dummy result as the last instruction is a jump, any conditional | 695 // Dummy result as the last instruction is a jump, any conditional |
673 // branch using the result will therefore be skipped. | 696 // branch using the result will therefore be skipped. |
674 return ZERO; | 697 return ZERO; |
675 } | 698 } |
676 | 699 |
677 | 700 |
678 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 701 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
679 BranchInstr* branch) { | 702 BranchInstr* branch) { |
680 BranchLabels labels = compiler->CreateBranchLabels(branch); | 703 BranchLabels labels = compiler->CreateBranchLabels(branch); |
681 EmitComparisonCode(compiler, labels); | 704 EmitComparisonCode(compiler, labels); |
682 } | 705 } |
683 | 706 |
684 | 707 |
685 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 708 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
686 Register result_reg = locs()->out(0).reg(); | 709 Register result_reg = locs()->out(0).reg(); |
687 Label is_true, is_false, done; | 710 Label is_true, is_false, done; |
688 BranchLabels labels = { &is_true, &is_false, &is_false }; | 711 BranchLabels labels = {&is_true, &is_false, &is_false}; |
689 EmitComparisonCode(compiler, labels); | 712 EmitComparisonCode(compiler, labels); |
690 __ Bind(&is_false); | 713 __ Bind(&is_false); |
691 __ LoadObject(result_reg, Bool::False()); | 714 __ LoadObject(result_reg, Bool::False()); |
692 __ jmp(&done, Assembler::kNearJump); | 715 __ jmp(&done, Assembler::kNearJump); |
693 __ Bind(&is_true); | 716 __ Bind(&is_true); |
694 __ LoadObject(result_reg, Bool::True()); | 717 __ LoadObject(result_reg, Bool::True()); |
695 __ Bind(&done); | 718 __ Bind(&done); |
696 } | 719 } |
697 | 720 |
698 | 721 |
699 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 722 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
700 bool opt) const { | 723 bool opt) const { |
701 const intptr_t kNumInputs = 2; | 724 const intptr_t kNumInputs = 2; |
702 const intptr_t kNumTemps = 0; | 725 const intptr_t kNumTemps = 0; |
703 if (operation_cid() == kDoubleCid) { | 726 if (operation_cid() == kDoubleCid) { |
704 LocationSummary* summary = new(zone) LocationSummary( | 727 LocationSummary* summary = new (zone) |
705 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 728 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
706 summary->set_in(0, Location::RequiresFpuRegister()); | 729 summary->set_in(0, Location::RequiresFpuRegister()); |
707 summary->set_in(1, Location::RequiresFpuRegister()); | 730 summary->set_in(1, Location::RequiresFpuRegister()); |
708 summary->set_out(0, Location::RequiresRegister()); | 731 summary->set_out(0, Location::RequiresRegister()); |
709 return summary; | 732 return summary; |
710 } else if (operation_cid() == kMintCid) { | 733 } else if (operation_cid() == kMintCid) { |
711 LocationSummary* summary = new(zone) LocationSummary( | 734 LocationSummary* summary = new (zone) |
712 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 735 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
713 summary->set_in(0, Location::RequiresRegister()); | 736 summary->set_in(0, Location::RequiresRegister()); |
714 summary->set_in(1, Location::RequiresRegister()); | 737 summary->set_in(1, Location::RequiresRegister()); |
715 summary->set_out(0, Location::RequiresRegister()); | 738 summary->set_out(0, Location::RequiresRegister()); |
716 return summary; | 739 return summary; |
717 } | 740 } |
718 ASSERT(operation_cid() == kSmiCid); | 741 ASSERT(operation_cid() == kSmiCid); |
719 LocationSummary* summary = new(zone) LocationSummary( | 742 LocationSummary* summary = new (zone) |
720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 743 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
721 summary->set_in(0, Location::RegisterOrConstant(left())); | 744 summary->set_in(0, Location::RegisterOrConstant(left())); |
722 // Only one input can be a constant operand. The case of two constant | 745 // Only one input can be a constant operand. The case of two constant |
723 // operands should be handled by constant propagation. | 746 // operands should be handled by constant propagation. |
724 summary->set_in(1, summary->in(0).IsConstant() | 747 summary->set_in(1, summary->in(0).IsConstant() |
725 ? Location::RequiresRegister() | 748 ? Location::RequiresRegister() |
726 : Location::RegisterOrConstant(right())); | 749 : Location::RegisterOrConstant(right())); |
727 summary->set_out(0, Location::RequiresRegister()); | 750 summary->set_out(0, Location::RequiresRegister()); |
728 return summary; | 751 return summary; |
729 } | 752 } |
730 | 753 |
731 | 754 |
732 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 755 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
733 BranchLabels labels) { | 756 BranchLabels labels) { |
734 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 757 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
735 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 758 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
736 } else { | 759 } else { |
737 ASSERT(operation_cid() == kDoubleCid); | 760 ASSERT(operation_cid() == kDoubleCid); |
738 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 761 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
739 } | 762 } |
740 } | 763 } |
741 | 764 |
742 | 765 |
743 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 766 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
744 Label is_true, is_false; | 767 Label is_true, is_false; |
745 BranchLabels labels = { &is_true, &is_false, &is_false }; | 768 BranchLabels labels = {&is_true, &is_false, &is_false}; |
746 Condition true_condition = EmitComparisonCode(compiler, labels); | 769 Condition true_condition = EmitComparisonCode(compiler, labels); |
747 EmitBranchOnCondition(compiler, true_condition, labels); | 770 EmitBranchOnCondition(compiler, true_condition, labels); |
748 | 771 |
749 Register result = locs()->out(0).reg(); | 772 Register result = locs()->out(0).reg(); |
750 Label done; | 773 Label done; |
751 __ Bind(&is_false); | 774 __ Bind(&is_false); |
752 __ LoadObject(result, Bool::False()); | 775 __ LoadObject(result, Bool::False()); |
753 __ jmp(&done); | 776 __ jmp(&done); |
754 __ Bind(&is_true); | 777 __ Bind(&is_true); |
755 __ LoadObject(result, Bool::True()); | 778 __ LoadObject(result, Bool::True()); |
(...skipping 17 matching lines...) Expand all Loading... |
773 | 796 |
774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 797 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
775 SetupNative(); | 798 SetupNative(); |
776 Register result = locs()->out(0).reg(); | 799 Register result = locs()->out(0).reg(); |
777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 800 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
778 | 801 |
779 // Push the result place holder initialized to NULL. | 802 // Push the result place holder initialized to NULL. |
780 __ PushObject(Object::null_object()); | 803 __ PushObject(Object::null_object()); |
781 // Pass a pointer to the first argument in RAX. | 804 // Pass a pointer to the first argument in RAX. |
782 if (!function().HasOptionalParameters()) { | 805 if (!function().HasOptionalParameters()) { |
783 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + | 806 __ leaq(RAX, |
784 function().NumParameters()) * kWordSize)); | 807 Address(RBP, (kParamEndSlotFromFp + function().NumParameters()) * |
| 808 kWordSize)); |
785 } else { | 809 } else { |
786 __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 810 __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
787 } | 811 } |
788 __ LoadImmediate(R10, Immediate(argc_tag)); | 812 __ LoadImmediate(R10, Immediate(argc_tag)); |
789 const StubEntry* stub_entry; | 813 const StubEntry* stub_entry; |
790 if (link_lazily()) { | 814 if (link_lazily()) { |
791 stub_entry = StubCode::CallBootstrapCFunction_entry(); | 815 stub_entry = StubCode::CallBootstrapCFunction_entry(); |
792 ExternalLabel label(NativeEntry::LinkNativeCallEntry()); | 816 ExternalLabel label(NativeEntry::LinkNativeCallEntry()); |
793 __ LoadNativeEntry(RBX, &label, kPatchable); | 817 __ LoadNativeEntry(RBX, &label, kPatchable); |
794 } else { | 818 } else { |
795 stub_entry = (is_bootstrap_native()) ? | 819 stub_entry = (is_bootstrap_native()) |
796 StubCode::CallBootstrapCFunction_entry() : | 820 ? StubCode::CallBootstrapCFunction_entry() |
797 StubCode::CallNativeCFunction_entry(); | 821 : StubCode::CallNativeCFunction_entry(); |
798 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 822 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
799 __ LoadNativeEntry(RBX, &label, kNotPatchable); | 823 __ LoadNativeEntry(RBX, &label, kNotPatchable); |
800 } | 824 } |
801 compiler->GenerateCall(token_pos(), | 825 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
802 *stub_entry, | |
803 RawPcDescriptors::kOther, | |
804 locs()); | 826 locs()); |
805 __ popq(result); | 827 __ popq(result); |
806 } | 828 } |
807 | 829 |
808 | 830 |
809 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { | 831 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { |
810 if (!index->definition()->IsConstant()) return false; | 832 if (!index->definition()->IsConstant()) return false; |
811 const Object& constant = index->definition()->AsConstant()->value(); | 833 const Object& constant = index->definition()->AsConstant()->value(); |
812 if (!constant.IsSmi()) return false; | 834 if (!constant.IsSmi()) return false; |
813 const Smi& smi_const = Smi::Cast(constant); | 835 const Smi& smi_const = Smi::Cast(constant); |
814 const intptr_t scale = Instance::ElementSizeFor(cid); | 836 const intptr_t scale = Instance::ElementSizeFor(cid); |
815 const intptr_t data_offset = Instance::DataOffsetFor(cid); | 837 const intptr_t data_offset = Instance::DataOffsetFor(cid); |
816 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; | 838 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; |
817 return Utils::IsInt(32, disp); | 839 return Utils::IsInt(32, disp); |
818 } | 840 } |
819 | 841 |
820 | 842 |
821 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 843 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
822 Zone* zone, bool opt) const { | 844 Zone* zone, |
| 845 bool opt) const { |
823 const intptr_t kNumInputs = 1; | 846 const intptr_t kNumInputs = 1; |
824 // TODO(fschneider): Allow immediate operands for the char code. | 847 // TODO(fschneider): Allow immediate operands for the char code. |
825 return LocationSummary::Make(zone, | 848 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
826 kNumInputs, | |
827 Location::RequiresRegister(), | |
828 LocationSummary::kNoCall); | 849 LocationSummary::kNoCall); |
829 } | 850 } |
830 | 851 |
831 | 852 |
832 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 853 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
833 FlowGraphCompiler* compiler) { | 854 FlowGraphCompiler* compiler) { |
834 ASSERT(compiler->is_optimizing()); | 855 ASSERT(compiler->is_optimizing()); |
835 Register char_code = locs()->in(0).reg(); | 856 Register char_code = locs()->in(0).reg(); |
836 Register result = locs()->out(0).reg(); | 857 Register result = locs()->out(0).reg(); |
837 | 858 |
838 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); | 859 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); |
839 __ movq(result, Address(result, | 860 __ movq(result, Address(result, char_code, |
840 char_code, | |
841 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 861 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
842 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 862 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
843 } | 863 } |
844 | 864 |
845 | 865 |
846 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 866 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
847 bool opt) const { | 867 bool opt) const { |
848 const intptr_t kNumInputs = 1; | 868 const intptr_t kNumInputs = 1; |
849 return LocationSummary::Make(zone, | 869 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
850 kNumInputs, | |
851 Location::RequiresRegister(), | |
852 LocationSummary::kNoCall); | 870 LocationSummary::kNoCall); |
853 } | 871 } |
854 | 872 |
855 | 873 |
856 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 874 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
857 ASSERT(cid_ == kOneByteStringCid); | 875 ASSERT(cid_ == kOneByteStringCid); |
858 Register str = locs()->in(0).reg(); | 876 Register str = locs()->in(0).reg(); |
859 Register result = locs()->out(0).reg(); | 877 Register result = locs()->out(0).reg(); |
860 Label is_one, done; | 878 Label is_one, done; |
861 __ movq(result, FieldAddress(str, String::length_offset())); | 879 __ movq(result, FieldAddress(str, String::length_offset())); |
862 __ cmpq(result, Immediate(Smi::RawValue(1))); | 880 __ cmpq(result, Immediate(Smi::RawValue(1))); |
863 __ j(EQUAL, &is_one, Assembler::kNearJump); | 881 __ j(EQUAL, &is_one, Assembler::kNearJump); |
864 __ movq(result, Immediate(Smi::RawValue(-1))); | 882 __ movq(result, Immediate(Smi::RawValue(-1))); |
865 __ jmp(&done); | 883 __ jmp(&done); |
866 __ Bind(&is_one); | 884 __ Bind(&is_one); |
867 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 885 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
868 __ SmiTag(result); | 886 __ SmiTag(result); |
869 __ Bind(&done); | 887 __ Bind(&done); |
870 } | 888 } |
871 | 889 |
872 | 890 |
873 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 891 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
874 bool opt) const { | 892 bool opt) const { |
875 const intptr_t kNumInputs = 1; | 893 const intptr_t kNumInputs = 1; |
876 const intptr_t kNumTemps = 0; | 894 const intptr_t kNumTemps = 0; |
877 LocationSummary* summary = new(zone) LocationSummary( | 895 LocationSummary* summary = new (zone) |
878 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
879 summary->set_in(0, Location::RegisterLocation(RAX)); | 897 summary->set_in(0, Location::RegisterLocation(RAX)); |
880 summary->set_out(0, Location::RegisterLocation(RAX)); | 898 summary->set_out(0, Location::RegisterLocation(RAX)); |
881 return summary; | 899 return summary; |
882 } | 900 } |
883 | 901 |
884 | 902 |
885 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 903 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
886 Register array = locs()->in(0).reg(); | 904 Register array = locs()->in(0).reg(); |
887 __ pushq(array); | 905 __ pushq(array); |
888 const int kNumberOfArguments = 1; | 906 const int kNumberOfArguments = 1; |
889 const Array& kNoArgumentNames = Object::null_array(); | 907 const Array& kNoArgumentNames = Object::null_array(); |
890 compiler->GenerateStaticCall(deopt_id(), | 908 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
891 token_pos(), | 909 kNumberOfArguments, kNoArgumentNames, locs(), |
892 CallFunction(), | |
893 kNumberOfArguments, | |
894 kNoArgumentNames, | |
895 locs(), | |
896 ICData::Handle()); | 910 ICData::Handle()); |
897 ASSERT(locs()->out(0).reg() == RAX); | 911 ASSERT(locs()->out(0).reg() == RAX); |
898 } | 912 } |
899 | 913 |
900 | 914 |
901 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 915 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
902 bool opt) const { | 916 bool opt) const { |
903 const intptr_t kNumInputs = 1; | 917 const intptr_t kNumInputs = 1; |
904 return LocationSummary::Make(zone, | 918 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
905 kNumInputs, | |
906 Location::RequiresRegister(), | |
907 LocationSummary::kNoCall); | 919 LocationSummary::kNoCall); |
908 } | 920 } |
909 | 921 |
910 | 922 |
911 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
912 Register obj = locs()->in(0).reg(); | 924 Register obj = locs()->in(0).reg(); |
913 Register result = locs()->out(0).reg(); | 925 Register result = locs()->out(0).reg(); |
914 if (object()->definition()->representation() == kUntagged) { | 926 if (object()->definition()->representation() == kUntagged) { |
915 __ movq(result, Address(obj, offset())); | 927 __ movq(result, Address(obj, offset())); |
916 } else { | 928 } else { |
917 ASSERT(object()->definition()->representation() == kTagged); | 929 ASSERT(object()->definition()->representation() == kTagged); |
918 __ movq(result, FieldAddress(obj, offset())); | 930 __ movq(result, FieldAddress(obj, offset())); |
919 } | 931 } |
920 } | 932 } |
921 | 933 |
922 | 934 |
923 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 935 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
924 bool opt) const { | 936 bool opt) const { |
925 const intptr_t kNumInputs = 1; | 937 const intptr_t kNumInputs = 1; |
926 return LocationSummary::Make(zone, | 938 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
927 kNumInputs, | |
928 Location::RequiresRegister(), | |
929 LocationSummary::kNoCall); | 939 LocationSummary::kNoCall); |
930 } | 940 } |
931 | 941 |
932 | 942 |
933 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 943 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
934 const Register object = locs()->in(0).reg(); | 944 const Register object = locs()->in(0).reg(); |
935 const Register result = locs()->out(0).reg(); | 945 const Register result = locs()->out(0).reg(); |
936 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 946 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
937 if (CompileType::Smi().IsAssignableTo(value_type) || | 947 if (CompileType::Smi().IsAssignableTo(value_type) || |
938 value_type.IsTypeParameter()) { | 948 value_type.IsTypeParameter()) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 UNIMPLEMENTED(); | 1041 UNIMPLEMENTED(); |
1032 return kTagged; | 1042 return kTagged; |
1033 } | 1043 } |
1034 } | 1044 } |
1035 | 1045 |
1036 | 1046 |
1037 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1047 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1038 bool opt) const { | 1048 bool opt) const { |
1039 const intptr_t kNumInputs = 2; | 1049 const intptr_t kNumInputs = 2; |
1040 const intptr_t kNumTemps = 0; | 1050 const intptr_t kNumTemps = 0; |
1041 LocationSummary* locs = new(zone) LocationSummary( | 1051 LocationSummary* locs = new (zone) |
1042 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1052 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1043 locs->set_in(0, Location::RequiresRegister()); | 1053 locs->set_in(0, Location::RequiresRegister()); |
1044 // The smi index is either untagged (element size == 1), or it is left smi | 1054 // The smi index is either untagged (element size == 1), or it is left smi |
1045 // tagged (for all element sizes > 1). | 1055 // tagged (for all element sizes > 1). |
1046 if (index_scale() == 1) { | 1056 if (index_scale() == 1) { |
1047 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1057 locs->set_in(1, |
1048 ? Location::Constant(index()->definition()->AsConstant()) | 1058 CanBeImmediateIndex(index(), class_id()) |
1049 : Location::WritableRegister()); | 1059 ? Location::Constant(index()->definition()->AsConstant()) |
| 1060 : Location::WritableRegister()); |
1050 } else { | 1061 } else { |
1051 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1062 locs->set_in(1, |
1052 ? Location::Constant(index()->definition()->AsConstant()) | 1063 CanBeImmediateIndex(index(), class_id()) |
1053 : Location::RequiresRegister()); | 1064 ? Location::Constant(index()->definition()->AsConstant()) |
| 1065 : Location::RequiresRegister()); |
1054 } | 1066 } |
1055 if ((representation() == kUnboxedDouble) || | 1067 if ((representation() == kUnboxedDouble) || |
1056 (representation() == kUnboxedFloat32x4) || | 1068 (representation() == kUnboxedFloat32x4) || |
1057 (representation() == kUnboxedInt32x4) || | 1069 (representation() == kUnboxedInt32x4) || |
1058 (representation() == kUnboxedFloat64x2)) { | 1070 (representation() == kUnboxedFloat64x2)) { |
1059 locs->set_out(0, Location::RequiresFpuRegister()); | 1071 locs->set_out(0, Location::RequiresFpuRegister()); |
1060 } else { | 1072 } else { |
1061 locs->set_out(0, Location::RequiresRegister()); | 1073 locs->set_out(0, Location::RequiresRegister()); |
1062 } | 1074 } |
1063 return locs; | 1075 return locs; |
1064 } | 1076 } |
1065 | 1077 |
1066 | 1078 |
1067 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1079 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1068 // The array register points to the backing store for external arrays. | 1080 // The array register points to the backing store for external arrays. |
1069 const Register array = locs()->in(0).reg(); | 1081 const Register array = locs()->in(0).reg(); |
1070 const Location index = locs()->in(1); | 1082 const Location index = locs()->in(1); |
1071 | 1083 |
1072 Address element_address = index.IsRegister() | 1084 Address element_address = |
1073 ? Assembler::ElementAddressForRegIndex( | 1085 index.IsRegister() |
1074 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1086 ? Assembler::ElementAddressForRegIndex( |
1075 : Assembler::ElementAddressForIntIndex( | 1087 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1076 IsExternal(), class_id(), index_scale(), | 1088 : Assembler::ElementAddressForIntIndex( |
1077 array, Smi::Cast(index.constant()).Value()); | 1089 IsExternal(), class_id(), index_scale(), array, |
| 1090 Smi::Cast(index.constant()).Value()); |
1078 | 1091 |
1079 if ((representation() == kUnboxedDouble) || | 1092 if ((representation() == kUnboxedDouble) || |
1080 (representation() == kUnboxedFloat32x4) || | 1093 (representation() == kUnboxedFloat32x4) || |
1081 (representation() == kUnboxedInt32x4) || | 1094 (representation() == kUnboxedInt32x4) || |
1082 (representation() == kUnboxedFloat64x2)) { | 1095 (representation() == kUnboxedFloat64x2)) { |
1083 if ((index_scale() == 1) && index.IsRegister()) { | 1096 if ((index_scale() == 1) && index.IsRegister()) { |
1084 __ SmiUntag(index.reg()); | 1097 __ SmiUntag(index.reg()); |
1085 } | 1098 } |
1086 | 1099 |
1087 XmmRegister result = locs()->out(0).fpu_reg(); | 1100 XmmRegister result = locs()->out(0).fpu_reg(); |
1088 if (class_id() == kTypedDataFloat32ArrayCid) { | 1101 if (class_id() == kTypedDataFloat32ArrayCid) { |
1089 // Load single precision float. | 1102 // Load single precision float. |
1090 __ movss(result, element_address); | 1103 __ movss(result, element_address); |
1091 } else if (class_id() == kTypedDataFloat64ArrayCid) { | 1104 } else if (class_id() == kTypedDataFloat64ArrayCid) { |
1092 __ movsd(result, element_address); | 1105 __ movsd(result, element_address); |
1093 } else { | 1106 } else { |
1094 ASSERT((class_id() == kTypedDataInt32x4ArrayCid) || | 1107 ASSERT((class_id() == kTypedDataInt32x4ArrayCid) || |
1095 (class_id() == kTypedDataFloat32x4ArrayCid) || | 1108 (class_id() == kTypedDataFloat32x4ArrayCid) || |
1096 (class_id() == kTypedDataFloat64x2ArrayCid)); | 1109 (class_id() == kTypedDataFloat64x2ArrayCid)); |
1097 __ movups(result, element_address); | 1110 __ movups(result, element_address); |
1098 } | 1111 } |
1099 return; | 1112 return; |
1100 } | 1113 } |
1101 | 1114 |
1102 if ((representation() == kUnboxedUint32) || | 1115 if ((representation() == kUnboxedUint32) || |
1103 (representation() == kUnboxedInt32)) { | 1116 (representation() == kUnboxedInt32)) { |
1104 if ((index_scale() == 1) && index.IsRegister()) { | 1117 if ((index_scale() == 1) && index.IsRegister()) { |
(...skipping 11 matching lines...) Expand all Loading... |
1116 break; | 1129 break; |
1117 default: | 1130 default: |
1118 UNREACHABLE(); | 1131 UNREACHABLE(); |
1119 } | 1132 } |
1120 return; | 1133 return; |
1121 } | 1134 } |
1122 | 1135 |
1123 if (representation() == kUnboxedMint) { | 1136 if (representation() == kUnboxedMint) { |
1124 ASSERT(class_id() == kTypedDataInt64ArrayCid); | 1137 ASSERT(class_id() == kTypedDataInt64ArrayCid); |
1125 if ((index_scale() == 1) && index.IsRegister()) { | 1138 if ((index_scale() == 1) && index.IsRegister()) { |
1126 __ SmiUntag(index.reg()); | 1139 __ SmiUntag(index.reg()); |
1127 } | 1140 } |
1128 Register result = locs()->out(0).reg(); | 1141 Register result = locs()->out(0).reg(); |
1129 __ movq(result, element_address); | 1142 __ movq(result, element_address); |
1130 return; | 1143 return; |
1131 } | 1144 } |
1132 | 1145 |
1133 ASSERT(representation() == kTagged); | 1146 ASSERT(representation() == kTagged); |
1134 | 1147 |
1135 if ((index_scale() == 1) && index.IsRegister()) { | 1148 if ((index_scale() == 1) && index.IsRegister()) { |
1136 __ SmiUntag(index.reg()); | 1149 __ SmiUntag(index.reg()); |
(...skipping 28 matching lines...) Expand all Loading... |
1165 __ movq(result, element_address); | 1178 __ movq(result, element_address); |
1166 break; | 1179 break; |
1167 } | 1180 } |
1168 } | 1181 } |
1169 | 1182 |
1170 | 1183 |
1171 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1184 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
1172 bool opt) const { | 1185 bool opt) const { |
1173 const intptr_t kNumInputs = 2; | 1186 const intptr_t kNumInputs = 2; |
1174 const intptr_t kNumTemps = 0; | 1187 const intptr_t kNumTemps = 0; |
1175 LocationSummary* summary = new(zone) LocationSummary( | 1188 LocationSummary* summary = new (zone) |
1176 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1177 summary->set_in(0, Location::RequiresRegister()); | 1190 summary->set_in(0, Location::RequiresRegister()); |
1178 // The smi index is either untagged (element size == 1), or it is left smi | 1191 // The smi index is either untagged (element size == 1), or it is left smi |
1179 // tagged (for all element sizes > 1). | 1192 // tagged (for all element sizes > 1). |
1180 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() | 1193 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() |
1181 : Location::RequiresRegister()); | 1194 : Location::RequiresRegister()); |
1182 summary->set_out(0, Location::RequiresRegister()); | 1195 summary->set_out(0, Location::RequiresRegister()); |
1183 return summary; | 1196 return summary; |
1184 } | 1197 } |
1185 | 1198 |
1186 | 1199 |
1187 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1200 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1188 // The string register points to the backing store for external strings. | 1201 // The string register points to the backing store for external strings. |
1189 const Register str = locs()->in(0).reg(); | 1202 const Register str = locs()->in(0).reg(); |
1190 const Location index = locs()->in(1); | 1203 const Location index = locs()->in(1); |
1191 | 1204 |
1192 Address element_address = Assembler::ElementAddressForRegIndex( | 1205 Address element_address = Assembler::ElementAddressForRegIndex( |
1193 IsExternal(), class_id(), index_scale(), str, index.reg()); | 1206 IsExternal(), class_id(), index_scale(), str, index.reg()); |
1194 | 1207 |
1195 if ((index_scale() == 1)) { | 1208 if ((index_scale() == 1)) { |
1196 __ SmiUntag(index.reg()); | 1209 __ SmiUntag(index.reg()); |
1197 } | 1210 } |
1198 Register result = locs()->out(0).reg(); | 1211 Register result = locs()->out(0).reg(); |
1199 switch (class_id()) { | 1212 switch (class_id()) { |
1200 case kOneByteStringCid: | 1213 case kOneByteStringCid: |
1201 case kExternalOneByteStringCid: | 1214 case kExternalOneByteStringCid: |
1202 switch (element_count()) { | 1215 switch (element_count()) { |
1203 case 1: __ movzxb(result, element_address); break; | 1216 case 1: |
1204 case 2: __ movzxw(result, element_address); break; | 1217 __ movzxb(result, element_address); |
1205 case 4: __ movl(result, element_address); break; | 1218 break; |
1206 default: UNREACHABLE(); | 1219 case 2: |
| 1220 __ movzxw(result, element_address); |
| 1221 break; |
| 1222 case 4: |
| 1223 __ movl(result, element_address); |
| 1224 break; |
| 1225 default: |
| 1226 UNREACHABLE(); |
1207 } | 1227 } |
1208 __ SmiTag(result); | 1228 __ SmiTag(result); |
1209 break; | 1229 break; |
1210 case kTwoByteStringCid: | 1230 case kTwoByteStringCid: |
1211 case kExternalTwoByteStringCid: | 1231 case kExternalTwoByteStringCid: |
1212 switch (element_count()) { | 1232 switch (element_count()) { |
1213 case 1: __ movzxw(result, element_address); break; | 1233 case 1: |
1214 case 2: __ movl(result, element_address); break; | 1234 __ movzxw(result, element_address); |
1215 default: UNREACHABLE(); | 1235 break; |
| 1236 case 2: |
| 1237 __ movl(result, element_address); |
| 1238 break; |
| 1239 default: |
| 1240 UNREACHABLE(); |
1216 } | 1241 } |
1217 __ SmiTag(result); | 1242 __ SmiTag(result); |
1218 break; | 1243 break; |
1219 default: | 1244 default: |
1220 UNREACHABLE(); | 1245 UNREACHABLE(); |
1221 break; | 1246 break; |
1222 } | 1247 } |
1223 } | 1248 } |
1224 | 1249 |
1225 | 1250 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 UNIMPLEMENTED(); | 1283 UNIMPLEMENTED(); |
1259 return kTagged; | 1284 return kTagged; |
1260 } | 1285 } |
1261 } | 1286 } |
1262 | 1287 |
1263 | 1288 |
1264 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1289 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1265 bool opt) const { | 1290 bool opt) const { |
1266 const intptr_t kNumInputs = 3; | 1291 const intptr_t kNumInputs = 3; |
1267 const intptr_t kNumTemps = 0; | 1292 const intptr_t kNumTemps = 0; |
1268 LocationSummary* locs = new(zone) LocationSummary( | 1293 LocationSummary* locs = new (zone) |
1269 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1294 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1270 locs->set_in(0, Location::RequiresRegister()); | 1295 locs->set_in(0, Location::RequiresRegister()); |
1271 // The smi index is either untagged (element size == 1), or it is left smi | 1296 // The smi index is either untagged (element size == 1), or it is left smi |
1272 // tagged (for all element sizes > 1). | 1297 // tagged (for all element sizes > 1). |
1273 if (index_scale() == 1) { | 1298 if (index_scale() == 1) { |
1274 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1299 locs->set_in(1, |
1275 ? Location::Constant(index()->definition()->AsConstant()) | 1300 CanBeImmediateIndex(index(), class_id()) |
1276 : Location::WritableRegister()); | 1301 ? Location::Constant(index()->definition()->AsConstant()) |
| 1302 : Location::WritableRegister()); |
1277 } else { | 1303 } else { |
1278 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1304 locs->set_in(1, |
1279 ? Location::Constant(index()->definition()->AsConstant()) | 1305 CanBeImmediateIndex(index(), class_id()) |
1280 : Location::RequiresRegister()); | 1306 ? Location::Constant(index()->definition()->AsConstant()) |
| 1307 : Location::RequiresRegister()); |
1281 } | 1308 } |
1282 switch (class_id()) { | 1309 switch (class_id()) { |
1283 case kArrayCid: | 1310 case kArrayCid: |
1284 locs->set_in(2, ShouldEmitStoreBarrier() | 1311 locs->set_in(2, ShouldEmitStoreBarrier() |
1285 ? Location::WritableRegister() | 1312 ? Location::WritableRegister() |
1286 : Location::RegisterOrConstant(value())); | 1313 : Location::RegisterOrConstant(value())); |
1287 break; | 1314 break; |
1288 case kExternalTypedDataUint8ArrayCid: | 1315 case kExternalTypedDataUint8ArrayCid: |
1289 case kExternalTypedDataUint8ClampedArrayCid: | 1316 case kExternalTypedDataUint8ClampedArrayCid: |
1290 case kTypedDataInt8ArrayCid: | 1317 case kTypedDataInt8ArrayCid: |
1291 case kTypedDataUint8ArrayCid: | 1318 case kTypedDataUint8ArrayCid: |
1292 case kTypedDataUint8ClampedArrayCid: | 1319 case kTypedDataUint8ClampedArrayCid: |
1293 case kOneByteStringCid: | 1320 case kOneByteStringCid: |
1294 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1321 // TODO(fschneider): Add location constraint for byte registers (RAX, |
1295 // RBX, RCX, RDX) instead of using a fixed register. | 1322 // RBX, RCX, RDX) instead of using a fixed register. |
1296 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1323 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
(...skipping 24 matching lines...) Expand all Loading... |
1321 } | 1348 } |
1322 return locs; | 1349 return locs; |
1323 } | 1350 } |
1324 | 1351 |
1325 | 1352 |
1326 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1353 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1327 // The array register points to the backing store for external arrays. | 1354 // The array register points to the backing store for external arrays. |
1328 const Register array = locs()->in(0).reg(); | 1355 const Register array = locs()->in(0).reg(); |
1329 const Location index = locs()->in(1); | 1356 const Location index = locs()->in(1); |
1330 | 1357 |
1331 Address element_address = index.IsRegister() | 1358 Address element_address = |
1332 ? Assembler::ElementAddressForRegIndex( | 1359 index.IsRegister() |
1333 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1360 ? Assembler::ElementAddressForRegIndex( |
1334 : Assembler::ElementAddressForIntIndex( | 1361 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1335 IsExternal(), class_id(), index_scale(), | 1362 : Assembler::ElementAddressForIntIndex( |
1336 array, Smi::Cast(index.constant()).Value()); | 1363 IsExternal(), class_id(), index_scale(), array, |
| 1364 Smi::Cast(index.constant()).Value()); |
1337 | 1365 |
1338 if ((index_scale() == 1) && index.IsRegister()) { | 1366 if ((index_scale() == 1) && index.IsRegister()) { |
1339 __ SmiUntag(index.reg()); | 1367 __ SmiUntag(index.reg()); |
1340 } | 1368 } |
1341 switch (class_id()) { | 1369 switch (class_id()) { |
1342 case kArrayCid: | 1370 case kArrayCid: |
1343 if (ShouldEmitStoreBarrier()) { | 1371 if (ShouldEmitStoreBarrier()) { |
1344 Register value = locs()->in(2).reg(); | 1372 Register value = locs()->in(2).reg(); |
1345 __ StoreIntoObject(array, element_address, value); | 1373 __ StoreIntoObject(array, element_address, value); |
1346 } else if (locs()->in(2).IsConstant()) { | 1374 } else if (locs()->in(2).IsConstant()) { |
(...skipping 22 matching lines...) Expand all Loading... |
1369 case kExternalTypedDataUint8ClampedArrayCid: { | 1397 case kExternalTypedDataUint8ClampedArrayCid: { |
1370 if (locs()->in(2).IsConstant()) { | 1398 if (locs()->in(2).IsConstant()) { |
1371 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1399 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1372 intptr_t value = constant.Value(); | 1400 intptr_t value = constant.Value(); |
1373 // Clamp to 0x0 or 0xFF respectively. | 1401 // Clamp to 0x0 or 0xFF respectively. |
1374 if (value > 0xFF) { | 1402 if (value > 0xFF) { |
1375 value = 0xFF; | 1403 value = 0xFF; |
1376 } else if (value < 0) { | 1404 } else if (value < 0) { |
1377 value = 0; | 1405 value = 0; |
1378 } | 1406 } |
1379 __ movb(element_address, | 1407 __ movb(element_address, Immediate(static_cast<int8_t>(value))); |
1380 Immediate(static_cast<int8_t>(value))); | |
1381 } else { | 1408 } else { |
1382 ASSERT(locs()->in(2).reg() == RAX); | 1409 ASSERT(locs()->in(2).reg() == RAX); |
1383 Label store_value, store_0xff; | 1410 Label store_value, store_0xff; |
1384 __ SmiUntag(RAX); | 1411 __ SmiUntag(RAX); |
1385 __ CompareImmediate(RAX, Immediate(0xFF)); | 1412 __ CompareImmediate(RAX, Immediate(0xFF)); |
1386 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); | 1413 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
1387 // Clamp to 0x0 or 0xFF respectively. | 1414 // Clamp to 0x0 or 0xFF respectively. |
1388 __ j(GREATER, &store_0xff); | 1415 __ j(GREATER, &store_0xff); |
1389 __ xorq(RAX, RAX); | 1416 __ xorq(RAX, RAX); |
1390 __ jmp(&store_value, Assembler::kNearJump); | 1417 __ jmp(&store_value, Assembler::kNearJump); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 | 1459 |
1433 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1460 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1434 bool opt) const { | 1461 bool opt) const { |
1435 const intptr_t kNumInputs = 1; | 1462 const intptr_t kNumInputs = 1; |
1436 | 1463 |
1437 const intptr_t value_cid = value()->Type()->ToCid(); | 1464 const intptr_t value_cid = value()->Type()->ToCid(); |
1438 const intptr_t field_cid = field().guarded_cid(); | 1465 const intptr_t field_cid = field().guarded_cid(); |
1439 | 1466 |
1440 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1467 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1441 const bool needs_value_cid_temp_reg = | 1468 const bool needs_value_cid_temp_reg = |
1442 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1469 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
1443 const bool needs_field_temp_reg = emit_full_guard; | 1470 const bool needs_field_temp_reg = emit_full_guard; |
1444 | 1471 |
1445 intptr_t num_temps = 0; | 1472 intptr_t num_temps = 0; |
1446 if (needs_value_cid_temp_reg) { | 1473 if (needs_value_cid_temp_reg) { |
1447 num_temps++; | 1474 num_temps++; |
1448 } | 1475 } |
1449 if (needs_field_temp_reg) { | 1476 if (needs_field_temp_reg) { |
1450 num_temps++; | 1477 num_temps++; |
1451 } | 1478 } |
1452 | 1479 |
1453 LocationSummary* summary = new(zone) LocationSummary( | 1480 LocationSummary* summary = new (zone) |
1454 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1481 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1455 summary->set_in(0, Location::RequiresRegister()); | 1482 summary->set_in(0, Location::RequiresRegister()); |
1456 | 1483 |
1457 for (intptr_t i = 0; i < num_temps; i++) { | 1484 for (intptr_t i = 0; i < num_temps; i++) { |
1458 summary->set_temp(i, Location::RequiresRegister()); | 1485 summary->set_temp(i, Location::RequiresRegister()); |
1459 } | 1486 } |
1460 | 1487 |
1461 | 1488 |
1462 return summary; | 1489 return summary; |
1463 } | 1490 } |
1464 | 1491 |
1465 | 1492 |
1466 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1493 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1467 ASSERT(sizeof(classid_t) == kInt32Size); | 1494 ASSERT(sizeof(classid_t) == kInt32Size); |
1468 const intptr_t value_cid = value()->Type()->ToCid(); | 1495 const intptr_t value_cid = value()->Type()->ToCid(); |
1469 const intptr_t field_cid = field().guarded_cid(); | 1496 const intptr_t field_cid = field().guarded_cid(); |
1470 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1497 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1471 | 1498 |
1472 if (field_cid == kDynamicCid) { | 1499 if (field_cid == kDynamicCid) { |
1473 if (Compiler::IsBackgroundCompilation()) { | 1500 if (Compiler::IsBackgroundCompilation()) { |
1474 // Field state changed while compiling. | 1501 // Field state changed while compiling. |
1475 Compiler::AbortBackgroundCompilation(deopt_id(), | 1502 Compiler::AbortBackgroundCompilation( |
| 1503 deopt_id(), |
1476 "GuardFieldClassInstr: field state changed while compiling"); | 1504 "GuardFieldClassInstr: field state changed while compiling"); |
1477 } | 1505 } |
1478 ASSERT(!compiler->is_optimizing()); | 1506 ASSERT(!compiler->is_optimizing()); |
1479 return; // Nothing to emit. | 1507 return; // Nothing to emit. |
1480 } | 1508 } |
1481 | 1509 |
1482 const bool emit_full_guard = | 1510 const bool emit_full_guard = |
1483 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1511 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
1484 | 1512 |
1485 const bool needs_value_cid_temp_reg = | 1513 const bool needs_value_cid_temp_reg = |
1486 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1514 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
1487 | 1515 |
1488 const bool needs_field_temp_reg = emit_full_guard; | 1516 const bool needs_field_temp_reg = emit_full_guard; |
1489 | 1517 |
1490 const Register value_reg = locs()->in(0).reg(); | 1518 const Register value_reg = locs()->in(0).reg(); |
1491 | 1519 |
1492 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1520 const Register value_cid_reg = |
1493 locs()->temp(0).reg() : kNoRegister; | 1521 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
1494 | 1522 |
1495 const Register field_reg = needs_field_temp_reg ? | 1523 const Register field_reg = needs_field_temp_reg |
1496 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1524 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1525 : kNoRegister; |
1497 | 1526 |
1498 Label ok, fail_label; | 1527 Label ok, fail_label; |
1499 | 1528 |
1500 Label* deopt = compiler->is_optimizing() ? | 1529 Label* deopt = |
1501 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1530 compiler->is_optimizing() |
| 1531 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1532 : NULL; |
1502 | 1533 |
1503 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1534 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
1504 | 1535 |
1505 if (emit_full_guard) { | 1536 if (emit_full_guard) { |
1506 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1537 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1507 | 1538 |
1508 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1539 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
1509 FieldAddress field_nullability_operand( | 1540 FieldAddress field_nullability_operand(field_reg, |
1510 field_reg, Field::is_nullable_offset()); | 1541 Field::is_nullable_offset()); |
1511 | 1542 |
1512 if (value_cid == kDynamicCid) { | 1543 if (value_cid == kDynamicCid) { |
1513 LoadValueCid(compiler, value_cid_reg, value_reg); | 1544 LoadValueCid(compiler, value_cid_reg, value_reg); |
1514 | 1545 |
1515 __ cmpl(value_cid_reg, field_cid_operand); | 1546 __ cmpl(value_cid_reg, field_cid_operand); |
1516 __ j(EQUAL, &ok); | 1547 __ j(EQUAL, &ok); |
1517 __ cmpl(value_cid_reg, field_nullability_operand); | 1548 __ cmpl(value_cid_reg, field_nullability_operand); |
1518 } else if (value_cid == kNullCid) { | 1549 } else if (value_cid == kNullCid) { |
1519 __ cmpl(field_nullability_operand, Immediate(value_cid)); | 1550 __ cmpl(field_nullability_operand, Immediate(value_cid)); |
1520 } else { | 1551 } else { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 } | 1620 } |
1590 __ Bind(&ok); | 1621 __ Bind(&ok); |
1591 } | 1622 } |
1592 | 1623 |
1593 | 1624 |
1594 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1625 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1595 bool opt) const { | 1626 bool opt) const { |
1596 const intptr_t kNumInputs = 1; | 1627 const intptr_t kNumInputs = 1; |
1597 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1628 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1598 const intptr_t kNumTemps = 3; | 1629 const intptr_t kNumTemps = 3; |
1599 LocationSummary* summary = new(zone) LocationSummary( | 1630 LocationSummary* summary = new (zone) |
1600 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1631 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1601 summary->set_in(0, Location::RequiresRegister()); | 1632 summary->set_in(0, Location::RequiresRegister()); |
1602 // We need temporaries for field object, length offset and expected length. | 1633 // We need temporaries for field object, length offset and expected length. |
1603 summary->set_temp(0, Location::RequiresRegister()); | 1634 summary->set_temp(0, Location::RequiresRegister()); |
1604 summary->set_temp(1, Location::RequiresRegister()); | 1635 summary->set_temp(1, Location::RequiresRegister()); |
1605 summary->set_temp(2, Location::RequiresRegister()); | 1636 summary->set_temp(2, Location::RequiresRegister()); |
1606 return summary; | 1637 return summary; |
1607 } else { | 1638 } else { |
1608 LocationSummary* summary = new(zone) LocationSummary( | 1639 LocationSummary* summary = new (zone) |
1609 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1640 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
1610 summary->set_in(0, Location::RequiresRegister()); | 1641 summary->set_in(0, Location::RequiresRegister()); |
1611 return summary; | 1642 return summary; |
1612 } | 1643 } |
1613 UNREACHABLE(); | 1644 UNREACHABLE(); |
1614 } | 1645 } |
1615 | 1646 |
1616 | 1647 |
1617 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1648 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1618 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1649 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1619 if (Compiler::IsBackgroundCompilation()) { | 1650 if (Compiler::IsBackgroundCompilation()) { |
1620 // Field state changed while compiling. | 1651 // Field state changed while compiling. |
1621 Compiler::AbortBackgroundCompilation(deopt_id(), | 1652 Compiler::AbortBackgroundCompilation( |
| 1653 deopt_id(), |
1622 "GuardFieldLengthInstr: field state changed while compiling"); | 1654 "GuardFieldLengthInstr: field state changed while compiling"); |
1623 } | 1655 } |
1624 ASSERT(!compiler->is_optimizing()); | 1656 ASSERT(!compiler->is_optimizing()); |
1625 return; // Nothing to emit. | 1657 return; // Nothing to emit. |
1626 } | 1658 } |
1627 | 1659 |
1628 Label* deopt = compiler->is_optimizing() ? | 1660 Label* deopt = |
1629 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1661 compiler->is_optimizing() |
| 1662 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1663 : NULL; |
1630 | 1664 |
1631 const Register value_reg = locs()->in(0).reg(); | 1665 const Register value_reg = locs()->in(0).reg(); |
1632 | 1666 |
1633 if (!compiler->is_optimizing() || | 1667 if (!compiler->is_optimizing() || |
1634 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1668 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1635 const Register field_reg = locs()->temp(0).reg(); | 1669 const Register field_reg = locs()->temp(0).reg(); |
1636 const Register offset_reg = locs()->temp(1).reg(); | 1670 const Register offset_reg = locs()->temp(1).reg(); |
1637 const Register length_reg = locs()->temp(2).reg(); | 1671 const Register length_reg = locs()->temp(2).reg(); |
1638 | 1672 |
1639 Label ok; | 1673 Label ok; |
1640 | 1674 |
1641 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1675 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1642 | 1676 |
1643 __ movsxb(offset_reg, FieldAddress(field_reg, | 1677 __ movsxb( |
1644 Field::guarded_list_length_in_object_offset_offset())); | 1678 offset_reg, |
1645 __ movq(length_reg, FieldAddress(field_reg, | 1679 FieldAddress(field_reg, |
1646 Field::guarded_list_length_offset())); | 1680 Field::guarded_list_length_in_object_offset_offset())); |
| 1681 __ movq(length_reg, |
| 1682 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
1647 | 1683 |
1648 __ cmpq(offset_reg, Immediate(0)); | 1684 __ cmpq(offset_reg, Immediate(0)); |
1649 __ j(NEGATIVE, &ok); | 1685 __ j(NEGATIVE, &ok); |
1650 | 1686 |
1651 // Load the length from the value. GuardFieldClass already verified that | 1687 // Load the length from the value. GuardFieldClass already verified that |
1652 // value's class matches guarded class id of the field. | 1688 // value's class matches guarded class id of the field. |
1653 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1689 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
1654 // why we use Address instead of FieldAddress. | 1690 // why we use Address instead of FieldAddress. |
1655 __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); | 1691 __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); |
1656 | 1692 |
1657 if (deopt == NULL) { | 1693 if (deopt == NULL) { |
1658 __ j(EQUAL, &ok); | 1694 __ j(EQUAL, &ok); |
1659 | 1695 |
1660 __ pushq(field_reg); | 1696 __ pushq(field_reg); |
1661 __ pushq(value_reg); | 1697 __ pushq(value_reg); |
1662 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1698 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1663 __ Drop(2); // Drop the field and the value. | 1699 __ Drop(2); // Drop the field and the value. |
1664 } else { | 1700 } else { |
1665 __ j(NOT_EQUAL, deopt); | 1701 __ j(NOT_EQUAL, deopt); |
1666 } | 1702 } |
1667 | 1703 |
1668 __ Bind(&ok); | 1704 __ Bind(&ok); |
1669 } else { | 1705 } else { |
1670 ASSERT(compiler->is_optimizing()); | 1706 ASSERT(compiler->is_optimizing()); |
1671 ASSERT(field().guarded_list_length() >= 0); | 1707 ASSERT(field().guarded_list_length() >= 0); |
1672 ASSERT(field().guarded_list_length_in_object_offset() != | 1708 ASSERT(field().guarded_list_length_in_object_offset() != |
1673 Field::kUnknownLengthOffset); | 1709 Field::kUnknownLengthOffset); |
1674 | 1710 |
1675 __ CompareImmediate( | 1711 __ CompareImmediate( |
1676 FieldAddress(value_reg, | 1712 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
1677 field().guarded_list_length_in_object_offset()), | 1713 Immediate(Smi::RawValue(field().guarded_list_length()))); |
1678 Immediate(Smi::RawValue(field().guarded_list_length()))); | |
1679 __ j(NOT_EQUAL, deopt); | 1714 __ j(NOT_EQUAL, deopt); |
1680 } | 1715 } |
1681 } | 1716 } |
1682 | 1717 |
1683 | 1718 |
1684 class BoxAllocationSlowPath : public SlowPathCode { | 1719 class BoxAllocationSlowPath : public SlowPathCode { |
1685 public: | 1720 public: |
1686 BoxAllocationSlowPath(Instruction* instruction, | 1721 BoxAllocationSlowPath(Instruction* instruction, |
1687 const Class& cls, | 1722 const Class& cls, |
1688 Register result) | 1723 Register result) |
1689 : instruction_(instruction), | 1724 : instruction_(instruction), cls_(cls), result_(result) {} |
1690 cls_(cls), | |
1691 result_(result) { } | |
1692 | 1725 |
1693 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1726 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1694 if (Assembler::EmittingComments()) { | 1727 if (Assembler::EmittingComments()) { |
1695 __ Comment("%s slow path allocation of %s", | 1728 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
1696 instruction_->DebugName(), | |
1697 String::Handle(cls_.ScrubbedName()).ToCString()); | 1729 String::Handle(cls_.ScrubbedName()).ToCString()); |
1698 } | 1730 } |
1699 __ Bind(entry_label()); | 1731 __ Bind(entry_label()); |
1700 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1732 const Code& stub = Code::ZoneHandle( |
1701 StubCode::GetAllocationStubForClass(cls_)); | 1733 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
1702 const StubEntry stub_entry(stub); | 1734 const StubEntry stub_entry(stub); |
1703 | 1735 |
1704 LocationSummary* locs = instruction_->locs(); | 1736 LocationSummary* locs = instruction_->locs(); |
1705 | 1737 |
1706 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1738 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
1707 | 1739 |
1708 compiler->SaveLiveRegisters(locs); | 1740 compiler->SaveLiveRegisters(locs); |
1709 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1741 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
1710 stub_entry, | 1742 stub_entry, RawPcDescriptors::kOther, locs); |
1711 RawPcDescriptors::kOther, | |
1712 locs); | |
1713 compiler->AddStubCallTarget(stub); | 1743 compiler->AddStubCallTarget(stub); |
1714 __ MoveRegister(result_, RAX); | 1744 __ MoveRegister(result_, RAX); |
1715 compiler->RestoreLiveRegisters(locs); | 1745 compiler->RestoreLiveRegisters(locs); |
1716 __ jmp(exit_label()); | 1746 __ jmp(exit_label()); |
1717 } | 1747 } |
1718 | 1748 |
1719 static void Allocate(FlowGraphCompiler* compiler, | 1749 static void Allocate(FlowGraphCompiler* compiler, |
1720 Instruction* instruction, | 1750 Instruction* instruction, |
1721 const Class& cls, | 1751 const Class& cls, |
1722 Register result, | 1752 Register result, |
1723 Register temp) { | 1753 Register temp) { |
1724 if (compiler->intrinsic_mode()) { | 1754 if (compiler->intrinsic_mode()) { |
1725 __ TryAllocate(cls, | 1755 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), |
1726 compiler->intrinsic_slow_path_label(), | 1756 Assembler::kFarJump, result, temp); |
1727 Assembler::kFarJump, | |
1728 result, | |
1729 temp); | |
1730 } else { | 1757 } else { |
1731 BoxAllocationSlowPath* slow_path = | 1758 BoxAllocationSlowPath* slow_path = |
1732 new BoxAllocationSlowPath(instruction, cls, result); | 1759 new BoxAllocationSlowPath(instruction, cls, result); |
1733 compiler->AddSlowPathCode(slow_path); | 1760 compiler->AddSlowPathCode(slow_path); |
1734 | 1761 |
1735 __ TryAllocate(cls, | 1762 __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result, |
1736 slow_path->entry_label(), | |
1737 Assembler::kFarJump, | |
1738 result, | |
1739 temp); | 1763 temp); |
1740 __ Bind(slow_path->exit_label()); | 1764 __ Bind(slow_path->exit_label()); |
1741 } | 1765 } |
1742 } | 1766 } |
1743 | 1767 |
1744 private: | 1768 private: |
1745 Instruction* instruction_; | 1769 Instruction* instruction_; |
1746 const Class& cls_; | 1770 const Class& cls_; |
1747 const Register result_; | 1771 const Register result_; |
1748 }; | 1772 }; |
1749 | 1773 |
1750 | 1774 |
1751 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1775 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
1752 bool opt) const { | 1776 bool opt) const { |
1753 const intptr_t kNumInputs = 2; | 1777 const intptr_t kNumInputs = 2; |
1754 const intptr_t kNumTemps = | 1778 const intptr_t kNumTemps = |
1755 (IsUnboxedStore() && opt) ? 2 : | 1779 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
1756 ((IsPotentialUnboxedStore()) ? 3 : 0); | 1780 LocationSummary* summary = new (zone) |
1757 LocationSummary* summary = new(zone) LocationSummary( | 1781 LocationSummary(zone, kNumInputs, kNumTemps, |
1758 zone, kNumInputs, kNumTemps, | 1782 ((IsUnboxedStore() && opt && is_initialization()) || |
1759 ((IsUnboxedStore() && opt && is_initialization()) || | 1783 IsPotentialUnboxedStore()) |
1760 IsPotentialUnboxedStore()) | 1784 ? LocationSummary::kCallOnSlowPath |
1761 ? LocationSummary::kCallOnSlowPath | 1785 : LocationSummary::kNoCall); |
1762 : LocationSummary::kNoCall); | |
1763 | 1786 |
1764 summary->set_in(0, Location::RequiresRegister()); | 1787 summary->set_in(0, Location::RequiresRegister()); |
1765 if (IsUnboxedStore() && opt) { | 1788 if (IsUnboxedStore() && opt) { |
1766 summary->set_in(1, Location::RequiresFpuRegister()); | 1789 summary->set_in(1, Location::RequiresFpuRegister()); |
1767 summary->set_temp(0, Location::RequiresRegister()); | 1790 summary->set_temp(0, Location::RequiresRegister()); |
1768 summary->set_temp(1, Location::RequiresRegister()); | 1791 summary->set_temp(1, Location::RequiresRegister()); |
1769 } else if (IsPotentialUnboxedStore()) { | 1792 } else if (IsPotentialUnboxedStore()) { |
1770 summary->set_in(1, ShouldEmitStoreBarrier() | 1793 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
1771 ? Location::WritableRegister() | 1794 : Location::RequiresRegister()); |
1772 : Location::RequiresRegister()); | |
1773 summary->set_temp(0, Location::RequiresRegister()); | 1795 summary->set_temp(0, Location::RequiresRegister()); |
1774 summary->set_temp(1, Location::RequiresRegister()); | 1796 summary->set_temp(1, Location::RequiresRegister()); |
1775 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1797 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
1776 : Location::FpuRegisterLocation(XMM1)); | 1798 : Location::FpuRegisterLocation(XMM1)); |
1777 } else { | 1799 } else { |
1778 summary->set_in(1, ShouldEmitStoreBarrier() | 1800 summary->set_in(1, ShouldEmitStoreBarrier() |
1779 ? Location::WritableRegister() | 1801 ? Location::WritableRegister() |
1780 : Location::RegisterOrConstant(value())); | 1802 : Location::RegisterOrConstant(value())); |
1781 } | 1803 } |
1782 return summary; | 1804 return summary; |
1783 } | 1805 } |
1784 | 1806 |
1785 | 1807 |
1786 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1808 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
1787 StoreInstanceFieldInstr* instruction, | 1809 StoreInstanceFieldInstr* instruction, |
1788 Register box_reg, | 1810 Register box_reg, |
1789 const Class& cls, | 1811 const Class& cls, |
1790 Register instance_reg, | 1812 Register instance_reg, |
1791 intptr_t offset, | 1813 intptr_t offset, |
1792 Register temp) { | 1814 Register temp) { |
1793 Label done; | 1815 Label done; |
1794 __ movq(box_reg, FieldAddress(instance_reg, offset)); | 1816 __ movq(box_reg, FieldAddress(instance_reg, offset)); |
1795 __ CompareObject(box_reg, Object::null_object()); | 1817 __ CompareObject(box_reg, Object::null_object()); |
1796 __ j(NOT_EQUAL, &done); | 1818 __ j(NOT_EQUAL, &done); |
1797 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1819 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
1798 __ movq(temp, box_reg); | 1820 __ movq(temp, box_reg); |
1799 __ StoreIntoObject(instance_reg, | 1821 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
1800 FieldAddress(instance_reg, offset), | |
1801 temp); | |
1802 | 1822 |
1803 __ Bind(&done); | 1823 __ Bind(&done); |
1804 } | 1824 } |
1805 | 1825 |
1806 | 1826 |
1807 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1827 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1808 ASSERT(sizeof(classid_t) == kInt32Size); | 1828 ASSERT(sizeof(classid_t) == kInt32Size); |
1809 Label skip_store; | 1829 Label skip_store; |
1810 | 1830 |
1811 Register instance_reg = locs()->in(0).reg(); | 1831 Register instance_reg = locs()->in(0).reg(); |
(...skipping 16 matching lines...) Expand all Loading... |
1828 case kFloat64x2Cid: | 1848 case kFloat64x2Cid: |
1829 cls = &compiler->float64x2_class(); | 1849 cls = &compiler->float64x2_class(); |
1830 break; | 1850 break; |
1831 default: | 1851 default: |
1832 UNREACHABLE(); | 1852 UNREACHABLE(); |
1833 } | 1853 } |
1834 | 1854 |
1835 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); | 1855 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
1836 __ movq(temp2, temp); | 1856 __ movq(temp2, temp); |
1837 __ StoreIntoObject(instance_reg, | 1857 __ StoreIntoObject(instance_reg, |
1838 FieldAddress(instance_reg, offset_in_bytes_), | 1858 FieldAddress(instance_reg, offset_in_bytes_), temp2); |
1839 temp2); | |
1840 } else { | 1859 } else { |
1841 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 1860 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
1842 } | 1861 } |
1843 switch (cid) { | 1862 switch (cid) { |
1844 case kDoubleCid: | 1863 case kDoubleCid: |
1845 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); | 1864 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
1846 __ movsd(FieldAddress(temp, Double::value_offset()), value); | 1865 __ movsd(FieldAddress(temp, Double::value_offset()), value); |
1847 break; | 1866 break; |
1848 case kFloat32x4Cid: | 1867 case kFloat32x4Cid: |
1849 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); | 1868 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
1850 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); | 1869 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); |
1851 break; | 1870 break; |
1852 case kFloat64x2Cid: | 1871 case kFloat64x2Cid: |
1853 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); | 1872 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); |
1854 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); | 1873 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); |
1855 break; | 1874 break; |
1856 default: | 1875 default: |
1857 UNREACHABLE(); | 1876 UNREACHABLE(); |
1858 } | 1877 } |
1859 return; | 1878 return; |
1860 } | 1879 } |
1861 | 1880 |
1862 if (IsPotentialUnboxedStore()) { | 1881 if (IsPotentialUnboxedStore()) { |
1863 Register value_reg = locs()->in(1).reg(); | 1882 Register value_reg = locs()->in(1).reg(); |
1864 Register temp = locs()->temp(0).reg(); | 1883 Register temp = locs()->temp(0).reg(); |
1865 Register temp2 = locs()->temp(1).reg(); | 1884 Register temp2 = locs()->temp(1).reg(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 // Fall through. | 1920 // Fall through. |
1902 __ jmp(&store_pointer); | 1921 __ jmp(&store_pointer); |
1903 | 1922 |
1904 if (!compiler->is_optimizing()) { | 1923 if (!compiler->is_optimizing()) { |
1905 locs()->live_registers()->Add(locs()->in(0)); | 1924 locs()->live_registers()->Add(locs()->in(0)); |
1906 locs()->live_registers()->Add(locs()->in(1)); | 1925 locs()->live_registers()->Add(locs()->in(1)); |
1907 } | 1926 } |
1908 | 1927 |
1909 { | 1928 { |
1910 __ Bind(&store_double); | 1929 __ Bind(&store_double); |
1911 EnsureMutableBox(compiler, | 1930 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
1912 this, | 1931 instance_reg, offset_in_bytes_, temp2); |
1913 temp, | |
1914 compiler->double_class(), | |
1915 instance_reg, | |
1916 offset_in_bytes_, | |
1917 temp2); | |
1918 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1932 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
1919 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); | 1933 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); |
1920 __ jmp(&skip_store); | 1934 __ jmp(&skip_store); |
1921 } | 1935 } |
1922 | 1936 |
1923 { | 1937 { |
1924 __ Bind(&store_float32x4); | 1938 __ Bind(&store_float32x4); |
1925 EnsureMutableBox(compiler, | 1939 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
1926 this, | 1940 instance_reg, offset_in_bytes_, temp2); |
1927 temp, | |
1928 compiler->float32x4_class(), | |
1929 instance_reg, | |
1930 offset_in_bytes_, | |
1931 temp2); | |
1932 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); | 1941 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); |
1933 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); | 1942 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); |
1934 __ jmp(&skip_store); | 1943 __ jmp(&skip_store); |
1935 } | 1944 } |
1936 | 1945 |
1937 { | 1946 { |
1938 __ Bind(&store_float64x2); | 1947 __ Bind(&store_float64x2); |
1939 EnsureMutableBox(compiler, | 1948 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
1940 this, | 1949 instance_reg, offset_in_bytes_, temp2); |
1941 temp, | |
1942 compiler->float64x2_class(), | |
1943 instance_reg, | |
1944 offset_in_bytes_, | |
1945 temp2); | |
1946 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); | 1950 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); |
1947 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); | 1951 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); |
1948 __ jmp(&skip_store); | 1952 __ jmp(&skip_store); |
1949 } | 1953 } |
1950 | 1954 |
1951 __ Bind(&store_pointer); | 1955 __ Bind(&store_pointer); |
1952 } | 1956 } |
1953 | 1957 |
1954 if (ShouldEmitStoreBarrier()) { | 1958 if (ShouldEmitStoreBarrier()) { |
1955 Register value_reg = locs()->in(1).reg(); | 1959 Register value_reg = locs()->in(1).reg(); |
1956 __ StoreIntoObject(instance_reg, | 1960 __ StoreIntoObject(instance_reg, |
1957 FieldAddress(instance_reg, offset_in_bytes_), | 1961 FieldAddress(instance_reg, offset_in_bytes_), value_reg, |
1958 value_reg, | |
1959 CanValueBeSmi()); | 1962 CanValueBeSmi()); |
1960 } else { | 1963 } else { |
1961 if (locs()->in(1).IsConstant()) { | 1964 if (locs()->in(1).IsConstant()) { |
1962 __ StoreIntoObjectNoBarrier(instance_reg, | 1965 __ StoreIntoObjectNoBarrier(instance_reg, |
1963 FieldAddress(instance_reg, offset_in_bytes_), | 1966 FieldAddress(instance_reg, offset_in_bytes_), |
1964 locs()->in(1).constant()); | 1967 locs()->in(1).constant()); |
1965 } else { | 1968 } else { |
1966 Register value_reg = locs()->in(1).reg(); | 1969 Register value_reg = locs()->in(1).reg(); |
1967 __ StoreIntoObjectNoBarrier(instance_reg, | 1970 __ StoreIntoObjectNoBarrier(instance_reg, |
1968 FieldAddress(instance_reg, offset_in_bytes_), | 1971 FieldAddress(instance_reg, offset_in_bytes_), |
1969 value_reg); | 1972 value_reg); |
1970 } | 1973 } |
1971 } | 1974 } |
1972 __ Bind(&skip_store); | 1975 __ Bind(&skip_store); |
1973 } | 1976 } |
1974 | 1977 |
1975 | 1978 |
1976 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1979 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
1977 bool opt) const { | 1980 bool opt) const { |
1978 const intptr_t kNumInputs = 1; | 1981 const intptr_t kNumInputs = 1; |
1979 const intptr_t kNumTemps = 0; | 1982 const intptr_t kNumTemps = 0; |
1980 LocationSummary* summary = new(zone) LocationSummary( | 1983 LocationSummary* summary = new (zone) |
1981 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1984 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1982 summary->set_in(0, Location::RequiresRegister()); | 1985 summary->set_in(0, Location::RequiresRegister()); |
1983 summary->set_out(0, Location::RequiresRegister()); | 1986 summary->set_out(0, Location::RequiresRegister()); |
1984 return summary; | 1987 return summary; |
1985 } | 1988 } |
1986 | 1989 |
1987 | 1990 |
1988 // When the parser is building an implicit static getter for optimization, | 1991 // When the parser is building an implicit static getter for optimization, |
1989 // it can generate a function body where deoptimization ids do not line up | 1992 // it can generate a function body where deoptimization ids do not line up |
1990 // with the unoptimized code. | 1993 // with the unoptimized code. |
1991 // | 1994 // |
1992 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1995 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
1993 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1996 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1994 Register field = locs()->in(0).reg(); | 1997 Register field = locs()->in(0).reg(); |
1995 Register result = locs()->out(0).reg(); | 1998 Register result = locs()->out(0).reg(); |
1996 __ movq(result, FieldAddress(field, Field::static_value_offset())); | 1999 __ movq(result, FieldAddress(field, Field::static_value_offset())); |
1997 } | 2000 } |
1998 | 2001 |
1999 | 2002 |
2000 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2003 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2001 bool opt) const { | 2004 bool opt) const { |
2002 LocationSummary* locs = new(zone) LocationSummary( | 2005 LocationSummary* locs = |
2003 zone, 1, 1, LocationSummary::kNoCall); | 2006 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
2004 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2007 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2005 : Location::RequiresRegister()); | 2008 : Location::RequiresRegister()); |
2006 locs->set_temp(0, Location::RequiresRegister()); | 2009 locs->set_temp(0, Location::RequiresRegister()); |
2007 return locs; | 2010 return locs; |
2008 } | 2011 } |
2009 | 2012 |
2010 | 2013 |
2011 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2014 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2012 Register value = locs()->in(0).reg(); | 2015 Register value = locs()->in(0).reg(); |
2013 Register temp = locs()->temp(0).reg(); | 2016 Register temp = locs()->temp(0).reg(); |
2014 | 2017 |
2015 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2018 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
2016 if (this->value()->NeedsStoreBuffer()) { | 2019 if (this->value()->NeedsStoreBuffer()) { |
2017 __ StoreIntoObject(temp, | 2020 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
2018 FieldAddress(temp, Field::static_value_offset()), | 2021 value, CanValueBeSmi()); |
2019 value, | |
2020 CanValueBeSmi()); | |
2021 } else { | 2022 } else { |
2022 __ StoreIntoObjectNoBarrier( | 2023 __ StoreIntoObjectNoBarrier( |
2023 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2024 temp, FieldAddress(temp, Field::static_value_offset()), value); |
2024 } | 2025 } |
2025 } | 2026 } |
2026 | 2027 |
2027 | 2028 |
2028 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2029 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
2029 bool opt) const { | 2030 bool opt) const { |
2030 const intptr_t kNumInputs = 2; | 2031 const intptr_t kNumInputs = 2; |
2031 const intptr_t kNumTemps = 0; | 2032 const intptr_t kNumTemps = 0; |
2032 LocationSummary* summary = new(zone) LocationSummary( | 2033 LocationSummary* summary = new (zone) |
2033 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2034 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2034 summary->set_in(0, Location::RegisterLocation(RAX)); | 2035 summary->set_in(0, Location::RegisterLocation(RAX)); |
2035 summary->set_in(1, Location::RegisterLocation(RDX)); | 2036 summary->set_in(1, Location::RegisterLocation(RDX)); |
2036 summary->set_out(0, Location::RegisterLocation(RAX)); | 2037 summary->set_out(0, Location::RegisterLocation(RAX)); |
2037 return summary; | 2038 return summary; |
2038 } | 2039 } |
2039 | 2040 |
2040 | 2041 |
2041 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2042 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2042 ASSERT(locs()->in(0).reg() == RAX); // Value. | 2043 ASSERT(locs()->in(0).reg() == RAX); // Value. |
2043 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. | 2044 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. |
2044 | 2045 |
2045 compiler->GenerateInstanceOf(token_pos(), | 2046 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
2046 deopt_id(), | |
2047 type(), | |
2048 negate_result(), | |
2049 locs()); | 2047 locs()); |
2050 ASSERT(locs()->out(0).reg() == RAX); | 2048 ASSERT(locs()->out(0).reg() == RAX); |
2051 } | 2049 } |
2052 | 2050 |
2053 | 2051 |
2054 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 2052 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
2055 // use slow path stub. | 2053 // use slow path stub. |
2056 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2054 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
2057 bool opt) const { | 2055 bool opt) const { |
2058 const intptr_t kNumInputs = 2; | 2056 const intptr_t kNumInputs = 2; |
2059 const intptr_t kNumTemps = 0; | 2057 const intptr_t kNumTemps = 0; |
2060 LocationSummary* locs = new(zone) LocationSummary( | 2058 LocationSummary* locs = new (zone) |
2061 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2059 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2062 locs->set_in(0, Location::RegisterLocation(RBX)); | 2060 locs->set_in(0, Location::RegisterLocation(RBX)); |
2063 locs->set_in(1, Location::RegisterLocation(R10)); | 2061 locs->set_in(1, Location::RegisterLocation(R10)); |
2064 locs->set_out(0, Location::RegisterLocation(RAX)); | 2062 locs->set_out(0, Location::RegisterLocation(RAX)); |
2065 return locs; | 2063 return locs; |
2066 } | 2064 } |
2067 | 2065 |
2068 | 2066 |
2069 // Inlines array allocation for known constant values. | 2067 // Inlines array allocation for known constant values. |
2070 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2068 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
2071 intptr_t num_elements, | 2069 intptr_t num_elements, |
2072 Label* slow_path, | 2070 Label* slow_path, |
2073 Label* done) { | 2071 Label* done) { |
2074 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2072 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
2075 const Register kLengthReg = R10; | 2073 const Register kLengthReg = R10; |
2076 const Register kElemTypeReg = RBX; | 2074 const Register kElemTypeReg = RBX; |
2077 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2075 const intptr_t instance_size = Array::InstanceSize(num_elements); |
2078 | 2076 |
2079 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, | 2077 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, |
2080 RAX, // instance | 2078 RAX, // instance |
2081 RCX, // end address | 2079 RCX, // end address |
2082 R13); // temp | 2080 R13); // temp |
2083 | 2081 |
2084 // RAX: new object start as a tagged pointer. | 2082 // RAX: new object start as a tagged pointer. |
2085 // Store the type argument field. | 2083 // Store the type argument field. |
2086 __ StoreIntoObjectNoBarrier(RAX, | 2084 __ StoreIntoObjectNoBarrier( |
2087 FieldAddress(RAX, Array::type_arguments_offset()), | 2085 RAX, FieldAddress(RAX, Array::type_arguments_offset()), kElemTypeReg); |
2088 kElemTypeReg); | |
2089 | 2086 |
2090 // Set the length field. | 2087 // Set the length field. |
2091 __ StoreIntoObjectNoBarrier(RAX, | 2088 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, Array::length_offset()), |
2092 FieldAddress(RAX, Array::length_offset()), | |
2093 kLengthReg); | 2089 kLengthReg); |
2094 | 2090 |
2095 // Initialize all array elements to raw_null. | 2091 // Initialize all array elements to raw_null. |
2096 // RAX: new object start as a tagged pointer. | 2092 // RAX: new object start as a tagged pointer. |
2097 // RCX: new object end address. | 2093 // RCX: new object end address. |
2098 // RDI: iterator which initially points to the start of the variable | 2094 // RDI: iterator which initially points to the start of the variable |
2099 // data area to be initialized. | 2095 // data area to be initialized. |
2100 if (num_elements > 0) { | 2096 if (num_elements > 0) { |
2101 const intptr_t array_size = instance_size - sizeof(RawArray); | 2097 const intptr_t array_size = instance_size - sizeof(RawArray); |
2102 __ LoadObject(R12, Object::null_object()); | 2098 __ LoadObject(R12, Object::null_object()); |
(...skipping 19 matching lines...) Expand all Loading... |
2122 | 2118 |
2123 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2119 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2124 // Allocate the array. R10 = length, RBX = element type. | 2120 // Allocate the array. R10 = length, RBX = element type. |
2125 const Register kLengthReg = R10; | 2121 const Register kLengthReg = R10; |
2126 const Register kElemTypeReg = RBX; | 2122 const Register kElemTypeReg = RBX; |
2127 const Register kResultReg = RAX; | 2123 const Register kResultReg = RAX; |
2128 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2124 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
2129 ASSERT(locs()->in(1).reg() == kLengthReg); | 2125 ASSERT(locs()->in(1).reg() == kLengthReg); |
2130 | 2126 |
2131 Label slow_path, done; | 2127 Label slow_path, done; |
2132 if (compiler->is_optimizing() && | 2128 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
2133 !FLAG_precompiled_mode && | |
2134 num_elements()->BindsToConstant() && | 2129 num_elements()->BindsToConstant() && |
2135 num_elements()->BoundConstant().IsSmi()) { | 2130 num_elements()->BoundConstant().IsSmi()) { |
2136 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2131 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
2137 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2132 if ((length >= 0) && (length <= Array::kMaxElements)) { |
2138 Label slow_path, done; | 2133 Label slow_path, done; |
2139 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2134 InlineArrayAllocation(compiler, length, &slow_path, &done); |
2140 __ Bind(&slow_path); | 2135 __ Bind(&slow_path); |
2141 __ PushObject(Object::null_object()); // Make room for the result. | 2136 __ PushObject(Object::null_object()); // Make room for the result. |
2142 __ pushq(kLengthReg); | 2137 __ pushq(kLengthReg); |
2143 __ pushq(kElemTypeReg); | 2138 __ pushq(kElemTypeReg); |
2144 compiler->GenerateRuntimeCall(token_pos(), | 2139 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2145 deopt_id(), | 2140 kAllocateArrayRuntimeEntry, 2, locs()); |
2146 kAllocateArrayRuntimeEntry, | |
2147 2, | |
2148 locs()); | |
2149 __ Drop(2); | 2141 __ Drop(2); |
2150 __ popq(kResultReg); | 2142 __ popq(kResultReg); |
2151 __ Bind(&done); | 2143 __ Bind(&done); |
2152 return; | 2144 return; |
2153 } | 2145 } |
2154 } | 2146 } |
2155 | 2147 |
2156 __ Bind(&slow_path); | 2148 __ Bind(&slow_path); |
2157 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2149 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2158 StubCode::AllocateArray_entry()->code()); | 2150 StubCode::AllocateArray_entry()->code()); |
2159 compiler->AddStubCallTarget(stub); | 2151 compiler->AddStubCallTarget(stub); |
2160 compiler->GenerateCall(token_pos(), | 2152 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
2161 *StubCode::AllocateArray_entry(), | 2153 RawPcDescriptors::kOther, locs()); |
2162 RawPcDescriptors::kOther, | |
2163 locs()); | |
2164 __ Bind(&done); | 2154 __ Bind(&done); |
2165 ASSERT(locs()->out(0).reg() == kResultReg); | 2155 ASSERT(locs()->out(0).reg() == kResultReg); |
2166 } | 2156 } |
2167 | 2157 |
2168 | 2158 |
2169 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2159 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2170 bool opt) const { | 2160 bool opt) const { |
2171 const intptr_t kNumInputs = 1; | 2161 const intptr_t kNumInputs = 1; |
2172 const intptr_t kNumTemps = | 2162 const intptr_t kNumTemps = |
2173 (IsUnboxedLoad() && opt) ? 1 : | 2163 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
2174 ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2164 LocationSummary* locs = new (zone) LocationSummary( |
2175 LocationSummary* locs = new(zone) LocationSummary( | 2165 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
2176 zone, kNumInputs, kNumTemps, | 2166 ? LocationSummary::kNoCall |
2177 (opt && !IsPotentialUnboxedLoad()) | 2167 : LocationSummary::kCallOnSlowPath); |
2178 ? LocationSummary::kNoCall | |
2179 : LocationSummary::kCallOnSlowPath); | |
2180 | 2168 |
2181 locs->set_in(0, Location::RequiresRegister()); | 2169 locs->set_in(0, Location::RequiresRegister()); |
2182 | 2170 |
2183 if (IsUnboxedLoad() && opt) { | 2171 if (IsUnboxedLoad() && opt) { |
2184 locs->set_temp(0, Location::RequiresRegister()); | 2172 locs->set_temp(0, Location::RequiresRegister()); |
2185 } else if (IsPotentialUnboxedLoad()) { | 2173 } else if (IsPotentialUnboxedLoad()) { |
2186 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2174 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
2187 : Location::FpuRegisterLocation(XMM1)); | 2175 : Location::FpuRegisterLocation(XMM1)); |
2188 locs->set_temp(1, Location::RequiresRegister()); | 2176 locs->set_temp(1, Location::RequiresRegister()); |
2189 } | 2177 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2250 | 2238 |
2251 // Fall through. | 2239 // Fall through. |
2252 __ jmp(&load_pointer); | 2240 __ jmp(&load_pointer); |
2253 | 2241 |
2254 if (!compiler->is_optimizing()) { | 2242 if (!compiler->is_optimizing()) { |
2255 locs()->live_registers()->Add(locs()->in(0)); | 2243 locs()->live_registers()->Add(locs()->in(0)); |
2256 } | 2244 } |
2257 | 2245 |
2258 { | 2246 { |
2259 __ Bind(&load_double); | 2247 __ Bind(&load_double); |
2260 BoxAllocationSlowPath::Allocate( | 2248 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
2261 compiler, this, compiler->double_class(), result, temp); | 2249 result, temp); |
2262 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2250 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2263 __ movsd(value, FieldAddress(temp, Double::value_offset())); | 2251 __ movsd(value, FieldAddress(temp, Double::value_offset())); |
2264 __ movsd(FieldAddress(result, Double::value_offset()), value); | 2252 __ movsd(FieldAddress(result, Double::value_offset()), value); |
2265 __ jmp(&done); | 2253 __ jmp(&done); |
2266 } | 2254 } |
2267 | 2255 |
2268 { | 2256 { |
2269 __ Bind(&load_float32x4); | 2257 __ Bind(&load_float32x4); |
2270 BoxAllocationSlowPath::Allocate( | 2258 BoxAllocationSlowPath::Allocate( |
2271 compiler, this, compiler->float32x4_class(), result, temp); | 2259 compiler, this, compiler->float32x4_class(), result, temp); |
(...skipping 17 matching lines...) Expand all Loading... |
2289 } | 2277 } |
2290 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); | 2278 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); |
2291 __ Bind(&done); | 2279 __ Bind(&done); |
2292 } | 2280 } |
2293 | 2281 |
2294 | 2282 |
2295 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2283 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2296 bool opt) const { | 2284 bool opt) const { |
2297 const intptr_t kNumInputs = 1; | 2285 const intptr_t kNumInputs = 1; |
2298 const intptr_t kNumTemps = 0; | 2286 const intptr_t kNumTemps = 0; |
2299 LocationSummary* locs = new(zone) LocationSummary( | 2287 LocationSummary* locs = new (zone) |
2300 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2288 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2301 locs->set_in(0, Location::RegisterLocation(RAX)); | 2289 locs->set_in(0, Location::RegisterLocation(RAX)); |
2302 locs->set_out(0, Location::RegisterLocation(RAX)); | 2290 locs->set_out(0, Location::RegisterLocation(RAX)); |
2303 return locs; | 2291 return locs; |
2304 } | 2292 } |
2305 | 2293 |
2306 | 2294 |
2307 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2295 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2308 Register instantiator_reg = locs()->in(0).reg(); | 2296 Register instantiator_reg = locs()->in(0).reg(); |
2309 Register result_reg = locs()->out(0).reg(); | 2297 Register result_reg = locs()->out(0).reg(); |
2310 | 2298 |
2311 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2299 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2312 // A runtime call to instantiate the type is required. | 2300 // A runtime call to instantiate the type is required. |
2313 __ PushObject(Object::null_object()); // Make room for the result. | 2301 __ PushObject(Object::null_object()); // Make room for the result. |
2314 __ PushObject(type()); | 2302 __ PushObject(type()); |
2315 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2303 __ pushq(instantiator_reg); // Push instantiator type arguments. |
2316 compiler->GenerateRuntimeCall(token_pos(), | 2304 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2317 deopt_id(), | 2305 kInstantiateTypeRuntimeEntry, 2, locs()); |
2318 kInstantiateTypeRuntimeEntry, | 2306 __ Drop(2); // Drop instantiator and uninstantiated type. |
2319 2, | |
2320 locs()); | |
2321 __ Drop(2); // Drop instantiator and uninstantiated type. | |
2322 __ popq(result_reg); // Pop instantiated type. | 2307 __ popq(result_reg); // Pop instantiated type. |
2323 ASSERT(instantiator_reg == result_reg); | 2308 ASSERT(instantiator_reg == result_reg); |
2324 } | 2309 } |
2325 | 2310 |
2326 | 2311 |
2327 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2312 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2328 Zone* zone, bool opt) const { | 2313 Zone* zone, |
| 2314 bool opt) const { |
2329 const intptr_t kNumInputs = 1; | 2315 const intptr_t kNumInputs = 1; |
2330 const intptr_t kNumTemps = 0; | 2316 const intptr_t kNumTemps = 0; |
2331 LocationSummary* locs = new(zone) LocationSummary( | 2317 LocationSummary* locs = new (zone) |
2332 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2318 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2333 locs->set_in(0, Location::RegisterLocation(RAX)); | 2319 locs->set_in(0, Location::RegisterLocation(RAX)); |
2334 locs->set_out(0, Location::RegisterLocation(RAX)); | 2320 locs->set_out(0, Location::RegisterLocation(RAX)); |
2335 return locs; | 2321 return locs; |
2336 } | 2322 } |
2337 | 2323 |
2338 | 2324 |
2339 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2325 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2340 FlowGraphCompiler* compiler) { | 2326 FlowGraphCompiler* compiler) { |
2341 Register instantiator_reg = locs()->in(0).reg(); | 2327 Register instantiator_reg = locs()->in(0).reg(); |
2342 Register result_reg = locs()->out(0).reg(); | 2328 Register result_reg = locs()->out(0).reg(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 __ Bind(&found); | 2363 __ Bind(&found); |
2378 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. | 2364 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. |
2379 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); | 2365 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); |
2380 | 2366 |
2381 __ Bind(&slow_case); | 2367 __ Bind(&slow_case); |
2382 // Instantiate non-null type arguments. | 2368 // Instantiate non-null type arguments. |
2383 // A runtime call to instantiate the type arguments is required. | 2369 // A runtime call to instantiate the type arguments is required. |
2384 __ PushObject(Object::null_object()); // Make room for the result. | 2370 __ PushObject(Object::null_object()); // Make room for the result. |
2385 __ PushObject(type_arguments()); | 2371 __ PushObject(type_arguments()); |
2386 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2372 __ pushq(instantiator_reg); // Push instantiator type arguments. |
2387 compiler->GenerateRuntimeCall(token_pos(), | 2373 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2388 deopt_id(), | 2374 kInstantiateTypeArgumentsRuntimeEntry, 2, |
2389 kInstantiateTypeArgumentsRuntimeEntry, | |
2390 2, | |
2391 locs()); | 2375 locs()); |
2392 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2376 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
2393 __ popq(result_reg); // Pop instantiated type arguments. | 2377 __ popq(result_reg); // Pop instantiated type arguments. |
2394 __ Bind(&type_arguments_instantiated); | 2378 __ Bind(&type_arguments_instantiated); |
2395 ASSERT(instantiator_reg == result_reg); | 2379 ASSERT(instantiator_reg == result_reg); |
2396 } | 2380 } |
2397 | 2381 |
2398 | 2382 |
2399 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2383 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2400 Zone* zone, | 2384 Zone* zone, |
2401 bool opt) const { | 2385 bool opt) const { |
2402 ASSERT(opt); | 2386 ASSERT(opt); |
2403 const intptr_t kNumInputs = 0; | 2387 const intptr_t kNumInputs = 0; |
2404 const intptr_t kNumTemps = 2; | 2388 const intptr_t kNumTemps = 2; |
2405 LocationSummary* locs = new(zone) LocationSummary( | 2389 LocationSummary* locs = new (zone) LocationSummary( |
2406 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2390 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2407 locs->set_temp(0, Location::RegisterLocation(R10)); | 2391 locs->set_temp(0, Location::RegisterLocation(R10)); |
2408 locs->set_temp(1, Location::RegisterLocation(R13)); | 2392 locs->set_temp(1, Location::RegisterLocation(R13)); |
2409 locs->set_out(0, Location::RegisterLocation(RAX)); | 2393 locs->set_out(0, Location::RegisterLocation(RAX)); |
2410 return locs; | 2394 return locs; |
2411 } | 2395 } |
2412 | 2396 |
2413 | 2397 |
2414 class AllocateContextSlowPath : public SlowPathCode { | 2398 class AllocateContextSlowPath : public SlowPathCode { |
2415 public: | 2399 public: |
2416 explicit AllocateContextSlowPath( | 2400 explicit AllocateContextSlowPath( |
2417 AllocateUninitializedContextInstr* instruction) | 2401 AllocateUninitializedContextInstr* instruction) |
2418 : instruction_(instruction) { } | 2402 : instruction_(instruction) {} |
2419 | 2403 |
2420 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2404 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2421 __ Comment("AllocateContextSlowPath"); | 2405 __ Comment("AllocateContextSlowPath"); |
2422 __ Bind(entry_label()); | 2406 __ Bind(entry_label()); |
2423 | 2407 |
2424 LocationSummary* locs = instruction_->locs(); | 2408 LocationSummary* locs = instruction_->locs(); |
2425 locs->live_registers()->Remove(locs->out(0)); | 2409 locs->live_registers()->Remove(locs->out(0)); |
2426 | 2410 |
2427 compiler->SaveLiveRegisters(locs); | 2411 compiler->SaveLiveRegisters(locs); |
2428 | 2412 |
2429 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables())); | 2413 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables())); |
2430 const Code& stub = Code::ZoneHandle( | 2414 const Code& stub = Code::ZoneHandle( |
2431 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2415 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
2432 compiler->AddStubCallTarget(stub); | 2416 compiler->AddStubCallTarget(stub); |
2433 compiler->GenerateCall(instruction_->token_pos(), | 2417 compiler->GenerateCall(instruction_->token_pos(), |
2434 *StubCode::AllocateContext_entry(), | 2418 *StubCode::AllocateContext_entry(), |
2435 RawPcDescriptors::kOther, | 2419 RawPcDescriptors::kOther, locs); |
2436 locs); | |
2437 ASSERT(instruction_->locs()->out(0).reg() == RAX); | 2420 ASSERT(instruction_->locs()->out(0).reg() == RAX); |
2438 compiler->RestoreLiveRegisters(instruction_->locs()); | 2421 compiler->RestoreLiveRegisters(instruction_->locs()); |
2439 __ jmp(exit_label()); | 2422 __ jmp(exit_label()); |
2440 } | 2423 } |
2441 | 2424 |
2442 private: | 2425 private: |
2443 AllocateUninitializedContextInstr* instruction_; | 2426 AllocateUninitializedContextInstr* instruction_; |
2444 }; | 2427 }; |
2445 | 2428 |
2446 | 2429 |
2447 void AllocateUninitializedContextInstr::EmitNativeCode( | 2430 void AllocateUninitializedContextInstr::EmitNativeCode( |
2448 FlowGraphCompiler* compiler) { | 2431 FlowGraphCompiler* compiler) { |
2449 ASSERT(compiler->is_optimizing()); | 2432 ASSERT(compiler->is_optimizing()); |
2450 Register temp = locs()->temp(0).reg(); | 2433 Register temp = locs()->temp(0).reg(); |
2451 Register result = locs()->out(0).reg(); | 2434 Register result = locs()->out(0).reg(); |
2452 // Try allocate the object. | 2435 // Try allocate the object. |
2453 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2436 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2454 compiler->AddSlowPathCode(slow_path); | 2437 compiler->AddSlowPathCode(slow_path); |
2455 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2438 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2456 | 2439 |
2457 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2440 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2458 Assembler::kFarJump, | 2441 Assembler::kFarJump, |
2459 result, // instance | 2442 result, // instance |
2460 temp, // end address | 2443 temp, // end address |
2461 locs()->temp(1).reg()); | 2444 locs()->temp(1).reg()); |
2462 | 2445 |
2463 // Setup up number of context variables field. | 2446 // Setup up number of context variables field. |
2464 __ movq(FieldAddress(result, Context::num_variables_offset()), | 2447 __ movq(FieldAddress(result, Context::num_variables_offset()), |
2465 Immediate(num_context_variables())); | 2448 Immediate(num_context_variables())); |
2466 | 2449 |
2467 __ Bind(slow_path->exit_label()); | 2450 __ Bind(slow_path->exit_label()); |
2468 } | 2451 } |
2469 | 2452 |
2470 | 2453 |
2471 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2454 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2472 bool opt) const { | 2455 bool opt) const { |
2473 const intptr_t kNumInputs = 0; | 2456 const intptr_t kNumInputs = 0; |
2474 const intptr_t kNumTemps = 1; | 2457 const intptr_t kNumTemps = 1; |
2475 LocationSummary* locs = new(zone) LocationSummary( | 2458 LocationSummary* locs = new (zone) |
2476 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2477 locs->set_temp(0, Location::RegisterLocation(R10)); | 2460 locs->set_temp(0, Location::RegisterLocation(R10)); |
2478 locs->set_out(0, Location::RegisterLocation(RAX)); | 2461 locs->set_out(0, Location::RegisterLocation(RAX)); |
2479 return locs; | 2462 return locs; |
2480 } | 2463 } |
2481 | 2464 |
2482 | 2465 |
2483 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2466 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2484 ASSERT(locs()->temp(0).reg() == R10); | 2467 ASSERT(locs()->temp(0).reg() == R10); |
2485 ASSERT(locs()->out(0).reg() == RAX); | 2468 ASSERT(locs()->out(0).reg() == RAX); |
2486 | 2469 |
2487 __ LoadImmediate(R10, Immediate(num_context_variables())); | 2470 __ LoadImmediate(R10, Immediate(num_context_variables())); |
2488 compiler->GenerateCall(token_pos(), | 2471 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2489 *StubCode::AllocateContext_entry(), | 2472 RawPcDescriptors::kOther, locs()); |
2490 RawPcDescriptors::kOther, | |
2491 locs()); | |
2492 } | 2473 } |
2493 | 2474 |
2494 | 2475 |
2495 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2476 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2496 bool opt) const { | 2477 bool opt) const { |
2497 const intptr_t kNumInputs = 1; | 2478 const intptr_t kNumInputs = 1; |
2498 const intptr_t kNumTemps = 1; | 2479 const intptr_t kNumTemps = 1; |
2499 LocationSummary* locs = new(zone) LocationSummary( | 2480 LocationSummary* locs = new (zone) |
2500 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2481 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2501 locs->set_in(0, Location::RegisterLocation(RAX)); | 2482 locs->set_in(0, Location::RegisterLocation(RAX)); |
2502 locs->set_temp(0, Location::RegisterLocation(RCX)); | 2483 locs->set_temp(0, Location::RegisterLocation(RCX)); |
2503 return locs; | 2484 return locs; |
2504 } | 2485 } |
2505 | 2486 |
2506 | 2487 |
2507 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2488 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2508 Register field = locs()->in(0).reg(); | 2489 Register field = locs()->in(0).reg(); |
2509 Register temp = locs()->temp(0).reg(); | 2490 Register temp = locs()->temp(0).reg(); |
2510 | 2491 |
2511 Label call_runtime, no_call; | 2492 Label call_runtime, no_call; |
2512 | 2493 |
2513 __ movq(temp, FieldAddress(field, Field::static_value_offset())); | 2494 __ movq(temp, FieldAddress(field, Field::static_value_offset())); |
2514 __ CompareObject(temp, Object::sentinel()); | 2495 __ CompareObject(temp, Object::sentinel()); |
2515 __ j(EQUAL, &call_runtime); | 2496 __ j(EQUAL, &call_runtime); |
2516 | 2497 |
2517 __ CompareObject(temp, Object::transition_sentinel()); | 2498 __ CompareObject(temp, Object::transition_sentinel()); |
2518 __ j(NOT_EQUAL, &no_call); | 2499 __ j(NOT_EQUAL, &no_call); |
2519 | 2500 |
2520 __ Bind(&call_runtime); | 2501 __ Bind(&call_runtime); |
2521 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2502 __ PushObject(Object::null_object()); // Make room for (unused) result. |
2522 __ pushq(field); | 2503 __ pushq(field); |
2523 compiler->GenerateRuntimeCall(token_pos(), | 2504 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2524 deopt_id(), | 2505 kInitStaticFieldRuntimeEntry, 1, locs()); |
2525 kInitStaticFieldRuntimeEntry, | |
2526 1, | |
2527 locs()); | |
2528 __ Drop(2); // Remove argument and unused result. | 2506 __ Drop(2); // Remove argument and unused result. |
2529 __ Bind(&no_call); | 2507 __ Bind(&no_call); |
2530 } | 2508 } |
2531 | 2509 |
2532 | 2510 |
2533 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2511 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2534 bool opt) const { | 2512 bool opt) const { |
2535 const intptr_t kNumInputs = 1; | 2513 const intptr_t kNumInputs = 1; |
2536 const intptr_t kNumTemps = 0; | 2514 const intptr_t kNumTemps = 0; |
2537 LocationSummary* locs = new(zone) LocationSummary( | 2515 LocationSummary* locs = new (zone) |
2538 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2516 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2539 locs->set_in(0, Location::RegisterLocation(RAX)); | 2517 locs->set_in(0, Location::RegisterLocation(RAX)); |
2540 locs->set_out(0, Location::RegisterLocation(RAX)); | 2518 locs->set_out(0, Location::RegisterLocation(RAX)); |
2541 return locs; | 2519 return locs; |
2542 } | 2520 } |
2543 | 2521 |
2544 | 2522 |
2545 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2523 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2546 Register context_value = locs()->in(0).reg(); | 2524 Register context_value = locs()->in(0).reg(); |
2547 Register result = locs()->out(0).reg(); | 2525 Register result = locs()->out(0).reg(); |
2548 | 2526 |
2549 __ PushObject(Object::null_object()); // Make room for the result. | 2527 __ PushObject(Object::null_object()); // Make room for the result. |
2550 __ pushq(context_value); | 2528 __ pushq(context_value); |
2551 compiler->GenerateRuntimeCall(token_pos(), | 2529 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2552 deopt_id(), | 2530 kCloneContextRuntimeEntry, 1, locs()); |
2553 kCloneContextRuntimeEntry, | |
2554 1, | |
2555 locs()); | |
2556 __ popq(result); // Remove argument. | 2531 __ popq(result); // Remove argument. |
2557 __ popq(result); // Get result (cloned context). | 2532 __ popq(result); // Get result (cloned context). |
2558 } | 2533 } |
2559 | 2534 |
2560 | 2535 |
2561 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2536 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2562 bool opt) const { | 2537 bool opt) const { |
2563 UNREACHABLE(); | 2538 UNREACHABLE(); |
2564 return NULL; | 2539 return NULL; |
2565 } | 2540 } |
2566 | 2541 |
2567 | 2542 |
2568 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2543 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2569 __ Bind(compiler->GetJumpLabel(this)); | 2544 __ Bind(compiler->GetJumpLabel(this)); |
2570 compiler->AddExceptionHandler(catch_try_index(), | 2545 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2571 try_index(), | |
2572 compiler->assembler()->CodeSize(), | 2546 compiler->assembler()->CodeSize(), |
2573 catch_handler_types_, | 2547 catch_handler_types_, needs_stacktrace()); |
2574 needs_stacktrace()); | |
2575 // On lazy deoptimization we patch the optimized code here to enter the | 2548 // On lazy deoptimization we patch the optimized code here to enter the |
2576 // deoptimization stub. | 2549 // deoptimization stub. |
2577 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2550 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2578 if (compiler->is_optimizing()) { | 2551 if (compiler->is_optimizing()) { |
2579 compiler->AddDeoptIndexAtCall(deopt_id); | 2552 compiler->AddDeoptIndexAtCall(deopt_id); |
2580 } else { | 2553 } else { |
2581 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2554 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
2582 deopt_id, | |
2583 TokenPosition::kNoSource); | 2555 TokenPosition::kNoSource); |
2584 } | 2556 } |
2585 if (HasParallelMove()) { | 2557 if (HasParallelMove()) { |
2586 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2558 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
2587 } | 2559 } |
2588 | 2560 |
2589 // Restore RSP from RBP as we are coming from a throw and the code for | 2561 // Restore RSP from RBP as we are coming from a throw and the code for |
2590 // popping arguments has not been run. | 2562 // popping arguments has not been run. |
2591 const intptr_t fp_sp_dist = | 2563 const intptr_t fp_sp_dist = |
2592 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2564 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2637 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 2609 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
2638 kStackTraceObjectReg); | 2610 kStackTraceObjectReg); |
2639 } | 2611 } |
2640 } | 2612 } |
2641 | 2613 |
2642 | 2614 |
2643 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2615 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2644 bool opt) const { | 2616 bool opt) const { |
2645 const intptr_t kNumInputs = 0; | 2617 const intptr_t kNumInputs = 0; |
2646 const intptr_t kNumTemps = 1; | 2618 const intptr_t kNumTemps = 1; |
2647 LocationSummary* summary = new(zone) LocationSummary( | 2619 LocationSummary* summary = new (zone) LocationSummary( |
2648 zone, kNumInputs, | 2620 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2649 kNumTemps, | |
2650 LocationSummary::kCallOnSlowPath); | |
2651 summary->set_temp(0, Location::RequiresRegister()); | 2621 summary->set_temp(0, Location::RequiresRegister()); |
2652 return summary; | 2622 return summary; |
2653 } | 2623 } |
2654 | 2624 |
2655 | 2625 |
2656 class CheckStackOverflowSlowPath : public SlowPathCode { | 2626 class CheckStackOverflowSlowPath : public SlowPathCode { |
2657 public: | 2627 public: |
2658 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2628 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2659 : instruction_(instruction) { } | 2629 : instruction_(instruction) {} |
2660 | 2630 |
2661 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2631 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2662 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2632 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
2663 __ Comment("CheckStackOverflowSlowPathOsr"); | 2633 __ Comment("CheckStackOverflowSlowPathOsr"); |
2664 __ Bind(osr_entry_label()); | 2634 __ Bind(osr_entry_label()); |
2665 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), | 2635 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), |
2666 Immediate(Thread::kOsrRequest)); | 2636 Immediate(Thread::kOsrRequest)); |
2667 } | 2637 } |
2668 __ Comment("CheckStackOverflowSlowPath"); | 2638 __ Comment("CheckStackOverflowSlowPath"); |
2669 __ Bind(entry_label()); | 2639 __ Bind(entry_label()); |
2670 compiler->SaveLiveRegisters(instruction_->locs()); | 2640 compiler->SaveLiveRegisters(instruction_->locs()); |
2671 // pending_deoptimization_env_ is needed to generate a runtime call that | 2641 // pending_deoptimization_env_ is needed to generate a runtime call that |
2672 // may throw an exception. | 2642 // may throw an exception. |
2673 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2643 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
2674 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2644 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
2675 compiler->pending_deoptimization_env_ = env; | 2645 compiler->pending_deoptimization_env_ = env; |
2676 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2646 compiler->GenerateRuntimeCall( |
2677 instruction_->deopt_id(), | 2647 instruction_->token_pos(), instruction_->deopt_id(), |
2678 kStackOverflowRuntimeEntry, | 2648 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
2679 0, | |
2680 instruction_->locs()); | |
2681 | 2649 |
2682 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2650 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
2683 // In unoptimized code, record loop stack checks as possible OSR entries. | 2651 // In unoptimized code, record loop stack checks as possible OSR entries. |
2684 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2652 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
2685 instruction_->deopt_id(), | 2653 instruction_->deopt_id(), |
2686 TokenPosition::kNoSource); | 2654 TokenPosition::kNoSource); |
2687 } | 2655 } |
2688 compiler->pending_deoptimization_env_ = NULL; | 2656 compiler->pending_deoptimization_env_ = NULL; |
2689 compiler->RestoreLiveRegisters(instruction_->locs()); | 2657 compiler->RestoreLiveRegisters(instruction_->locs()); |
2690 __ jmp(exit_label()); | 2658 __ jmp(exit_label()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2727 __ Bind(slow_path->exit_label()); | 2695 __ Bind(slow_path->exit_label()); |
2728 } | 2696 } |
2729 | 2697 |
2730 | 2698 |
2731 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2699 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2732 BinarySmiOpInstr* shift_left) { | 2700 BinarySmiOpInstr* shift_left) { |
2733 const LocationSummary& locs = *shift_left->locs(); | 2701 const LocationSummary& locs = *shift_left->locs(); |
2734 Register left = locs.in(0).reg(); | 2702 Register left = locs.in(0).reg(); |
2735 Register result = locs.out(0).reg(); | 2703 Register result = locs.out(0).reg(); |
2736 ASSERT(left == result); | 2704 ASSERT(left == result); |
2737 Label* deopt = shift_left->CanDeoptimize() ? | 2705 Label* deopt = shift_left->CanDeoptimize() |
2738 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2706 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
2739 : NULL; | 2707 ICData::kDeoptBinarySmiOp) |
| 2708 : NULL; |
2740 if (locs.in(1).IsConstant()) { | 2709 if (locs.in(1).IsConstant()) { |
2741 const Object& constant = locs.in(1).constant(); | 2710 const Object& constant = locs.in(1).constant(); |
2742 ASSERT(constant.IsSmi()); | 2711 ASSERT(constant.IsSmi()); |
2743 // shlq operation masks the count to 6 bits. | 2712 // shlq operation masks the count to 6 bits. |
2744 const intptr_t kCountLimit = 0x3F; | 2713 const intptr_t kCountLimit = 0x3F; |
2745 const intptr_t value = Smi::Cast(constant).Value(); | 2714 const intptr_t value = Smi::Cast(constant).Value(); |
2746 ASSERT((0 < value) && (value < kCountLimit)); | 2715 ASSERT((0 < value) && (value < kCountLimit)); |
2747 if (shift_left->can_overflow()) { | 2716 if (shift_left->can_overflow()) { |
2748 if (value == 1) { | 2717 if (value == 1) { |
2749 // Use overflow flag. | 2718 // Use overflow flag. |
(...skipping 25 matching lines...) Expand all Loading... |
2775 const intptr_t left_int = Smi::Cast(obj).Value(); | 2744 const intptr_t left_int = Smi::Cast(obj).Value(); |
2776 if (left_int == 0) { | 2745 if (left_int == 0) { |
2777 __ CompareImmediate(right, Immediate(0)); | 2746 __ CompareImmediate(right, Immediate(0)); |
2778 __ j(NEGATIVE, deopt); | 2747 __ j(NEGATIVE, deopt); |
2779 return; | 2748 return; |
2780 } | 2749 } |
2781 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2750 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
2782 const bool right_needs_check = | 2751 const bool right_needs_check = |
2783 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2752 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
2784 if (right_needs_check) { | 2753 if (right_needs_check) { |
2785 __ CompareImmediate(right, | 2754 __ CompareImmediate( |
2786 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); | 2755 right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); |
2787 __ j(ABOVE_EQUAL, deopt); | 2756 __ j(ABOVE_EQUAL, deopt); |
2788 } | 2757 } |
2789 __ SmiUntag(right); | 2758 __ SmiUntag(right); |
2790 __ shlq(left, right); | 2759 __ shlq(left, right); |
2791 } | 2760 } |
2792 return; | 2761 return; |
2793 } | 2762 } |
2794 | 2763 |
2795 const bool right_needs_check = | 2764 const bool right_needs_check = |
2796 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2765 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
2797 ASSERT(right == RCX); // Count must be in RCX | 2766 ASSERT(right == RCX); // Count must be in RCX |
2798 if (!shift_left->can_overflow()) { | 2767 if (!shift_left->can_overflow()) { |
2799 if (right_needs_check) { | 2768 if (right_needs_check) { |
2800 const bool right_may_be_negative = | 2769 const bool right_may_be_negative = |
2801 (right_range == NULL) || !right_range->IsPositive(); | 2770 (right_range == NULL) || !right_range->IsPositive(); |
2802 if (right_may_be_negative) { | 2771 if (right_may_be_negative) { |
2803 ASSERT(shift_left->CanDeoptimize()); | 2772 ASSERT(shift_left->CanDeoptimize()); |
2804 __ CompareImmediate(right, Immediate(0)); | 2773 __ CompareImmediate(right, Immediate(0)); |
2805 __ j(NEGATIVE, deopt); | 2774 __ j(NEGATIVE, deopt); |
2806 } | 2775 } |
2807 Label done, is_not_zero; | 2776 Label done, is_not_zero; |
2808 __ CompareImmediate(right, | 2777 __ CompareImmediate( |
2809 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 2778 right, Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
2810 __ j(BELOW, &is_not_zero, Assembler::kNearJump); | 2779 __ j(BELOW, &is_not_zero, Assembler::kNearJump); |
2811 __ xorq(left, left); | 2780 __ xorq(left, left); |
2812 __ jmp(&done, Assembler::kNearJump); | 2781 __ jmp(&done, Assembler::kNearJump); |
2813 __ Bind(&is_not_zero); | 2782 __ Bind(&is_not_zero); |
2814 __ SmiUntag(right); | 2783 __ SmiUntag(right); |
2815 __ shlq(left, right); | 2784 __ shlq(left, right); |
2816 __ Bind(&done); | 2785 __ Bind(&done); |
2817 } else { | 2786 } else { |
2818 __ SmiUntag(right); | 2787 __ SmiUntag(right); |
2819 __ shlq(left, right); | 2788 __ shlq(left, right); |
2820 } | 2789 } |
2821 } else { | 2790 } else { |
2822 if (right_needs_check) { | 2791 if (right_needs_check) { |
2823 ASSERT(shift_left->CanDeoptimize()); | 2792 ASSERT(shift_left->CanDeoptimize()); |
2824 __ CompareImmediate(right, | 2793 __ CompareImmediate( |
2825 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 2794 right, Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
2826 __ j(ABOVE_EQUAL, deopt); | 2795 __ j(ABOVE_EQUAL, deopt); |
2827 } | 2796 } |
2828 // Left is not a constant. | 2797 // Left is not a constant. |
2829 Register temp = locs.temp(0).reg(); | 2798 Register temp = locs.temp(0).reg(); |
2830 // Check if count too large for handling it inlined. | 2799 // Check if count too large for handling it inlined. |
2831 __ movq(temp, left); | 2800 __ movq(temp, left); |
2832 __ SmiUntag(right); | 2801 __ SmiUntag(right); |
2833 // Overflow test (preserve temp and right); | 2802 // Overflow test (preserve temp and right); |
2834 __ shlq(left, right); | 2803 __ shlq(left, right); |
2835 __ sarq(left, right); | 2804 __ sarq(left, right); |
2836 __ cmpq(left, temp); | 2805 __ cmpq(left, temp); |
2837 __ j(NOT_EQUAL, deopt); // Overflow. | 2806 __ j(NOT_EQUAL, deopt); // Overflow. |
2838 // Shift for result now we know there is no overflow. | 2807 // Shift for result now we know there is no overflow. |
2839 __ shlq(left, right); | 2808 __ shlq(left, right); |
2840 } | 2809 } |
2841 } | 2810 } |
2842 | 2811 |
2843 | 2812 |
2844 class CheckedSmiSlowPath : public SlowPathCode { | 2813 class CheckedSmiSlowPath : public SlowPathCode { |
2845 public: | 2814 public: |
2846 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2815 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
2847 : instruction_(instruction), try_index_(try_index) { } | 2816 : instruction_(instruction), try_index_(try_index) {} |
2848 | 2817 |
2849 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2818 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2850 if (Assembler::EmittingComments()) { | 2819 if (Assembler::EmittingComments()) { |
2851 __ Comment("slow path smi operation"); | 2820 __ Comment("slow path smi operation"); |
2852 } | 2821 } |
2853 __ Bind(entry_label()); | 2822 __ Bind(entry_label()); |
2854 LocationSummary* locs = instruction_->locs(); | 2823 LocationSummary* locs = instruction_->locs(); |
2855 Register result = locs->out(0).reg(); | 2824 Register result = locs->out(0).reg(); |
2856 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2825 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
2857 | 2826 |
2858 compiler->SaveLiveRegisters(locs); | 2827 compiler->SaveLiveRegisters(locs); |
2859 __ pushq(locs->in(0).reg()); | 2828 __ pushq(locs->in(0).reg()); |
2860 __ pushq(locs->in(1).reg()); | 2829 __ pushq(locs->in(1).reg()); |
2861 compiler->EmitMegamorphicInstanceCall( | 2830 compiler->EmitMegamorphicInstanceCall( |
2862 *instruction_->call()->ic_data(), | 2831 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
2863 instruction_->call()->ArgumentCount(), | 2832 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
2864 instruction_->call()->deopt_id(), | 2833 locs, try_index_, |
2865 instruction_->call()->token_pos(), | |
2866 locs, | |
2867 try_index_, | |
2868 /* slow_path_argument_count = */ 2); | 2834 /* slow_path_argument_count = */ 2); |
2869 __ MoveRegister(result, RAX); | 2835 __ MoveRegister(result, RAX); |
2870 compiler->RestoreLiveRegisters(locs); | 2836 compiler->RestoreLiveRegisters(locs); |
2871 __ jmp(exit_label()); | 2837 __ jmp(exit_label()); |
2872 } | 2838 } |
2873 | 2839 |
2874 private: | 2840 private: |
2875 CheckedSmiOpInstr* instruction_; | 2841 CheckedSmiOpInstr* instruction_; |
2876 intptr_t try_index_; | 2842 intptr_t try_index_; |
2877 }; | 2843 }; |
2878 | 2844 |
2879 | 2845 |
2880 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2846 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
2881 bool opt) const { | 2847 bool opt) const { |
2882 const intptr_t kNumInputs = 2; | 2848 const intptr_t kNumInputs = 2; |
2883 const intptr_t kNumTemps = 0; | 2849 const intptr_t kNumTemps = 0; |
2884 LocationSummary* summary = new(zone) LocationSummary( | 2850 LocationSummary* summary = new (zone) LocationSummary( |
2885 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2851 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2886 summary->set_in(0, Location::RequiresRegister()); | 2852 summary->set_in(0, Location::RequiresRegister()); |
2887 summary->set_in(1, Location::RequiresRegister()); | 2853 summary->set_in(1, Location::RequiresRegister()); |
2888 switch (op_kind()) { | 2854 switch (op_kind()) { |
2889 case Token::kADD: | 2855 case Token::kADD: |
2890 case Token::kSUB: | 2856 case Token::kSUB: |
2891 case Token::kMUL: | 2857 case Token::kMUL: |
2892 summary->set_out(0, Location::RequiresRegister()); | 2858 summary->set_out(0, Location::RequiresRegister()); |
2893 break; | 2859 break; |
2894 case Token::kBIT_OR: | 2860 case Token::kBIT_OR: |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2964 | 2930 |
2965 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2931 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
2966 public: | 2932 public: |
2967 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2933 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
2968 intptr_t try_index, | 2934 intptr_t try_index, |
2969 BranchLabels labels, | 2935 BranchLabels labels, |
2970 bool merged = false) | 2936 bool merged = false) |
2971 : instruction_(instruction), | 2937 : instruction_(instruction), |
2972 try_index_(try_index), | 2938 try_index_(try_index), |
2973 labels_(labels), | 2939 labels_(labels), |
2974 merged_(merged) { } | 2940 merged_(merged) {} |
2975 | 2941 |
2976 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2942 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2977 if (Assembler::EmittingComments()) { | 2943 if (Assembler::EmittingComments()) { |
2978 __ Comment("slow path smi comparison"); | 2944 __ Comment("slow path smi comparison"); |
2979 } | 2945 } |
2980 __ Bind(entry_label()); | 2946 __ Bind(entry_label()); |
2981 LocationSummary* locs = instruction_->locs(); | 2947 LocationSummary* locs = instruction_->locs(); |
2982 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 2948 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
2983 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2949 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
2984 | 2950 |
2985 compiler->SaveLiveRegisters(locs); | 2951 compiler->SaveLiveRegisters(locs); |
2986 __ pushq(locs->in(0).reg()); | 2952 __ pushq(locs->in(0).reg()); |
2987 __ pushq(locs->in(1).reg()); | 2953 __ pushq(locs->in(1).reg()); |
2988 compiler->EmitMegamorphicInstanceCall( | 2954 compiler->EmitMegamorphicInstanceCall( |
2989 *instruction_->call()->ic_data(), | 2955 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
2990 instruction_->call()->ArgumentCount(), | 2956 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
2991 instruction_->call()->deopt_id(), | 2957 locs, try_index_, |
2992 instruction_->call()->token_pos(), | |
2993 locs, | |
2994 try_index_, | |
2995 /* slow_path_argument_count = */ 2); | 2958 /* slow_path_argument_count = */ 2); |
2996 __ MoveRegister(result, RAX); | 2959 __ MoveRegister(result, RAX); |
2997 compiler->RestoreLiveRegisters(locs); | 2960 compiler->RestoreLiveRegisters(locs); |
2998 if (merged_) { | 2961 if (merged_) { |
2999 __ CompareObject(result, Bool::True()); | 2962 __ CompareObject(result, Bool::True()); |
3000 __ j(EQUAL, instruction_->is_negated() | 2963 __ j(EQUAL, instruction_->is_negated() ? labels_.false_label |
3001 ? labels_.false_label : labels_.true_label); | 2964 : labels_.true_label); |
3002 __ jmp(instruction_->is_negated() | 2965 __ jmp(instruction_->is_negated() ? labels_.true_label |
3003 ? labels_.true_label : labels_.false_label); | 2966 : labels_.false_label); |
3004 } else { | 2967 } else { |
3005 __ jmp(exit_label()); | 2968 __ jmp(exit_label()); |
3006 } | 2969 } |
3007 } | 2970 } |
3008 | 2971 |
3009 private: | 2972 private: |
3010 CheckedSmiComparisonInstr* instruction_; | 2973 CheckedSmiComparisonInstr* instruction_; |
3011 intptr_t try_index_; | 2974 intptr_t try_index_; |
3012 BranchLabels labels_; | 2975 BranchLabels labels_; |
3013 bool merged_; | 2976 bool merged_; |
3014 }; | 2977 }; |
3015 | 2978 |
3016 | 2979 |
3017 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2980 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
3018 Zone* zone, bool opt) const { | 2981 Zone* zone, |
| 2982 bool opt) const { |
3019 const intptr_t kNumInputs = 2; | 2983 const intptr_t kNumInputs = 2; |
3020 const intptr_t kNumTemps = 1; | 2984 const intptr_t kNumTemps = 1; |
3021 LocationSummary* summary = new(zone) LocationSummary( | 2985 LocationSummary* summary = new (zone) LocationSummary( |
3022 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2986 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3023 summary->set_in(0, Location::RequiresRegister()); | 2987 summary->set_in(0, Location::RequiresRegister()); |
3024 summary->set_in(1, Location::RequiresRegister()); | 2988 summary->set_in(1, Location::RequiresRegister()); |
3025 summary->set_temp(0, Location::RequiresRegister()); | 2989 summary->set_temp(0, Location::RequiresRegister()); |
3026 summary->set_out(0, Location::RequiresRegister()); | 2990 summary->set_out(0, Location::RequiresRegister()); |
3027 return summary; | 2991 return summary; |
3028 } | 2992 } |
3029 | 2993 |
3030 | 2994 |
3031 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2995 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
3032 FlowGraphCompiler* compiler, BranchLabels labels) { | 2996 FlowGraphCompiler* compiler, |
| 2997 BranchLabels labels) { |
3033 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 2998 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
3034 } | 2999 } |
3035 | 3000 |
3036 | 3001 |
3037 #define EMIT_SMI_CHECK \ | 3002 #define EMIT_SMI_CHECK \ |
3038 intptr_t left_cid = left()->Type()->ToCid(); \ | 3003 intptr_t left_cid = left()->Type()->ToCid(); \ |
3039 intptr_t right_cid = right()->Type()->ToCid(); \ | 3004 intptr_t right_cid = right()->Type()->ToCid(); \ |
3040 Register left = locs()->in(0).reg(); \ | 3005 Register left = locs()->in(0).reg(); \ |
3041 Register right = locs()->in(1).reg(); \ | 3006 Register right = locs()->in(1).reg(); \ |
3042 if (this->left()->definition() == this->right()->definition()) { \ | 3007 if (this->left()->definition() == this->right()->definition()) { \ |
3043 __ testq(left, Immediate(kSmiTagMask)); \ | 3008 __ testq(left, Immediate(kSmiTagMask)); \ |
3044 } else if (left_cid == kSmiCid) { \ | 3009 } else if (left_cid == kSmiCid) { \ |
3045 __ testq(right, Immediate(kSmiTagMask)); \ | 3010 __ testq(right, Immediate(kSmiTagMask)); \ |
3046 } else if (right_cid == kSmiCid) { \ | 3011 } else if (right_cid == kSmiCid) { \ |
3047 __ testq(left, Immediate(kSmiTagMask)); \ | 3012 __ testq(left, Immediate(kSmiTagMask)); \ |
3048 } else { \ | 3013 } else { \ |
3049 __ movq(TMP, left); \ | 3014 __ movq(TMP, left); \ |
3050 __ orq(TMP, right); \ | 3015 __ orq(TMP, right); \ |
3051 __ testq(TMP, Immediate(kSmiTagMask)); \ | 3016 __ testq(TMP, Immediate(kSmiTagMask)); \ |
3052 } \ | 3017 } \ |
3053 __ j(NOT_ZERO, slow_path->entry_label()) | 3018 __ j(NOT_ZERO, slow_path->entry_label()) |
3054 | 3019 |
3055 | 3020 |
3056 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3021 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3057 BranchInstr* branch) { | 3022 BranchInstr* branch) { |
3058 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3023 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3059 CheckedSmiComparisonSlowPath* slow_path = | 3024 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3060 new CheckedSmiComparisonSlowPath(this, | 3025 this, compiler->CurrentTryIndex(), labels, |
3061 compiler->CurrentTryIndex(), | 3026 /* merged = */ true); |
3062 labels, | |
3063 /* merged = */ true); | |
3064 compiler->AddSlowPathCode(slow_path); | 3027 compiler->AddSlowPathCode(slow_path); |
3065 EMIT_SMI_CHECK; | 3028 EMIT_SMI_CHECK; |
3066 Condition true_condition = EmitComparisonCode(compiler, labels); | 3029 Condition true_condition = EmitComparisonCode(compiler, labels); |
3067 EmitBranchOnCondition(compiler, true_condition, labels); | 3030 EmitBranchOnCondition(compiler, true_condition, labels); |
3068 __ Bind(slow_path->exit_label()); | 3031 __ Bind(slow_path->exit_label()); |
3069 } | 3032 } |
3070 | 3033 |
3071 | 3034 |
3072 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3035 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3073 Label true_label, false_label, done; | 3036 Label true_label, false_label, done; |
3074 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3037 BranchLabels labels = {&true_label, &false_label, &false_label}; |
3075 CheckedSmiComparisonSlowPath* slow_path = | 3038 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3076 new CheckedSmiComparisonSlowPath(this, | 3039 this, compiler->CurrentTryIndex(), labels, |
3077 compiler->CurrentTryIndex(), | 3040 /* merged = */ false); |
3078 labels, | |
3079 /* merged = */ false); | |
3080 compiler->AddSlowPathCode(slow_path); | 3041 compiler->AddSlowPathCode(slow_path); |
3081 EMIT_SMI_CHECK; | 3042 EMIT_SMI_CHECK; |
3082 Condition true_condition = EmitComparisonCode(compiler, labels); | 3043 Condition true_condition = EmitComparisonCode(compiler, labels); |
3083 EmitBranchOnCondition(compiler, true_condition, labels); | 3044 EmitBranchOnCondition(compiler, true_condition, labels); |
3084 Register result = locs()->out(0).reg(); | 3045 Register result = locs()->out(0).reg(); |
3085 __ Bind(&false_label); | 3046 __ Bind(&false_label); |
3086 __ LoadObject(result, Bool::False()); | 3047 __ LoadObject(result, Bool::False()); |
3087 __ jmp(&done); | 3048 __ jmp(&done); |
3088 __ Bind(&true_label); | 3049 __ Bind(&true_label); |
3089 __ LoadObject(result, Bool::True()); | 3050 __ LoadObject(result, Bool::True()); |
3090 __ Bind(&done); | 3051 __ Bind(&done); |
3091 __ Bind(slow_path->exit_label()); | 3052 __ Bind(slow_path->exit_label()); |
3092 } | 3053 } |
3093 | 3054 |
3094 | 3055 |
3095 static bool CanBeImmediate(const Object& constant) { | 3056 static bool CanBeImmediate(const Object& constant) { |
3096 return constant.IsSmi() && | 3057 return constant.IsSmi() && |
3097 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 3058 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
3098 } | 3059 } |
3099 | 3060 |
3100 static bool IsSmiValue(const Object& constant, intptr_t value) { | 3061 static bool IsSmiValue(const Object& constant, intptr_t value) { |
3101 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 3062 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
3102 } | 3063 } |
3103 | 3064 |
3104 | 3065 |
3105 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3066 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3106 bool opt) const { | 3067 bool opt) const { |
3107 const intptr_t kNumInputs = 2; | 3068 const intptr_t kNumInputs = 2; |
3108 | 3069 |
3109 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3070 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3110 if ((right_constant != NULL) && | 3071 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && |
3111 (op_kind() != Token::kTRUNCDIV) && | 3072 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && |
3112 (op_kind() != Token::kSHL) && | 3073 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { |
3113 (op_kind() != Token::kMUL) && | |
3114 (op_kind() != Token::kMOD) && | |
3115 CanBeImmediate(right_constant->value())) { | |
3116 const intptr_t kNumTemps = 0; | 3074 const intptr_t kNumTemps = 0; |
3117 LocationSummary* summary = new(zone) LocationSummary( | 3075 LocationSummary* summary = new (zone) |
3118 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3119 summary->set_in(0, Location::RequiresRegister()); | 3077 summary->set_in(0, Location::RequiresRegister()); |
3120 summary->set_in(1, Location::Constant(right_constant)); | 3078 summary->set_in(1, Location::Constant(right_constant)); |
3121 summary->set_out(0, Location::SameAsFirstInput()); | 3079 summary->set_out(0, Location::SameAsFirstInput()); |
3122 return summary; | 3080 return summary; |
3123 } | 3081 } |
3124 | 3082 |
3125 if (op_kind() == Token::kTRUNCDIV) { | 3083 if (op_kind() == Token::kTRUNCDIV) { |
3126 const intptr_t kNumTemps = 1; | 3084 const intptr_t kNumTemps = 1; |
3127 LocationSummary* summary = new(zone) LocationSummary( | 3085 LocationSummary* summary = new (zone) |
3128 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3086 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3129 if (RightIsPowerOfTwoConstant()) { | 3087 if (RightIsPowerOfTwoConstant()) { |
3130 summary->set_in(0, Location::RequiresRegister()); | 3088 summary->set_in(0, Location::RequiresRegister()); |
3131 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3089 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3132 summary->set_in(1, Location::Constant(right_constant)); | 3090 summary->set_in(1, Location::Constant(right_constant)); |
3133 summary->set_temp(0, Location::RequiresRegister()); | 3091 summary->set_temp(0, Location::RequiresRegister()); |
3134 summary->set_out(0, Location::SameAsFirstInput()); | 3092 summary->set_out(0, Location::SameAsFirstInput()); |
3135 } else { | 3093 } else { |
3136 // Both inputs must be writable because they will be untagged. | 3094 // Both inputs must be writable because they will be untagged. |
3137 summary->set_in(0, Location::RegisterLocation(RAX)); | 3095 summary->set_in(0, Location::RegisterLocation(RAX)); |
3138 summary->set_in(1, Location::WritableRegister()); | 3096 summary->set_in(1, Location::WritableRegister()); |
3139 summary->set_out(0, Location::SameAsFirstInput()); | 3097 summary->set_out(0, Location::SameAsFirstInput()); |
3140 // Will be used for sign extension and division. | 3098 // Will be used for sign extension and division. |
3141 summary->set_temp(0, Location::RegisterLocation(RDX)); | 3099 summary->set_temp(0, Location::RegisterLocation(RDX)); |
3142 } | 3100 } |
3143 return summary; | 3101 return summary; |
3144 } else if (op_kind() == Token::kMOD) { | 3102 } else if (op_kind() == Token::kMOD) { |
3145 const intptr_t kNumTemps = 1; | 3103 const intptr_t kNumTemps = 1; |
3146 LocationSummary* summary = new(zone) LocationSummary( | 3104 LocationSummary* summary = new (zone) |
3147 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3105 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3148 // Both inputs must be writable because they will be untagged. | 3106 // Both inputs must be writable because they will be untagged. |
3149 summary->set_in(0, Location::RegisterLocation(RDX)); | 3107 summary->set_in(0, Location::RegisterLocation(RDX)); |
3150 summary->set_in(1, Location::WritableRegister()); | 3108 summary->set_in(1, Location::WritableRegister()); |
3151 summary->set_out(0, Location::SameAsFirstInput()); | 3109 summary->set_out(0, Location::SameAsFirstInput()); |
3152 // Will be used for sign extension and division. | 3110 // Will be used for sign extension and division. |
3153 summary->set_temp(0, Location::RegisterLocation(RAX)); | 3111 summary->set_temp(0, Location::RegisterLocation(RAX)); |
3154 return summary; | 3112 return summary; |
3155 } else if (op_kind() == Token::kSHR) { | 3113 } else if (op_kind() == Token::kSHR) { |
3156 const intptr_t kNumTemps = 0; | 3114 const intptr_t kNumTemps = 0; |
3157 LocationSummary* summary = new(zone) LocationSummary( | 3115 LocationSummary* summary = new (zone) |
3158 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3116 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3159 summary->set_in(0, Location::RequiresRegister()); | 3117 summary->set_in(0, Location::RequiresRegister()); |
3160 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 3118 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
3161 summary->set_out(0, Location::SameAsFirstInput()); | 3119 summary->set_out(0, Location::SameAsFirstInput()); |
3162 return summary; | 3120 return summary; |
3163 } else if (op_kind() == Token::kSHL) { | 3121 } else if (op_kind() == Token::kSHL) { |
3164 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. | 3122 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. |
3165 const bool shiftBy1 = | 3123 const bool shiftBy1 = |
3166 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); | 3124 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); |
3167 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; | 3125 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; |
3168 LocationSummary* summary = new(zone) LocationSummary( | 3126 LocationSummary* summary = new (zone) |
3169 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3127 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3170 summary->set_in(0, Location::RequiresRegister()); | 3128 summary->set_in(0, Location::RequiresRegister()); |
3171 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 3129 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
3172 if (kNumTemps == 1) { | 3130 if (kNumTemps == 1) { |
3173 summary->set_temp(0, Location::RequiresRegister()); | 3131 summary->set_temp(0, Location::RequiresRegister()); |
3174 } | 3132 } |
3175 summary->set_out(0, Location::SameAsFirstInput()); | 3133 summary->set_out(0, Location::SameAsFirstInput()); |
3176 return summary; | 3134 return summary; |
3177 } else { | 3135 } else { |
3178 const intptr_t kNumTemps = 0; | 3136 const intptr_t kNumTemps = 0; |
3179 LocationSummary* summary = new(zone) LocationSummary( | 3137 LocationSummary* summary = new (zone) |
3180 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3181 summary->set_in(0, Location::RequiresRegister()); | 3139 summary->set_in(0, Location::RequiresRegister()); |
3182 ConstantInstr* constant = right()->definition()->AsConstant(); | 3140 ConstantInstr* constant = right()->definition()->AsConstant(); |
3183 if (constant != NULL) { | 3141 if (constant != NULL) { |
3184 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3142 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
3185 } else { | 3143 } else { |
3186 summary->set_in(1, Location::PrefersRegister()); | 3144 summary->set_in(1, Location::PrefersRegister()); |
3187 } | 3145 } |
3188 summary->set_out(0, Location::SameAsFirstInput()); | 3146 summary->set_out(0, Location::SameAsFirstInput()); |
3189 return summary; | 3147 return summary; |
3190 } | 3148 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3259 case Token::kBIT_XOR: { | 3217 case Token::kBIT_XOR: { |
3260 // No overflow check. | 3218 // No overflow check. |
3261 __ XorImmediate(left, Immediate(imm)); | 3219 __ XorImmediate(left, Immediate(imm)); |
3262 break; | 3220 break; |
3263 } | 3221 } |
3264 | 3222 |
3265 case Token::kSHR: { | 3223 case Token::kSHR: { |
3266 // sarq operation masks the count to 6 bits. | 3224 // sarq operation masks the count to 6 bits. |
3267 const intptr_t kCountLimit = 0x3F; | 3225 const intptr_t kCountLimit = 0x3F; |
3268 const intptr_t value = Smi::Cast(constant).Value(); | 3226 const intptr_t value = Smi::Cast(constant).Value(); |
3269 __ sarq(left, Immediate( | 3227 __ sarq(left, |
3270 Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 3228 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
3271 __ SmiTag(left); | 3229 __ SmiTag(left); |
3272 break; | 3230 break; |
3273 } | 3231 } |
3274 | 3232 |
3275 default: | 3233 default: |
3276 UNREACHABLE(); | 3234 UNREACHABLE(); |
3277 break; | 3235 break; |
3278 } | 3236 } |
3279 return; | 3237 return; |
3280 } // locs()->in(1).IsConstant(). | 3238 } // locs()->in(1).IsConstant(). |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3386 __ SmiUntag(right); | 3344 __ SmiUntag(right); |
3387 __ cdq(); | 3345 __ cdq(); |
3388 __ idivl(right); | 3346 __ idivl(right); |
3389 __ movsxd(result, result); | 3347 __ movsxd(result, result); |
3390 __ jmp(&done); | 3348 __ jmp(&done); |
3391 | 3349 |
3392 // Divide using 64bit idiv. | 3350 // Divide using 64bit idiv. |
3393 __ Bind(¬_32bit); | 3351 __ Bind(¬_32bit); |
3394 __ SmiUntag(left); | 3352 __ SmiUntag(left); |
3395 __ SmiUntag(right); | 3353 __ SmiUntag(right); |
3396 __ cqo(); // Sign extend RAX -> RDX:RAX. | 3354 __ cqo(); // Sign extend RAX -> RDX:RAX. |
3397 __ idivq(right); // RAX: quotient, RDX: remainder. | 3355 __ idivq(right); // RAX: quotient, RDX: remainder. |
3398 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3356 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
3399 // case we cannot tag the result. | 3357 // case we cannot tag the result. |
3400 __ CompareImmediate(result, Immediate(0x4000000000000000)); | 3358 __ CompareImmediate(result, Immediate(0x4000000000000000)); |
3401 __ j(EQUAL, deopt); | 3359 __ j(EQUAL, deopt); |
3402 __ Bind(&done); | 3360 __ Bind(&done); |
3403 __ SmiTag(result); | 3361 __ SmiTag(result); |
3404 break; | 3362 break; |
3405 } | 3363 } |
3406 case Token::kMOD: { | 3364 case Token::kMOD: { |
(...skipping 27 matching lines...) Expand all Loading... |
3434 __ cdq(); | 3392 __ cdq(); |
3435 __ idivl(right); | 3393 __ idivl(right); |
3436 __ movsxd(result, result); | 3394 __ movsxd(result, result); |
3437 __ jmp(&div_done); | 3395 __ jmp(&div_done); |
3438 | 3396 |
3439 // Divide using 64bit idiv. | 3397 // Divide using 64bit idiv. |
3440 __ Bind(¬_32bit); | 3398 __ Bind(¬_32bit); |
3441 __ SmiUntag(left); | 3399 __ SmiUntag(left); |
3442 __ SmiUntag(right); | 3400 __ SmiUntag(right); |
3443 __ movq(RAX, RDX); | 3401 __ movq(RAX, RDX); |
3444 __ cqo(); // Sign extend RAX -> RDX:RAX. | 3402 __ cqo(); // Sign extend RAX -> RDX:RAX. |
3445 __ idivq(right); // RAX: quotient, RDX: remainder. | 3403 __ idivq(right); // RAX: quotient, RDX: remainder. |
3446 __ Bind(&div_done); | 3404 __ Bind(&div_done); |
3447 // res = left % right; | 3405 // res = left % right; |
3448 // if (res < 0) { | 3406 // if (res < 0) { |
3449 // if (right < 0) { | 3407 // if (right < 0) { |
3450 // res = res - right; | 3408 // res = res - right; |
3451 // } else { | 3409 // } else { |
3452 // res = res + right; | 3410 // res = res + right; |
3453 // } | 3411 // } |
3454 // } | 3412 // } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3516 } | 3474 } |
3517 } | 3475 } |
3518 | 3476 |
3519 | 3477 |
3520 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3478 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3521 bool opt) const { | 3479 bool opt) const { |
3522 intptr_t left_cid = left()->Type()->ToCid(); | 3480 intptr_t left_cid = left()->Type()->ToCid(); |
3523 intptr_t right_cid = right()->Type()->ToCid(); | 3481 intptr_t right_cid = right()->Type()->ToCid(); |
3524 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3482 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3525 const intptr_t kNumInputs = 2; | 3483 const intptr_t kNumInputs = 2; |
3526 const bool need_temp = (left()->definition() != right()->definition()) | 3484 const bool need_temp = (left()->definition() != right()->definition()) && |
3527 && (left_cid != kSmiCid) | 3485 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
3528 && (right_cid != kSmiCid); | |
3529 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3486 const intptr_t kNumTemps = need_temp ? 1 : 0; |
3530 LocationSummary* summary = new(zone) LocationSummary( | 3487 LocationSummary* summary = new (zone) |
3531 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3532 summary->set_in(0, Location::RequiresRegister()); | 3489 summary->set_in(0, Location::RequiresRegister()); |
3533 summary->set_in(1, Location::RequiresRegister()); | 3490 summary->set_in(1, Location::RequiresRegister()); |
3534 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3491 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
3535 return summary; | 3492 return summary; |
3536 } | 3493 } |
3537 | 3494 |
3538 | 3495 |
3539 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3496 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3540 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3497 Label* deopt = |
3541 ICData::kDeoptBinaryDoubleOp, | 3498 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3542 licm_hoisted_ ? ICData::kHoisted : 0); | 3499 licm_hoisted_ ? ICData::kHoisted : 0); |
3543 intptr_t left_cid = left()->Type()->ToCid(); | 3500 intptr_t left_cid = left()->Type()->ToCid(); |
3544 intptr_t right_cid = right()->Type()->ToCid(); | 3501 intptr_t right_cid = right()->Type()->ToCid(); |
3545 Register left = locs()->in(0).reg(); | 3502 Register left = locs()->in(0).reg(); |
3546 Register right = locs()->in(1).reg(); | 3503 Register right = locs()->in(1).reg(); |
3547 if (this->left()->definition() == this->right()->definition()) { | 3504 if (this->left()->definition() == this->right()->definition()) { |
3548 __ testq(left, Immediate(kSmiTagMask)); | 3505 __ testq(left, Immediate(kSmiTagMask)); |
3549 } else if (left_cid == kSmiCid) { | 3506 } else if (left_cid == kSmiCid) { |
3550 __ testq(right, Immediate(kSmiTagMask)); | 3507 __ testq(right, Immediate(kSmiTagMask)); |
3551 } else if (right_cid == kSmiCid) { | 3508 } else if (right_cid == kSmiCid) { |
3552 __ testq(left, Immediate(kSmiTagMask)); | 3509 __ testq(left, Immediate(kSmiTagMask)); |
3553 } else { | 3510 } else { |
3554 Register temp = locs()->temp(0).reg(); | 3511 Register temp = locs()->temp(0).reg(); |
3555 __ movq(temp, left); | 3512 __ movq(temp, left); |
3556 __ orq(temp, right); | 3513 __ orq(temp, right); |
3557 __ testq(temp, Immediate(kSmiTagMask)); | 3514 __ testq(temp, Immediate(kSmiTagMask)); |
3558 } | 3515 } |
3559 __ j(ZERO, deopt); | 3516 __ j(ZERO, deopt); |
3560 } | 3517 } |
3561 | 3518 |
3562 | 3519 |
3563 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3520 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3564 bool opt) const { | |
3565 const intptr_t kNumInputs = 1; | 3521 const intptr_t kNumInputs = 1; |
3566 const intptr_t kNumTemps = 1; | 3522 const intptr_t kNumTemps = 1; |
3567 LocationSummary* summary = new(zone) LocationSummary( | 3523 LocationSummary* summary = new (zone) LocationSummary( |
3568 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3524 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3569 summary->set_in(0, Location::RequiresFpuRegister()); | 3525 summary->set_in(0, Location::RequiresFpuRegister()); |
3570 summary->set_temp(0, Location::RequiresRegister()); | 3526 summary->set_temp(0, Location::RequiresRegister()); |
3571 summary->set_out(0, Location::RequiresRegister()); | 3527 summary->set_out(0, Location::RequiresRegister()); |
3572 return summary; | 3528 return summary; |
3573 } | 3529 } |
3574 | 3530 |
3575 | 3531 |
3576 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3532 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3577 Register out_reg = locs()->out(0).reg(); | 3533 Register out_reg = locs()->out(0).reg(); |
3578 Register temp = locs()->temp(0).reg(); | 3534 Register temp = locs()->temp(0).reg(); |
3579 XmmRegister value = locs()->in(0).fpu_reg(); | 3535 XmmRegister value = locs()->in(0).fpu_reg(); |
3580 | 3536 |
3581 BoxAllocationSlowPath::Allocate( | 3537 BoxAllocationSlowPath::Allocate(compiler, this, |
3582 compiler, this, compiler->BoxClassFor(from_representation()), out_reg, | 3538 compiler->BoxClassFor(from_representation()), |
3583 temp); | 3539 out_reg, temp); |
3584 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 3540 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
3585 switch (from_representation()) { | 3541 switch (from_representation()) { |
3586 case kUnboxedDouble: | 3542 case kUnboxedDouble: |
3587 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3543 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
3588 break; | 3544 break; |
3589 case kUnboxedFloat32x4: | 3545 case kUnboxedFloat32x4: |
3590 case kUnboxedFloat64x2: | 3546 case kUnboxedFloat64x2: |
3591 case kUnboxedInt32x4: | 3547 case kUnboxedInt32x4: |
3592 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3548 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
3593 break; | 3549 break; |
3594 default: | 3550 default: |
3595 UNREACHABLE(); | 3551 UNREACHABLE(); |
3596 break; | 3552 break; |
3597 } | 3553 } |
3598 } | 3554 } |
3599 | 3555 |
3600 | 3556 |
3601 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3557 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3602 bool opt) const { | |
3603 const intptr_t kNumInputs = 1; | 3558 const intptr_t kNumInputs = 1; |
3604 const intptr_t kNumTemps = 0; | 3559 const intptr_t kNumTemps = 0; |
3605 const bool needs_writable_input = | 3560 const bool needs_writable_input = |
3606 (representation() != kUnboxedMint) && | 3561 (representation() != kUnboxedMint) && |
3607 (value()->Type()->ToNullableCid() != BoxCid()); | 3562 (value()->Type()->ToNullableCid() != BoxCid()); |
3608 LocationSummary* summary = new(zone) LocationSummary( | 3563 LocationSummary* summary = new (zone) |
3609 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3564 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3610 summary->set_in(0, needs_writable_input ? Location::WritableRegister() | 3565 summary->set_in(0, needs_writable_input ? Location::WritableRegister() |
3611 : Location::RequiresRegister()); | 3566 : Location::RequiresRegister()); |
3612 if (representation() == kUnboxedMint) { | 3567 if (representation() == kUnboxedMint) { |
3613 summary->set_out(0, Location::SameAsFirstInput()); | 3568 summary->set_out(0, Location::SameAsFirstInput()); |
3614 } else { | 3569 } else { |
3615 summary->set_out(0, Location::RequiresFpuRegister()); | 3570 summary->set_out(0, Location::RequiresFpuRegister()); |
3616 } | 3571 } |
3617 return summary; | 3572 return summary; |
3618 } | 3573 } |
3619 | 3574 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3677 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3632 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3678 const intptr_t value_cid = value()->Type()->ToCid(); | 3633 const intptr_t value_cid = value()->Type()->ToCid(); |
3679 const intptr_t box_cid = BoxCid(); | 3634 const intptr_t box_cid = BoxCid(); |
3680 | 3635 |
3681 if (value_cid == box_cid) { | 3636 if (value_cid == box_cid) { |
3682 EmitLoadFromBox(compiler); | 3637 EmitLoadFromBox(compiler); |
3683 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3638 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
3684 EmitSmiConversion(compiler); | 3639 EmitSmiConversion(compiler); |
3685 } else { | 3640 } else { |
3686 const Register box = locs()->in(0).reg(); | 3641 const Register box = locs()->in(0).reg(); |
3687 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3642 Label* deopt = |
3688 ICData::kDeoptCheckClass); | 3643 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
3689 Label is_smi; | 3644 Label is_smi; |
3690 | 3645 |
3691 if ((value()->Type()->ToNullableCid() == box_cid) && | 3646 if ((value()->Type()->ToNullableCid() == box_cid) && |
3692 value()->Type()->is_nullable()) { | 3647 value()->Type()->is_nullable()) { |
3693 __ CompareObject(box, Object::null_object()); | 3648 __ CompareObject(box, Object::null_object()); |
3694 __ j(EQUAL, deopt); | 3649 __ j(EQUAL, deopt); |
3695 } else { | 3650 } else { |
3696 __ testq(box, Immediate(kSmiTagMask)); | 3651 __ testq(box, Immediate(kSmiTagMask)); |
3697 __ j(ZERO, CanConvertSmi() ? &is_smi : deopt); | 3652 __ j(ZERO, CanConvertSmi() ? &is_smi : deopt); |
3698 __ CompareClassId(box, box_cid); | 3653 __ CompareClassId(box, box_cid); |
(...skipping 10 matching lines...) Expand all Loading... |
3709 __ Bind(&done); | 3664 __ Bind(&done); |
3710 } | 3665 } |
3711 } | 3666 } |
3712 } | 3667 } |
3713 | 3668 |
3714 | 3669 |
3715 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3670 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
3716 bool opt) const { | 3671 bool opt) const { |
3717 const intptr_t kNumInputs = 1; | 3672 const intptr_t kNumInputs = 1; |
3718 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 3673 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
3719 LocationSummary* summary = new(zone) LocationSummary( | 3674 LocationSummary* summary = new (zone) |
3720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3675 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3721 summary->set_in(0, Location::RequiresRegister()); | 3676 summary->set_in(0, Location::RequiresRegister()); |
3722 summary->set_out(0, Location::SameAsFirstInput()); | 3677 summary->set_out(0, Location::SameAsFirstInput()); |
3723 if (kNumTemps > 0) { | 3678 if (kNumTemps > 0) { |
3724 summary->set_temp(0, Location::RequiresRegister()); | 3679 summary->set_temp(0, Location::RequiresRegister()); |
3725 } | 3680 } |
3726 return summary; | 3681 return summary; |
3727 } | 3682 } |
3728 | 3683 |
3729 | 3684 |
3730 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3685 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3731 const intptr_t value_cid = value()->Type()->ToCid(); | 3686 const intptr_t value_cid = value()->Type()->ToCid(); |
3732 const Register value = locs()->in(0).reg(); | 3687 const Register value = locs()->in(0).reg(); |
3733 Label* deopt = CanDeoptimize() ? | 3688 Label* deopt = |
3734 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3689 CanDeoptimize() |
| 3690 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3691 : NULL; |
3735 ASSERT(value == locs()->out(0).reg()); | 3692 ASSERT(value == locs()->out(0).reg()); |
3736 | 3693 |
3737 if (value_cid == kSmiCid) { | 3694 if (value_cid == kSmiCid) { |
3738 __ SmiUntag(value); | 3695 __ SmiUntag(value); |
3739 } else if (value_cid == kMintCid) { | 3696 } else if (value_cid == kMintCid) { |
3740 __ movq(value, FieldAddress(value, Mint::value_offset())); | 3697 __ movq(value, FieldAddress(value, Mint::value_offset())); |
3741 } else if (!CanDeoptimize()) { | 3698 } else if (!CanDeoptimize()) { |
3742 // Type information is not conclusive, but range analysis found | 3699 // Type information is not conclusive, but range analysis found |
3743 // the value to be in int64 range. Therefore it must be a smi | 3700 // the value to be in int64 range. Therefore it must be a smi |
3744 // or mint value. | 3701 // or mint value. |
(...skipping 20 matching lines...) Expand all Loading... |
3765 ASSERT(representation() == kUnboxedInt32); | 3722 ASSERT(representation() == kUnboxedInt32); |
3766 Register temp = locs()->temp(0).reg(); | 3723 Register temp = locs()->temp(0).reg(); |
3767 __ movsxd(temp, value); | 3724 __ movsxd(temp, value); |
3768 __ cmpq(temp, value); | 3725 __ cmpq(temp, value); |
3769 __ j(NOT_EQUAL, deopt); | 3726 __ j(NOT_EQUAL, deopt); |
3770 } | 3727 } |
3771 } | 3728 } |
3772 | 3729 |
3773 | 3730 |
3774 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3731 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
3775 bool opt) const { | 3732 bool opt) const { |
3776 ASSERT((from_representation() == kUnboxedInt32) || | 3733 ASSERT((from_representation() == kUnboxedInt32) || |
3777 (from_representation() == kUnboxedUint32)); | 3734 (from_representation() == kUnboxedUint32)); |
3778 const intptr_t kNumInputs = 1; | 3735 const intptr_t kNumInputs = 1; |
3779 const intptr_t kNumTemps = 0; | 3736 const intptr_t kNumTemps = 0; |
3780 LocationSummary* summary = new(zone) LocationSummary( | 3737 LocationSummary* summary = new (zone) |
3781 zone, | 3738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3782 kNumInputs, | |
3783 kNumTemps, | |
3784 LocationSummary::kNoCall); | |
3785 summary->set_in(0, Location::RequiresRegister()); | 3739 summary->set_in(0, Location::RequiresRegister()); |
3786 summary->set_out(0, Location::RequiresRegister()); | 3740 summary->set_out(0, Location::RequiresRegister()); |
3787 return summary; | 3741 return summary; |
3788 } | 3742 } |
3789 | 3743 |
3790 | 3744 |
3791 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3745 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3792 const Register value = locs()->in(0).reg(); | 3746 const Register value = locs()->in(0).reg(); |
3793 const Register out = locs()->out(0).reg(); | 3747 const Register out = locs()->out(0).reg(); |
3794 ASSERT(value != out); | 3748 ASSERT(value != out); |
3795 | 3749 |
3796 ASSERT(kSmiTagSize == 1); | 3750 ASSERT(kSmiTagSize == 1); |
3797 if (from_representation() == kUnboxedInt32) { | 3751 if (from_representation() == kUnboxedInt32) { |
3798 __ movsxd(out, value); | 3752 __ movsxd(out, value); |
3799 } else { | 3753 } else { |
3800 ASSERT(from_representation() == kUnboxedUint32); | 3754 ASSERT(from_representation() == kUnboxedUint32); |
3801 __ movl(out, value); | 3755 __ movl(out, value); |
3802 } | 3756 } |
3803 __ SmiTag(out); | 3757 __ SmiTag(out); |
3804 } | 3758 } |
3805 | 3759 |
3806 | 3760 |
3807 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3761 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
3808 bool opt) const { | 3762 bool opt) const { |
3809 const intptr_t kNumInputs = 1; | 3763 const intptr_t kNumInputs = 1; |
3810 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3764 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3811 LocationSummary* summary = new(zone) LocationSummary( | 3765 LocationSummary* summary = new (zone) |
3812 zone, | 3766 LocationSummary(zone, kNumInputs, kNumTemps, |
3813 kNumInputs, | 3767 ValueFitsSmi() ? LocationSummary::kNoCall |
3814 kNumTemps, | 3768 : LocationSummary::kCallOnSlowPath); |
3815 ValueFitsSmi() ? LocationSummary::kNoCall | |
3816 : LocationSummary::kCallOnSlowPath); | |
3817 summary->set_in(0, Location::RequiresRegister()); | 3769 summary->set_in(0, Location::RequiresRegister()); |
3818 if (!ValueFitsSmi()) { | 3770 if (!ValueFitsSmi()) { |
3819 summary->set_temp(0, Location::RequiresRegister()); | 3771 summary->set_temp(0, Location::RequiresRegister()); |
3820 } | 3772 } |
3821 summary->set_out(0, Location::RequiresRegister()); | 3773 summary->set_out(0, Location::RequiresRegister()); |
3822 return summary; | 3774 return summary; |
3823 } | 3775 } |
3824 | 3776 |
3825 | 3777 |
3826 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3778 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3827 const Register out = locs()->out(0).reg(); | 3779 const Register out = locs()->out(0).reg(); |
3828 const Register value = locs()->in(0).reg(); | 3780 const Register value = locs()->in(0).reg(); |
3829 __ MoveRegister(out, value); | 3781 __ MoveRegister(out, value); |
3830 __ SmiTag(out); | 3782 __ SmiTag(out); |
3831 if (!ValueFitsSmi()) { | 3783 if (!ValueFitsSmi()) { |
3832 const Register temp = locs()->temp(0).reg(); | 3784 const Register temp = locs()->temp(0).reg(); |
3833 Label done; | 3785 Label done; |
3834 __ j(NO_OVERFLOW, &done); | 3786 __ j(NO_OVERFLOW, &done); |
3835 BoxAllocationSlowPath::Allocate( | 3787 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
3836 compiler, this, compiler->mint_class(), out, temp); | 3788 temp); |
3837 __ movq(FieldAddress(out, Mint::value_offset()), value); | 3789 __ movq(FieldAddress(out, Mint::value_offset()), value); |
3838 __ Bind(&done); | 3790 __ Bind(&done); |
3839 } | 3791 } |
3840 } | 3792 } |
3841 | 3793 |
3842 | 3794 |
3843 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3795 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
3844 bool opt) const { | 3796 bool opt) const { |
3845 const intptr_t kNumInputs = 2; | 3797 const intptr_t kNumInputs = 2; |
3846 const intptr_t kNumTemps = 0; | 3798 const intptr_t kNumTemps = 0; |
3847 LocationSummary* summary = new(zone) LocationSummary( | 3799 LocationSummary* summary = new (zone) |
3848 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3800 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3849 summary->set_in(0, Location::RequiresFpuRegister()); | 3801 summary->set_in(0, Location::RequiresFpuRegister()); |
3850 summary->set_in(1, Location::RequiresFpuRegister()); | 3802 summary->set_in(1, Location::RequiresFpuRegister()); |
3851 summary->set_out(0, Location::SameAsFirstInput()); | 3803 summary->set_out(0, Location::SameAsFirstInput()); |
3852 return summary; | 3804 return summary; |
3853 } | 3805 } |
3854 | 3806 |
3855 | 3807 |
3856 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3808 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3857 XmmRegister left = locs()->in(0).fpu_reg(); | 3809 XmmRegister left = locs()->in(0).fpu_reg(); |
3858 XmmRegister right = locs()->in(1).fpu_reg(); | 3810 XmmRegister right = locs()->in(1).fpu_reg(); |
3859 | 3811 |
3860 ASSERT(locs()->out(0).fpu_reg() == left); | 3812 ASSERT(locs()->out(0).fpu_reg() == left); |
3861 | 3813 |
3862 switch (op_kind()) { | 3814 switch (op_kind()) { |
3863 case Token::kADD: __ addsd(left, right); break; | 3815 case Token::kADD: |
3864 case Token::kSUB: __ subsd(left, right); break; | 3816 __ addsd(left, right); |
3865 case Token::kMUL: __ mulsd(left, right); break; | 3817 break; |
3866 case Token::kDIV: __ divsd(left, right); break; | 3818 case Token::kSUB: |
3867 default: UNREACHABLE(); | 3819 __ subsd(left, right); |
| 3820 break; |
| 3821 case Token::kMUL: |
| 3822 __ mulsd(left, right); |
| 3823 break; |
| 3824 case Token::kDIV: |
| 3825 __ divsd(left, right); |
| 3826 break; |
| 3827 default: |
| 3828 UNREACHABLE(); |
3868 } | 3829 } |
3869 } | 3830 } |
3870 | 3831 |
3871 | 3832 |
3872 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3833 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
3873 bool opt) const { | 3834 bool opt) const { |
3874 const intptr_t kNumInputs = 1; | 3835 const intptr_t kNumInputs = 1; |
3875 const intptr_t kNumTemps = | 3836 const intptr_t kNumTemps = |
3876 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3837 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
3877 LocationSummary* summary = new(zone) LocationSummary( | 3838 LocationSummary* summary = new (zone) |
3878 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3839 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3879 summary->set_in(0, Location::RequiresFpuRegister()); | 3840 summary->set_in(0, Location::RequiresFpuRegister()); |
3880 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3841 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3881 summary->set_temp(0, Location::RequiresRegister()); | 3842 summary->set_temp(0, Location::RequiresRegister()); |
3882 } | 3843 } |
3883 summary->set_out(0, Location::RequiresRegister()); | 3844 summary->set_out(0, Location::RequiresRegister()); |
3884 return summary; | 3845 return summary; |
3885 } | 3846 } |
3886 | 3847 |
3887 | 3848 |
3888 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3849 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
(...skipping 25 matching lines...) Expand all Loading... |
3914 BranchInstr* branch) { | 3875 BranchInstr* branch) { |
3915 ASSERT(compiler->is_optimizing()); | 3876 ASSERT(compiler->is_optimizing()); |
3916 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3877 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3917 Condition true_condition = EmitComparisonCode(compiler, labels); | 3878 Condition true_condition = EmitComparisonCode(compiler, labels); |
3918 EmitBranchOnCondition(compiler, true_condition, labels); | 3879 EmitBranchOnCondition(compiler, true_condition, labels); |
3919 } | 3880 } |
3920 | 3881 |
3921 | 3882 |
3922 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3883 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3923 Label is_true, is_false; | 3884 Label is_true, is_false; |
3924 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3885 BranchLabels labels = {&is_true, &is_false, &is_false}; |
3925 Condition true_condition = EmitComparisonCode(compiler, labels); | 3886 Condition true_condition = EmitComparisonCode(compiler, labels); |
3926 EmitBranchOnCondition(compiler, true_condition, labels); | 3887 EmitBranchOnCondition(compiler, true_condition, labels); |
3927 | 3888 |
3928 Register result = locs()->out(0).reg(); | 3889 Register result = locs()->out(0).reg(); |
3929 Label done; | 3890 Label done; |
3930 __ Bind(&is_false); | 3891 __ Bind(&is_false); |
3931 __ LoadObject(result, Bool::False()); | 3892 __ LoadObject(result, Bool::False()); |
3932 __ jmp(&done); | 3893 __ jmp(&done); |
3933 __ Bind(&is_true); | 3894 __ Bind(&is_true); |
3934 __ LoadObject(result, Bool::True()); | 3895 __ LoadObject(result, Bool::True()); |
3935 __ Bind(&done); | 3896 __ Bind(&done); |
3936 } | 3897 } |
3937 | 3898 |
3938 | 3899 |
3939 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3900 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3940 bool opt) const { | 3901 bool opt) const { |
3941 const intptr_t kNumInputs = 2; | 3902 const intptr_t kNumInputs = 2; |
3942 const intptr_t kNumTemps = 0; | 3903 const intptr_t kNumTemps = 0; |
3943 LocationSummary* summary = new(zone) LocationSummary( | 3904 LocationSummary* summary = new (zone) |
3944 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3905 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3945 summary->set_in(0, Location::RequiresFpuRegister()); | 3906 summary->set_in(0, Location::RequiresFpuRegister()); |
3946 summary->set_in(1, Location::RequiresFpuRegister()); | 3907 summary->set_in(1, Location::RequiresFpuRegister()); |
3947 summary->set_out(0, Location::SameAsFirstInput()); | 3908 summary->set_out(0, Location::SameAsFirstInput()); |
3948 return summary; | 3909 return summary; |
3949 } | 3910 } |
3950 | 3911 |
3951 | 3912 |
3952 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3913 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3953 XmmRegister left = locs()->in(0).fpu_reg(); | 3914 XmmRegister left = locs()->in(0).fpu_reg(); |
3954 XmmRegister right = locs()->in(1).fpu_reg(); | 3915 XmmRegister right = locs()->in(1).fpu_reg(); |
3955 | 3916 |
3956 ASSERT(locs()->out(0).fpu_reg() == left); | 3917 ASSERT(locs()->out(0).fpu_reg() == left); |
3957 | 3918 |
3958 switch (op_kind()) { | 3919 switch (op_kind()) { |
3959 case Token::kADD: __ addps(left, right); break; | 3920 case Token::kADD: |
3960 case Token::kSUB: __ subps(left, right); break; | 3921 __ addps(left, right); |
3961 case Token::kMUL: __ mulps(left, right); break; | 3922 break; |
3962 case Token::kDIV: __ divps(left, right); break; | 3923 case Token::kSUB: |
3963 default: UNREACHABLE(); | 3924 __ subps(left, right); |
| 3925 break; |
| 3926 case Token::kMUL: |
| 3927 __ mulps(left, right); |
| 3928 break; |
| 3929 case Token::kDIV: |
| 3930 __ divps(left, right); |
| 3931 break; |
| 3932 default: |
| 3933 UNREACHABLE(); |
3964 } | 3934 } |
3965 } | 3935 } |
3966 | 3936 |
3967 | 3937 |
3968 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3938 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
3969 bool opt) const { | 3939 bool opt) const { |
3970 const intptr_t kNumInputs = 2; | 3940 const intptr_t kNumInputs = 2; |
3971 const intptr_t kNumTemps = 0; | 3941 const intptr_t kNumTemps = 0; |
3972 LocationSummary* summary = new(zone) LocationSummary( | 3942 LocationSummary* summary = new (zone) |
3973 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3974 summary->set_in(0, Location::RequiresFpuRegister()); | 3944 summary->set_in(0, Location::RequiresFpuRegister()); |
3975 summary->set_in(1, Location::RequiresFpuRegister()); | 3945 summary->set_in(1, Location::RequiresFpuRegister()); |
3976 summary->set_out(0, Location::SameAsFirstInput()); | 3946 summary->set_out(0, Location::SameAsFirstInput()); |
3977 return summary; | 3947 return summary; |
3978 } | 3948 } |
3979 | 3949 |
3980 | 3950 |
3981 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3951 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3982 XmmRegister left = locs()->in(0).fpu_reg(); | 3952 XmmRegister left = locs()->in(0).fpu_reg(); |
3983 XmmRegister right = locs()->in(1).fpu_reg(); | 3953 XmmRegister right = locs()->in(1).fpu_reg(); |
3984 | 3954 |
3985 ASSERT(locs()->out(0).fpu_reg() == left); | 3955 ASSERT(locs()->out(0).fpu_reg() == left); |
3986 | 3956 |
3987 switch (op_kind()) { | 3957 switch (op_kind()) { |
3988 case Token::kADD: __ addpd(left, right); break; | 3958 case Token::kADD: |
3989 case Token::kSUB: __ subpd(left, right); break; | 3959 __ addpd(left, right); |
3990 case Token::kMUL: __ mulpd(left, right); break; | 3960 break; |
3991 case Token::kDIV: __ divpd(left, right); break; | 3961 case Token::kSUB: |
3992 default: UNREACHABLE(); | 3962 __ subpd(left, right); |
| 3963 break; |
| 3964 case Token::kMUL: |
| 3965 __ mulpd(left, right); |
| 3966 break; |
| 3967 case Token::kDIV: |
| 3968 __ divpd(left, right); |
| 3969 break; |
| 3970 default: |
| 3971 UNREACHABLE(); |
3993 } | 3972 } |
3994 } | 3973 } |
3995 | 3974 |
3996 | 3975 |
3997 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3976 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
3998 bool opt) const { | 3977 bool opt) const { |
3999 const intptr_t kNumInputs = 1; | 3978 const intptr_t kNumInputs = 1; |
4000 const intptr_t kNumTemps = 0; | 3979 const intptr_t kNumTemps = 0; |
4001 LocationSummary* summary = new(zone) LocationSummary( | 3980 LocationSummary* summary = new (zone) |
4002 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3981 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4003 summary->set_in(0, Location::RequiresFpuRegister()); | 3982 summary->set_in(0, Location::RequiresFpuRegister()); |
4004 summary->set_out(0, Location::SameAsFirstInput()); | 3983 summary->set_out(0, Location::SameAsFirstInput()); |
4005 return summary; | 3984 return summary; |
4006 } | 3985 } |
4007 | 3986 |
4008 | 3987 |
4009 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3988 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4010 XmmRegister value = locs()->in(0).fpu_reg(); | 3989 XmmRegister value = locs()->in(0).fpu_reg(); |
4011 | 3990 |
4012 ASSERT(locs()->out(0).fpu_reg() == value); | 3991 ASSERT(locs()->out(0).fpu_reg() == value); |
(...skipping 12 matching lines...) Expand all Loading... |
4025 __ cvtss2sd(value, value); | 4004 __ cvtss2sd(value, value); |
4026 break; | 4005 break; |
4027 case MethodRecognizer::kFloat32x4ShuffleW: | 4006 case MethodRecognizer::kFloat32x4ShuffleW: |
4028 __ shufps(value, value, Immediate(0xFF)); | 4007 __ shufps(value, value, Immediate(0xFF)); |
4029 __ cvtss2sd(value, value); | 4008 __ cvtss2sd(value, value); |
4030 break; | 4009 break; |
4031 case MethodRecognizer::kFloat32x4Shuffle: | 4010 case MethodRecognizer::kFloat32x4Shuffle: |
4032 case MethodRecognizer::kInt32x4Shuffle: | 4011 case MethodRecognizer::kInt32x4Shuffle: |
4033 __ shufps(value, value, Immediate(mask_)); | 4012 __ shufps(value, value, Immediate(mask_)); |
4034 break; | 4013 break; |
4035 default: UNREACHABLE(); | 4014 default: |
| 4015 UNREACHABLE(); |
4036 } | 4016 } |
4037 } | 4017 } |
4038 | 4018 |
4039 | 4019 |
4040 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 4020 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
4041 bool opt) const { | 4021 bool opt) const { |
4042 const intptr_t kNumInputs = 2; | 4022 const intptr_t kNumInputs = 2; |
4043 const intptr_t kNumTemps = 0; | 4023 const intptr_t kNumTemps = 0; |
4044 LocationSummary* summary = new(zone) LocationSummary( | 4024 LocationSummary* summary = new (zone) |
4045 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4025 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4046 summary->set_in(0, Location::RequiresFpuRegister()); | 4026 summary->set_in(0, Location::RequiresFpuRegister()); |
4047 summary->set_in(1, Location::RequiresFpuRegister()); | 4027 summary->set_in(1, Location::RequiresFpuRegister()); |
4048 summary->set_out(0, Location::SameAsFirstInput()); | 4028 summary->set_out(0, Location::SameAsFirstInput()); |
4049 return summary; | 4029 return summary; |
4050 } | 4030 } |
4051 | 4031 |
4052 | 4032 |
4053 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4033 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4054 XmmRegister left = locs()->in(0).fpu_reg(); | 4034 XmmRegister left = locs()->in(0).fpu_reg(); |
4055 XmmRegister right = locs()->in(1).fpu_reg(); | 4035 XmmRegister right = locs()->in(1).fpu_reg(); |
4056 | 4036 |
4057 ASSERT(locs()->out(0).fpu_reg() == left); | 4037 ASSERT(locs()->out(0).fpu_reg() == left); |
4058 switch (op_kind()) { | 4038 switch (op_kind()) { |
4059 case MethodRecognizer::kFloat32x4ShuffleMix: | 4039 case MethodRecognizer::kFloat32x4ShuffleMix: |
4060 case MethodRecognizer::kInt32x4ShuffleMix: | 4040 case MethodRecognizer::kInt32x4ShuffleMix: |
4061 __ shufps(left, right, Immediate(mask_)); | 4041 __ shufps(left, right, Immediate(mask_)); |
4062 break; | 4042 break; |
4063 default: UNREACHABLE(); | 4043 default: |
| 4044 UNREACHABLE(); |
4064 } | 4045 } |
4065 } | 4046 } |
4066 | 4047 |
4067 | 4048 |
4068 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 4049 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
4069 bool opt) const { | 4050 bool opt) const { |
4070 const intptr_t kNumInputs = 1; | 4051 const intptr_t kNumInputs = 1; |
4071 const intptr_t kNumTemps = 0; | 4052 const intptr_t kNumTemps = 0; |
4072 LocationSummary* summary = new(zone) LocationSummary( | 4053 LocationSummary* summary = new (zone) |
4073 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4074 summary->set_in(0, Location::RequiresFpuRegister()); | 4055 summary->set_in(0, Location::RequiresFpuRegister()); |
4075 summary->set_out(0, Location::RequiresRegister()); | 4056 summary->set_out(0, Location::RequiresRegister()); |
4076 return summary; | 4057 return summary; |
4077 } | 4058 } |
4078 | 4059 |
4079 | 4060 |
4080 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4061 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4081 XmmRegister value = locs()->in(0).fpu_reg(); | 4062 XmmRegister value = locs()->in(0).fpu_reg(); |
4082 Register out = locs()->out(0).reg(); | 4063 Register out = locs()->out(0).reg(); |
4083 | 4064 |
4084 __ movmskps(out, value); | 4065 __ movmskps(out, value); |
4085 __ SmiTag(out); | 4066 __ SmiTag(out); |
4086 } | 4067 } |
4087 | 4068 |
4088 | 4069 |
4089 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4070 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
4090 Zone* zone, bool opt) const { | 4071 Zone* zone, |
| 4072 bool opt) const { |
4091 const intptr_t kNumInputs = 4; | 4073 const intptr_t kNumInputs = 4; |
4092 const intptr_t kNumTemps = 0; | 4074 const intptr_t kNumTemps = 0; |
4093 LocationSummary* summary = new(zone) LocationSummary( | 4075 LocationSummary* summary = new (zone) |
4094 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4095 summary->set_in(0, Location::RequiresFpuRegister()); | 4077 summary->set_in(0, Location::RequiresFpuRegister()); |
4096 summary->set_in(1, Location::RequiresFpuRegister()); | 4078 summary->set_in(1, Location::RequiresFpuRegister()); |
4097 summary->set_in(2, Location::RequiresFpuRegister()); | 4079 summary->set_in(2, Location::RequiresFpuRegister()); |
4098 summary->set_in(3, Location::RequiresFpuRegister()); | 4080 summary->set_in(3, Location::RequiresFpuRegister()); |
4099 summary->set_out(0, Location::SameAsFirstInput()); | 4081 summary->set_out(0, Location::SameAsFirstInput()); |
4100 return summary; | 4082 return summary; |
4101 } | 4083 } |
4102 | 4084 |
4103 | 4085 |
4104 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4086 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 16 matching lines...) Expand all Loading... |
4121 __ movss(Address(RSP, 12), v0); | 4103 __ movss(Address(RSP, 12), v0); |
4122 __ movups(v0, Address(RSP, 0)); | 4104 __ movups(v0, Address(RSP, 0)); |
4123 __ AddImmediate(RSP, Immediate(16)); | 4105 __ AddImmediate(RSP, Immediate(16)); |
4124 } | 4106 } |
4125 | 4107 |
4126 | 4108 |
4127 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 4109 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
4128 bool opt) const { | 4110 bool opt) const { |
4129 const intptr_t kNumInputs = 0; | 4111 const intptr_t kNumInputs = 0; |
4130 const intptr_t kNumTemps = 0; | 4112 const intptr_t kNumTemps = 0; |
4131 LocationSummary* summary = new(zone) LocationSummary( | 4113 LocationSummary* summary = new (zone) |
4132 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4133 summary->set_out(0, Location::RequiresFpuRegister()); | 4115 summary->set_out(0, Location::RequiresFpuRegister()); |
4134 return summary; | 4116 return summary; |
4135 } | 4117 } |
4136 | 4118 |
4137 | 4119 |
4138 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4120 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4139 XmmRegister value = locs()->out(0).fpu_reg(); | 4121 XmmRegister value = locs()->out(0).fpu_reg(); |
4140 __ xorps(value, value); | 4122 __ xorps(value, value); |
4141 } | 4123 } |
4142 | 4124 |
4143 | 4125 |
4144 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4126 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
4145 bool opt) const { | 4127 bool opt) const { |
4146 const intptr_t kNumInputs = 1; | 4128 const intptr_t kNumInputs = 1; |
4147 const intptr_t kNumTemps = 0; | 4129 const intptr_t kNumTemps = 0; |
4148 LocationSummary* summary = new(zone) LocationSummary( | 4130 LocationSummary* summary = new (zone) |
4149 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4131 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4150 summary->set_in(0, Location::RequiresFpuRegister()); | 4132 summary->set_in(0, Location::RequiresFpuRegister()); |
4151 summary->set_out(0, Location::SameAsFirstInput()); | 4133 summary->set_out(0, Location::SameAsFirstInput()); |
4152 return summary; | 4134 return summary; |
4153 } | 4135 } |
4154 | 4136 |
4155 | 4137 |
4156 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4138 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4157 XmmRegister value = locs()->out(0).fpu_reg(); | 4139 XmmRegister value = locs()->out(0).fpu_reg(); |
4158 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 4140 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
4159 // Convert to Float32. | 4141 // Convert to Float32. |
4160 __ cvtsd2ss(value, value); | 4142 __ cvtsd2ss(value, value); |
4161 // Splat across all lanes. | 4143 // Splat across all lanes. |
4162 __ shufps(value, value, Immediate(0x00)); | 4144 __ shufps(value, value, Immediate(0x00)); |
4163 } | 4145 } |
4164 | 4146 |
4165 | 4147 |
4166 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4148 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
4167 bool opt) const { | 4149 bool opt) const { |
4168 const intptr_t kNumInputs = 2; | 4150 const intptr_t kNumInputs = 2; |
4169 const intptr_t kNumTemps = 0; | 4151 const intptr_t kNumTemps = 0; |
4170 LocationSummary* summary = new(zone) LocationSummary( | 4152 LocationSummary* summary = new (zone) |
4171 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4153 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4172 summary->set_in(0, Location::RequiresFpuRegister()); | 4154 summary->set_in(0, Location::RequiresFpuRegister()); |
4173 summary->set_in(1, Location::RequiresFpuRegister()); | 4155 summary->set_in(1, Location::RequiresFpuRegister()); |
4174 summary->set_out(0, Location::SameAsFirstInput()); | 4156 summary->set_out(0, Location::SameAsFirstInput()); |
4175 return summary; | 4157 return summary; |
4176 } | 4158 } |
4177 | 4159 |
4178 | 4160 |
4179 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4161 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4180 XmmRegister left = locs()->in(0).fpu_reg(); | 4162 XmmRegister left = locs()->in(0).fpu_reg(); |
4181 XmmRegister right = locs()->in(1).fpu_reg(); | 4163 XmmRegister right = locs()->in(1).fpu_reg(); |
(...skipping 13 matching lines...) Expand all Loading... |
4195 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 4177 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
4196 __ cmppsnlt(left, right); | 4178 __ cmppsnlt(left, right); |
4197 break; | 4179 break; |
4198 case MethodRecognizer::kFloat32x4LessThan: | 4180 case MethodRecognizer::kFloat32x4LessThan: |
4199 __ cmppslt(left, right); | 4181 __ cmppslt(left, right); |
4200 break; | 4182 break; |
4201 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4183 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
4202 __ cmppsle(left, right); | 4184 __ cmppsle(left, right); |
4203 break; | 4185 break; |
4204 | 4186 |
4205 default: UNREACHABLE(); | 4187 default: |
| 4188 UNREACHABLE(); |
4206 } | 4189 } |
4207 } | 4190 } |
4208 | 4191 |
4209 | 4192 |
4210 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4193 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
4211 bool opt) const { | 4194 bool opt) const { |
4212 const intptr_t kNumInputs = 2; | 4195 const intptr_t kNumInputs = 2; |
4213 const intptr_t kNumTemps = 0; | 4196 const intptr_t kNumTemps = 0; |
4214 LocationSummary* summary = new(zone) LocationSummary( | 4197 LocationSummary* summary = new (zone) |
4215 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4198 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4216 summary->set_in(0, Location::RequiresFpuRegister()); | 4199 summary->set_in(0, Location::RequiresFpuRegister()); |
4217 summary->set_in(1, Location::RequiresFpuRegister()); | 4200 summary->set_in(1, Location::RequiresFpuRegister()); |
4218 summary->set_out(0, Location::SameAsFirstInput()); | 4201 summary->set_out(0, Location::SameAsFirstInput()); |
4219 return summary; | 4202 return summary; |
4220 } | 4203 } |
4221 | 4204 |
4222 | 4205 |
4223 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4206 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4224 XmmRegister left = locs()->in(0).fpu_reg(); | 4207 XmmRegister left = locs()->in(0).fpu_reg(); |
4225 XmmRegister right = locs()->in(1).fpu_reg(); | 4208 XmmRegister right = locs()->in(1).fpu_reg(); |
4226 | 4209 |
4227 ASSERT(locs()->out(0).fpu_reg() == left); | 4210 ASSERT(locs()->out(0).fpu_reg() == left); |
4228 | 4211 |
4229 switch (op_kind()) { | 4212 switch (op_kind()) { |
4230 case MethodRecognizer::kFloat32x4Min: | 4213 case MethodRecognizer::kFloat32x4Min: |
4231 __ minps(left, right); | 4214 __ minps(left, right); |
4232 break; | 4215 break; |
4233 case MethodRecognizer::kFloat32x4Max: | 4216 case MethodRecognizer::kFloat32x4Max: |
4234 __ maxps(left, right); | 4217 __ maxps(left, right); |
4235 break; | 4218 break; |
4236 default: UNREACHABLE(); | 4219 default: |
| 4220 UNREACHABLE(); |
4237 } | 4221 } |
4238 } | 4222 } |
4239 | 4223 |
4240 | 4224 |
4241 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4225 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
4242 bool opt) const { | 4226 bool opt) const { |
4243 const intptr_t kNumInputs = 2; | 4227 const intptr_t kNumInputs = 2; |
4244 const intptr_t kNumTemps = 0; | 4228 const intptr_t kNumTemps = 0; |
4245 LocationSummary* summary = new(zone) LocationSummary( | 4229 LocationSummary* summary = new (zone) |
4246 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4247 summary->set_in(0, Location::RequiresFpuRegister()); | 4231 summary->set_in(0, Location::RequiresFpuRegister()); |
4248 summary->set_in(1, Location::RequiresFpuRegister()); | 4232 summary->set_in(1, Location::RequiresFpuRegister()); |
4249 summary->set_out(0, Location::SameAsFirstInput()); | 4233 summary->set_out(0, Location::SameAsFirstInput()); |
4250 return summary; | 4234 return summary; |
4251 } | 4235 } |
4252 | 4236 |
4253 | 4237 |
4254 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4238 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4255 XmmRegister left = locs()->in(0).fpu_reg(); | 4239 XmmRegister left = locs()->in(0).fpu_reg(); |
4256 XmmRegister right = locs()->in(1).fpu_reg(); | 4240 XmmRegister right = locs()->in(1).fpu_reg(); |
4257 | 4241 |
4258 ASSERT(locs()->out(0).fpu_reg() == left); | 4242 ASSERT(locs()->out(0).fpu_reg() == left); |
4259 | 4243 |
4260 switch (op_kind()) { | 4244 switch (op_kind()) { |
4261 case MethodRecognizer::kFloat32x4Scale: | 4245 case MethodRecognizer::kFloat32x4Scale: |
4262 __ cvtsd2ss(left, left); | 4246 __ cvtsd2ss(left, left); |
4263 __ shufps(left, left, Immediate(0x00)); | 4247 __ shufps(left, left, Immediate(0x00)); |
4264 __ mulps(left, right); | 4248 __ mulps(left, right); |
4265 break; | 4249 break; |
4266 default: UNREACHABLE(); | 4250 default: |
| 4251 UNREACHABLE(); |
4267 } | 4252 } |
4268 } | 4253 } |
4269 | 4254 |
4270 | 4255 |
4271 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4256 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
4272 bool opt) const { | 4257 bool opt) const { |
4273 const intptr_t kNumInputs = 1; | 4258 const intptr_t kNumInputs = 1; |
4274 const intptr_t kNumTemps = 0; | 4259 const intptr_t kNumTemps = 0; |
4275 LocationSummary* summary = new(zone) LocationSummary( | 4260 LocationSummary* summary = new (zone) |
4276 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4261 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4277 summary->set_in(0, Location::RequiresFpuRegister()); | 4262 summary->set_in(0, Location::RequiresFpuRegister()); |
4278 summary->set_out(0, Location::SameAsFirstInput()); | 4263 summary->set_out(0, Location::SameAsFirstInput()); |
4279 return summary; | 4264 return summary; |
4280 } | 4265 } |
4281 | 4266 |
4282 | 4267 |
4283 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4268 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4284 XmmRegister left = locs()->in(0).fpu_reg(); | 4269 XmmRegister left = locs()->in(0).fpu_reg(); |
4285 | 4270 |
4286 ASSERT(locs()->out(0).fpu_reg() == left); | 4271 ASSERT(locs()->out(0).fpu_reg() == left); |
4287 | 4272 |
4288 switch (op_kind()) { | 4273 switch (op_kind()) { |
4289 case MethodRecognizer::kFloat32x4Sqrt: | 4274 case MethodRecognizer::kFloat32x4Sqrt: |
4290 __ sqrtps(left); | 4275 __ sqrtps(left); |
4291 break; | 4276 break; |
4292 case MethodRecognizer::kFloat32x4Reciprocal: | 4277 case MethodRecognizer::kFloat32x4Reciprocal: |
4293 __ reciprocalps(left); | 4278 __ reciprocalps(left); |
4294 break; | 4279 break; |
4295 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4280 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4296 __ rsqrtps(left); | 4281 __ rsqrtps(left); |
4297 break; | 4282 break; |
4298 default: UNREACHABLE(); | 4283 default: |
| 4284 UNREACHABLE(); |
4299 } | 4285 } |
4300 } | 4286 } |
4301 | 4287 |
4302 | 4288 |
4303 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4289 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4304 bool opt) const { | 4290 bool opt) const { |
4305 const intptr_t kNumInputs = 1; | 4291 const intptr_t kNumInputs = 1; |
4306 const intptr_t kNumTemps = 0; | 4292 const intptr_t kNumTemps = 0; |
4307 LocationSummary* summary = new(zone) LocationSummary( | 4293 LocationSummary* summary = new (zone) |
4308 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4294 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4309 summary->set_in(0, Location::RequiresFpuRegister()); | 4295 summary->set_in(0, Location::RequiresFpuRegister()); |
4310 summary->set_out(0, Location::SameAsFirstInput()); | 4296 summary->set_out(0, Location::SameAsFirstInput()); |
4311 return summary; | 4297 return summary; |
4312 } | 4298 } |
4313 | 4299 |
4314 | 4300 |
4315 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4301 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4316 XmmRegister left = locs()->in(0).fpu_reg(); | 4302 XmmRegister left = locs()->in(0).fpu_reg(); |
4317 | 4303 |
4318 ASSERT(locs()->out(0).fpu_reg() == left); | 4304 ASSERT(locs()->out(0).fpu_reg() == left); |
4319 switch (op_kind()) { | 4305 switch (op_kind()) { |
4320 case MethodRecognizer::kFloat32x4Negate: | 4306 case MethodRecognizer::kFloat32x4Negate: |
4321 __ negateps(left); | 4307 __ negateps(left); |
4322 break; | 4308 break; |
4323 case MethodRecognizer::kFloat32x4Absolute: | 4309 case MethodRecognizer::kFloat32x4Absolute: |
4324 __ absps(left); | 4310 __ absps(left); |
4325 break; | 4311 break; |
4326 default: UNREACHABLE(); | 4312 default: |
| 4313 UNREACHABLE(); |
4327 } | 4314 } |
4328 } | 4315 } |
4329 | 4316 |
4330 | 4317 |
4331 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4318 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
4332 bool opt) const { | 4319 bool opt) const { |
4333 const intptr_t kNumInputs = 3; | 4320 const intptr_t kNumInputs = 3; |
4334 const intptr_t kNumTemps = 0; | 4321 const intptr_t kNumTemps = 0; |
4335 LocationSummary* summary = new(zone) LocationSummary( | 4322 LocationSummary* summary = new (zone) |
4336 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4337 summary->set_in(0, Location::RequiresFpuRegister()); | 4324 summary->set_in(0, Location::RequiresFpuRegister()); |
4338 summary->set_in(1, Location::RequiresFpuRegister()); | 4325 summary->set_in(1, Location::RequiresFpuRegister()); |
4339 summary->set_in(2, Location::RequiresFpuRegister()); | 4326 summary->set_in(2, Location::RequiresFpuRegister()); |
4340 summary->set_out(0, Location::SameAsFirstInput()); | 4327 summary->set_out(0, Location::SameAsFirstInput()); |
4341 return summary; | 4328 return summary; |
4342 } | 4329 } |
4343 | 4330 |
4344 | 4331 |
4345 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4332 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4346 XmmRegister left = locs()->in(0).fpu_reg(); | 4333 XmmRegister left = locs()->in(0).fpu_reg(); |
4347 XmmRegister lower = locs()->in(1).fpu_reg(); | 4334 XmmRegister lower = locs()->in(1).fpu_reg(); |
4348 XmmRegister upper = locs()->in(2).fpu_reg(); | 4335 XmmRegister upper = locs()->in(2).fpu_reg(); |
4349 ASSERT(locs()->out(0).fpu_reg() == left); | 4336 ASSERT(locs()->out(0).fpu_reg() == left); |
4350 __ minps(left, upper); | 4337 __ minps(left, upper); |
4351 __ maxps(left, lower); | 4338 __ maxps(left, lower); |
4352 } | 4339 } |
4353 | 4340 |
4354 | 4341 |
4355 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4342 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
4356 bool opt) const { | 4343 bool opt) const { |
4357 const intptr_t kNumInputs = 2; | 4344 const intptr_t kNumInputs = 2; |
4358 const intptr_t kNumTemps = 0; | 4345 const intptr_t kNumTemps = 0; |
4359 LocationSummary* summary = new(zone) LocationSummary( | 4346 LocationSummary* summary = new (zone) |
4360 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4347 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4361 summary->set_in(0, Location::RequiresFpuRegister()); | 4348 summary->set_in(0, Location::RequiresFpuRegister()); |
4362 summary->set_in(1, Location::RequiresFpuRegister()); | 4349 summary->set_in(1, Location::RequiresFpuRegister()); |
4363 summary->set_out(0, Location::SameAsFirstInput()); | 4350 summary->set_out(0, Location::SameAsFirstInput()); |
4364 return summary; | 4351 return summary; |
4365 } | 4352 } |
4366 | 4353 |
4367 | 4354 |
4368 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4355 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4369 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4356 XmmRegister replacement = locs()->in(0).fpu_reg(); |
4370 XmmRegister value = locs()->in(1).fpu_reg(); | 4357 XmmRegister value = locs()->in(1).fpu_reg(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4409 __ cvtsd2ss(replacement, replacement); | 4396 __ cvtsd2ss(replacement, replacement); |
4410 __ AddImmediate(RSP, Immediate(-16)); | 4397 __ AddImmediate(RSP, Immediate(-16)); |
4411 // Move value to stack. | 4398 // Move value to stack. |
4412 __ movups(Address(RSP, 0), value); | 4399 __ movups(Address(RSP, 0), value); |
4413 // Write over W value. | 4400 // Write over W value. |
4414 __ movss(Address(RSP, 12), replacement); | 4401 __ movss(Address(RSP, 12), replacement); |
4415 // Move updated value into output register. | 4402 // Move updated value into output register. |
4416 __ movups(replacement, Address(RSP, 0)); | 4403 __ movups(replacement, Address(RSP, 0)); |
4417 __ AddImmediate(RSP, Immediate(16)); | 4404 __ AddImmediate(RSP, Immediate(16)); |
4418 break; | 4405 break; |
4419 default: UNREACHABLE(); | 4406 default: |
| 4407 UNREACHABLE(); |
4420 } | 4408 } |
4421 } | 4409 } |
4422 | 4410 |
4423 | 4411 |
4424 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4412 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
4425 bool opt) const { | 4413 bool opt) const { |
4426 const intptr_t kNumInputs = 1; | 4414 const intptr_t kNumInputs = 1; |
4427 const intptr_t kNumTemps = 0; | 4415 const intptr_t kNumTemps = 0; |
4428 LocationSummary* summary = new(zone) LocationSummary( | 4416 LocationSummary* summary = new (zone) |
4429 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4417 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4430 summary->set_in(0, Location::RequiresFpuRegister()); | 4418 summary->set_in(0, Location::RequiresFpuRegister()); |
4431 summary->set_out(0, Location::SameAsFirstInput()); | 4419 summary->set_out(0, Location::SameAsFirstInput()); |
4432 return summary; | 4420 return summary; |
4433 } | 4421 } |
4434 | 4422 |
4435 | 4423 |
4436 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4424 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4437 // NOP. | 4425 // NOP. |
4438 } | 4426 } |
4439 | 4427 |
4440 | 4428 |
4441 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4429 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
4442 bool opt) const { | 4430 bool opt) const { |
4443 const intptr_t kNumInputs = 1; | 4431 const intptr_t kNumInputs = 1; |
4444 const intptr_t kNumTemps = 0; | 4432 const intptr_t kNumTemps = 0; |
4445 LocationSummary* summary = new(zone) LocationSummary( | 4433 LocationSummary* summary = new (zone) |
4446 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4434 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4447 summary->set_in(0, Location::RequiresFpuRegister()); | 4435 summary->set_in(0, Location::RequiresFpuRegister()); |
4448 summary->set_out(0, Location::SameAsFirstInput()); | 4436 summary->set_out(0, Location::SameAsFirstInput()); |
4449 return summary; | 4437 return summary; |
4450 } | 4438 } |
4451 | 4439 |
4452 | 4440 |
4453 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4441 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4454 XmmRegister value = locs()->in(0).fpu_reg(); | 4442 XmmRegister value = locs()->in(0).fpu_reg(); |
4455 | 4443 |
4456 ASSERT(locs()->out(0).fpu_reg() == value); | 4444 ASSERT(locs()->out(0).fpu_reg() == value); |
4457 switch (op_kind()) { | 4445 switch (op_kind()) { |
4458 case MethodRecognizer::kFloat64x2GetX: | 4446 case MethodRecognizer::kFloat64x2GetX: |
4459 // nop. | 4447 // nop. |
4460 break; | 4448 break; |
4461 case MethodRecognizer::kFloat64x2GetY: | 4449 case MethodRecognizer::kFloat64x2GetY: |
4462 __ shufpd(value, value, Immediate(0x33)); | 4450 __ shufpd(value, value, Immediate(0x33)); |
4463 break; | 4451 break; |
4464 default: UNREACHABLE(); | 4452 default: |
| 4453 UNREACHABLE(); |
4465 } | 4454 } |
4466 } | 4455 } |
4467 | 4456 |
4468 | 4457 |
4469 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4458 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
4470 bool opt) const { | 4459 bool opt) const { |
4471 const intptr_t kNumInputs = 0; | 4460 const intptr_t kNumInputs = 0; |
4472 const intptr_t kNumTemps = 0; | 4461 const intptr_t kNumTemps = 0; |
4473 LocationSummary* summary = new(zone) LocationSummary( | 4462 LocationSummary* summary = new (zone) |
4474 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4463 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4475 summary->set_out(0, Location::RequiresFpuRegister()); | 4464 summary->set_out(0, Location::RequiresFpuRegister()); |
4476 return summary; | 4465 return summary; |
4477 } | 4466 } |
4478 | 4467 |
4479 | 4468 |
4480 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4469 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4481 XmmRegister value = locs()->out(0).fpu_reg(); | 4470 XmmRegister value = locs()->out(0).fpu_reg(); |
4482 __ xorpd(value, value); | 4471 __ xorpd(value, value); |
4483 } | 4472 } |
4484 | 4473 |
4485 | 4474 |
4486 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4475 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
4487 bool opt) const { | 4476 bool opt) const { |
4488 const intptr_t kNumInputs = 1; | 4477 const intptr_t kNumInputs = 1; |
4489 const intptr_t kNumTemps = 0; | 4478 const intptr_t kNumTemps = 0; |
4490 LocationSummary* summary = new(zone) LocationSummary( | 4479 LocationSummary* summary = new (zone) |
4491 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4480 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4492 summary->set_in(0, Location::RequiresFpuRegister()); | 4481 summary->set_in(0, Location::RequiresFpuRegister()); |
4493 summary->set_out(0, Location::SameAsFirstInput()); | 4482 summary->set_out(0, Location::SameAsFirstInput()); |
4494 return summary; | 4483 return summary; |
4495 } | 4484 } |
4496 | 4485 |
4497 | 4486 |
4498 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4487 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4499 XmmRegister value = locs()->out(0).fpu_reg(); | 4488 XmmRegister value = locs()->out(0).fpu_reg(); |
4500 __ shufpd(value, value, Immediate(0x0)); | 4489 __ shufpd(value, value, Immediate(0x0)); |
4501 } | 4490 } |
4502 | 4491 |
4503 | 4492 |
4504 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4493 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4505 Zone* zone, bool opt) const { | 4494 Zone* zone, |
| 4495 bool opt) const { |
4506 const intptr_t kNumInputs = 2; | 4496 const intptr_t kNumInputs = 2; |
4507 const intptr_t kNumTemps = 0; | 4497 const intptr_t kNumTemps = 0; |
4508 LocationSummary* summary = new(zone) LocationSummary( | 4498 LocationSummary* summary = new (zone) |
4509 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4499 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4510 summary->set_in(0, Location::RequiresFpuRegister()); | 4500 summary->set_in(0, Location::RequiresFpuRegister()); |
4511 summary->set_in(1, Location::RequiresFpuRegister()); | 4501 summary->set_in(1, Location::RequiresFpuRegister()); |
4512 summary->set_out(0, Location::SameAsFirstInput()); | 4502 summary->set_out(0, Location::SameAsFirstInput()); |
4513 return summary; | 4503 return summary; |
4514 } | 4504 } |
4515 | 4505 |
4516 | 4506 |
4517 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4507 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4518 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4508 XmmRegister v0 = locs()->in(0).fpu_reg(); |
4519 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4509 XmmRegister v1 = locs()->in(1).fpu_reg(); |
4520 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4510 ASSERT(v0 == locs()->out(0).fpu_reg()); |
4521 // shufpd mask 0x0 results in: | 4511 // shufpd mask 0x0 results in: |
4522 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4512 // Lower 64-bits of v0 = Lower 64-bits of v0. |
4523 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4513 // Upper 64-bits of v0 = Lower 64-bits of v1. |
4524 __ shufpd(v0, v1, Immediate(0x0)); | 4514 __ shufpd(v0, v1, Immediate(0x0)); |
4525 } | 4515 } |
4526 | 4516 |
4527 | 4517 |
4528 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4518 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4529 Zone* zone, bool opt) const { | 4519 Zone* zone, |
| 4520 bool opt) const { |
4530 const intptr_t kNumInputs = 1; | 4521 const intptr_t kNumInputs = 1; |
4531 const intptr_t kNumTemps = 0; | 4522 const intptr_t kNumTemps = 0; |
4532 LocationSummary* summary = new(zone) LocationSummary( | 4523 LocationSummary* summary = new (zone) |
4533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4534 summary->set_in(0, Location::RequiresFpuRegister()); | 4525 summary->set_in(0, Location::RequiresFpuRegister()); |
4535 summary->set_out(0, Location::SameAsFirstInput()); | 4526 summary->set_out(0, Location::SameAsFirstInput()); |
4536 return summary; | 4527 return summary; |
4537 } | 4528 } |
4538 | 4529 |
4539 | 4530 |
4540 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4531 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4541 XmmRegister value = locs()->out(0).fpu_reg(); | 4532 XmmRegister value = locs()->out(0).fpu_reg(); |
4542 __ cvtpd2ps(value, value); | 4533 __ cvtpd2ps(value, value); |
4543 } | 4534 } |
4544 | 4535 |
4545 | 4536 |
4546 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4537 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4547 Zone* zone, bool opt) const { | 4538 Zone* zone, |
| 4539 bool opt) const { |
4548 const intptr_t kNumInputs = 1; | 4540 const intptr_t kNumInputs = 1; |
4549 const intptr_t kNumTemps = 0; | 4541 const intptr_t kNumTemps = 0; |
4550 LocationSummary* summary = new(zone) LocationSummary( | 4542 LocationSummary* summary = new (zone) |
4551 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4543 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4552 summary->set_in(0, Location::RequiresFpuRegister()); | 4544 summary->set_in(0, Location::RequiresFpuRegister()); |
4553 summary->set_out(0, Location::SameAsFirstInput()); | 4545 summary->set_out(0, Location::SameAsFirstInput()); |
4554 return summary; | 4546 return summary; |
4555 } | 4547 } |
4556 | 4548 |
4557 | 4549 |
4558 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4550 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4559 XmmRegister value = locs()->out(0).fpu_reg(); | 4551 XmmRegister value = locs()->out(0).fpu_reg(); |
4560 __ cvtps2pd(value, value); | 4552 __ cvtps2pd(value, value); |
4561 } | 4553 } |
4562 | 4554 |
4563 | 4555 |
4564 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4556 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4565 bool opt) const { | 4557 bool opt) const { |
4566 const intptr_t kNumInputs = 1; | 4558 const intptr_t kNumInputs = 1; |
4567 const intptr_t kNumTemps = 0; | 4559 const intptr_t kNumTemps = 0; |
4568 LocationSummary* summary = new(zone) LocationSummary( | 4560 LocationSummary* summary = new (zone) |
4569 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4561 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4570 summary->set_in(0, Location::RequiresFpuRegister()); | 4562 summary->set_in(0, Location::RequiresFpuRegister()); |
4571 if (representation() == kTagged) { | 4563 if (representation() == kTagged) { |
4572 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4564 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
4573 summary->set_out(0, Location::RequiresRegister()); | 4565 summary->set_out(0, Location::RequiresRegister()); |
4574 } else { | 4566 } else { |
4575 ASSERT(representation() == kUnboxedFloat64x2); | 4567 ASSERT(representation() == kUnboxedFloat64x2); |
4576 summary->set_out(0, Location::SameAsFirstInput()); | 4568 summary->set_out(0, Location::SameAsFirstInput()); |
4577 } | 4569 } |
4578 return summary; | 4570 return summary; |
4579 } | 4571 } |
(...skipping 12 matching lines...) Expand all Loading... |
4592 case MethodRecognizer::kFloat64x2Abs: | 4584 case MethodRecognizer::kFloat64x2Abs: |
4593 __ abspd(left); | 4585 __ abspd(left); |
4594 break; | 4586 break; |
4595 case MethodRecognizer::kFloat64x2Sqrt: | 4587 case MethodRecognizer::kFloat64x2Sqrt: |
4596 __ sqrtpd(left); | 4588 __ sqrtpd(left); |
4597 break; | 4589 break; |
4598 case MethodRecognizer::kFloat64x2GetSignMask: | 4590 case MethodRecognizer::kFloat64x2GetSignMask: |
4599 __ movmskpd(locs()->out(0).reg(), left); | 4591 __ movmskpd(locs()->out(0).reg(), left); |
4600 __ SmiTag(locs()->out(0).reg()); | 4592 __ SmiTag(locs()->out(0).reg()); |
4601 break; | 4593 break; |
4602 default: UNREACHABLE(); | 4594 default: |
| 4595 UNREACHABLE(); |
4603 } | 4596 } |
4604 } | 4597 } |
4605 | 4598 |
4606 | 4599 |
4607 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4600 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
4608 bool opt) const { | 4601 bool opt) const { |
4609 const intptr_t kNumInputs = 2; | 4602 const intptr_t kNumInputs = 2; |
4610 const intptr_t kNumTemps = 0; | 4603 const intptr_t kNumTemps = 0; |
4611 LocationSummary* summary = new(zone) LocationSummary( | 4604 LocationSummary* summary = new (zone) |
4612 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4605 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4613 summary->set_in(0, Location::RequiresFpuRegister()); | 4606 summary->set_in(0, Location::RequiresFpuRegister()); |
4614 summary->set_in(1, Location::RequiresFpuRegister()); | 4607 summary->set_in(1, Location::RequiresFpuRegister()); |
4615 summary->set_out(0, Location::SameAsFirstInput()); | 4608 summary->set_out(0, Location::SameAsFirstInput()); |
4616 return summary; | 4609 return summary; |
4617 } | 4610 } |
4618 | 4611 |
4619 | 4612 |
4620 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4613 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4621 XmmRegister left = locs()->in(0).fpu_reg(); | 4614 XmmRegister left = locs()->in(0).fpu_reg(); |
4622 XmmRegister right = locs()->in(1).fpu_reg(); | 4615 XmmRegister right = locs()->in(1).fpu_reg(); |
(...skipping 23 matching lines...) Expand all Loading... |
4646 // Move updated value into output register. | 4639 // Move updated value into output register. |
4647 __ movups(left, Address(RSP, 0)); | 4640 __ movups(left, Address(RSP, 0)); |
4648 __ addq(RSP, Immediate(16)); | 4641 __ addq(RSP, Immediate(16)); |
4649 break; | 4642 break; |
4650 case MethodRecognizer::kFloat64x2Min: | 4643 case MethodRecognizer::kFloat64x2Min: |
4651 __ minpd(left, right); | 4644 __ minpd(left, right); |
4652 break; | 4645 break; |
4653 case MethodRecognizer::kFloat64x2Max: | 4646 case MethodRecognizer::kFloat64x2Max: |
4654 __ maxpd(left, right); | 4647 __ maxpd(left, right); |
4655 break; | 4648 break; |
4656 default: UNREACHABLE(); | 4649 default: |
| 4650 UNREACHABLE(); |
4657 } | 4651 } |
4658 } | 4652 } |
4659 | 4653 |
4660 | 4654 |
4661 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4655 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
4662 Zone* zone, bool opt) const { | 4656 bool opt) const { |
4663 const intptr_t kNumInputs = 4; | 4657 const intptr_t kNumInputs = 4; |
4664 const intptr_t kNumTemps = 0; | 4658 const intptr_t kNumTemps = 0; |
4665 LocationSummary* summary = new(zone) LocationSummary( | 4659 LocationSummary* summary = new (zone) |
4666 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4660 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4667 summary->set_in(0, Location::RequiresRegister()); | 4661 summary->set_in(0, Location::RequiresRegister()); |
4668 summary->set_in(1, Location::RequiresRegister()); | 4662 summary->set_in(1, Location::RequiresRegister()); |
4669 summary->set_in(2, Location::RequiresRegister()); | 4663 summary->set_in(2, Location::RequiresRegister()); |
4670 summary->set_in(3, Location::RequiresRegister()); | 4664 summary->set_in(3, Location::RequiresRegister()); |
4671 summary->set_out(0, Location::RequiresFpuRegister()); | 4665 summary->set_out(0, Location::RequiresFpuRegister()); |
4672 return summary; | 4666 return summary; |
4673 } | 4667 } |
4674 | 4668 |
4675 | 4669 |
4676 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4670 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4677 Register v0 = locs()->in(0).reg(); | 4671 Register v0 = locs()->in(0).reg(); |
4678 Register v1 = locs()->in(1).reg(); | 4672 Register v1 = locs()->in(1).reg(); |
4679 Register v2 = locs()->in(2).reg(); | 4673 Register v2 = locs()->in(2).reg(); |
4680 Register v3 = locs()->in(3).reg(); | 4674 Register v3 = locs()->in(3).reg(); |
4681 XmmRegister result = locs()->out(0).fpu_reg(); | 4675 XmmRegister result = locs()->out(0).fpu_reg(); |
4682 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); | 4676 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); |
4683 __ movl(Address(RSP, 0 * kInt32Size), v0); | 4677 __ movl(Address(RSP, 0 * kInt32Size), v0); |
4684 __ movl(Address(RSP, 1 * kInt32Size), v1); | 4678 __ movl(Address(RSP, 1 * kInt32Size), v1); |
4685 __ movl(Address(RSP, 2 * kInt32Size), v2); | 4679 __ movl(Address(RSP, 2 * kInt32Size), v2); |
4686 __ movl(Address(RSP, 3 * kInt32Size), v3); | 4680 __ movl(Address(RSP, 3 * kInt32Size), v3); |
4687 __ movups(result, Address(RSP, 0)); | 4681 __ movups(result, Address(RSP, 0)); |
4688 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); | 4682 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); |
4689 } | 4683 } |
4690 | 4684 |
4691 | 4685 |
4692 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4686 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
4693 Zone* zone, bool opt) const { | 4687 Zone* zone, |
| 4688 bool opt) const { |
4694 const intptr_t kNumInputs = 4; | 4689 const intptr_t kNumInputs = 4; |
4695 const intptr_t kNumTemps = 1; | 4690 const intptr_t kNumTemps = 1; |
4696 LocationSummary* summary = new(zone) LocationSummary( | 4691 LocationSummary* summary = new (zone) |
4697 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4692 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4698 summary->set_in(0, Location::RequiresRegister()); | 4693 summary->set_in(0, Location::RequiresRegister()); |
4699 summary->set_in(1, Location::RequiresRegister()); | 4694 summary->set_in(1, Location::RequiresRegister()); |
4700 summary->set_in(2, Location::RequiresRegister()); | 4695 summary->set_in(2, Location::RequiresRegister()); |
4701 summary->set_in(3, Location::RequiresRegister()); | 4696 summary->set_in(3, Location::RequiresRegister()); |
4702 summary->set_temp(0, Location::RequiresRegister()); | 4697 summary->set_temp(0, Location::RequiresRegister()); |
4703 summary->set_out(0, Location::RequiresFpuRegister()); | 4698 summary->set_out(0, Location::RequiresFpuRegister()); |
4704 return summary; | 4699 return summary; |
4705 } | 4700 } |
4706 | 4701 |
4707 | 4702 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4756 | 4751 |
4757 __ movups(result, Address(RSP, 0)); | 4752 __ movups(result, Address(RSP, 0)); |
4758 __ AddImmediate(RSP, Immediate(16)); | 4753 __ AddImmediate(RSP, Immediate(16)); |
4759 } | 4754 } |
4760 | 4755 |
4761 | 4756 |
4762 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4757 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
4763 bool opt) const { | 4758 bool opt) const { |
4764 const intptr_t kNumInputs = 1; | 4759 const intptr_t kNumInputs = 1; |
4765 const intptr_t kNumTemps = 0; | 4760 const intptr_t kNumTemps = 0; |
4766 LocationSummary* summary = new(zone) LocationSummary( | 4761 LocationSummary* summary = new (zone) |
4767 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4762 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4768 summary->set_in(0, Location::RequiresFpuRegister()); | 4763 summary->set_in(0, Location::RequiresFpuRegister()); |
4769 summary->set_out(0, Location::RequiresRegister()); | 4764 summary->set_out(0, Location::RequiresRegister()); |
4770 return summary; | 4765 return summary; |
4771 } | 4766 } |
4772 | 4767 |
4773 | 4768 |
4774 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4769 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4775 XmmRegister value = locs()->in(0).fpu_reg(); | 4770 XmmRegister value = locs()->in(0).fpu_reg(); |
4776 Register result = locs()->out(0).reg(); | 4771 Register result = locs()->out(0).reg(); |
4777 Label done; | 4772 Label done; |
4778 Label non_zero; | 4773 Label non_zero; |
4779 __ AddImmediate(RSP, Immediate(-16)); | 4774 __ AddImmediate(RSP, Immediate(-16)); |
4780 // Move value to stack. | 4775 // Move value to stack. |
4781 __ movups(Address(RSP, 0), value); | 4776 __ movups(Address(RSP, 0), value); |
4782 switch (op_kind()) { | 4777 switch (op_kind()) { |
4783 case MethodRecognizer::kInt32x4GetFlagX: | 4778 case MethodRecognizer::kInt32x4GetFlagX: |
4784 __ movl(result, Address(RSP, 0)); | 4779 __ movl(result, Address(RSP, 0)); |
4785 break; | 4780 break; |
4786 case MethodRecognizer::kInt32x4GetFlagY: | 4781 case MethodRecognizer::kInt32x4GetFlagY: |
4787 __ movl(result, Address(RSP, 4)); | 4782 __ movl(result, Address(RSP, 4)); |
4788 break; | 4783 break; |
4789 case MethodRecognizer::kInt32x4GetFlagZ: | 4784 case MethodRecognizer::kInt32x4GetFlagZ: |
4790 __ movl(result, Address(RSP, 8)); | 4785 __ movl(result, Address(RSP, 8)); |
4791 break; | 4786 break; |
4792 case MethodRecognizer::kInt32x4GetFlagW: | 4787 case MethodRecognizer::kInt32x4GetFlagW: |
4793 __ movl(result, Address(RSP, 12)); | 4788 __ movl(result, Address(RSP, 12)); |
4794 break; | 4789 break; |
4795 default: UNREACHABLE(); | 4790 default: |
| 4791 UNREACHABLE(); |
4796 } | 4792 } |
4797 __ AddImmediate(RSP, Immediate(16)); | 4793 __ AddImmediate(RSP, Immediate(16)); |
4798 __ testl(result, result); | 4794 __ testl(result, result); |
4799 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4795 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
4800 __ LoadObject(result, Bool::False()); | 4796 __ LoadObject(result, Bool::False()); |
4801 __ jmp(&done); | 4797 __ jmp(&done); |
4802 __ Bind(&non_zero); | 4798 __ Bind(&non_zero); |
4803 __ LoadObject(result, Bool::True()); | 4799 __ LoadObject(result, Bool::True()); |
4804 __ Bind(&done); | 4800 __ Bind(&done); |
4805 } | 4801 } |
4806 | 4802 |
4807 | 4803 |
4808 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4804 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
4809 bool opt) const { | 4805 bool opt) const { |
4810 const intptr_t kNumInputs = 3; | 4806 const intptr_t kNumInputs = 3; |
4811 const intptr_t kNumTemps = 1; | 4807 const intptr_t kNumTemps = 1; |
4812 LocationSummary* summary = new(zone) LocationSummary( | 4808 LocationSummary* summary = new (zone) |
4813 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4809 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4814 summary->set_in(0, Location::RequiresFpuRegister()); | 4810 summary->set_in(0, Location::RequiresFpuRegister()); |
4815 summary->set_in(1, Location::RequiresFpuRegister()); | 4811 summary->set_in(1, Location::RequiresFpuRegister()); |
4816 summary->set_in(2, Location::RequiresFpuRegister()); | 4812 summary->set_in(2, Location::RequiresFpuRegister()); |
4817 summary->set_temp(0, Location::RequiresFpuRegister()); | 4813 summary->set_temp(0, Location::RequiresFpuRegister()); |
4818 summary->set_out(0, Location::SameAsFirstInput()); | 4814 summary->set_out(0, Location::SameAsFirstInput()); |
4819 return summary; | 4815 return summary; |
4820 } | 4816 } |
4821 | 4817 |
4822 | 4818 |
4823 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4819 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 13 matching lines...) Expand all Loading... |
4837 __ andps(temp, falseValue); | 4833 __ andps(temp, falseValue); |
4838 // out = mask | temp. | 4834 // out = mask | temp. |
4839 __ orps(mask, temp); | 4835 __ orps(mask, temp); |
4840 } | 4836 } |
4841 | 4837 |
4842 | 4838 |
4843 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4839 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
4844 bool opt) const { | 4840 bool opt) const { |
4845 const intptr_t kNumInputs = 2; | 4841 const intptr_t kNumInputs = 2; |
4846 const intptr_t kNumTemps = 1; | 4842 const intptr_t kNumTemps = 1; |
4847 LocationSummary* summary = new(zone) LocationSummary( | 4843 LocationSummary* summary = new (zone) |
4848 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4844 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4849 summary->set_in(0, Location::RequiresFpuRegister()); | 4845 summary->set_in(0, Location::RequiresFpuRegister()); |
4850 summary->set_in(1, Location::RequiresRegister()); | 4846 summary->set_in(1, Location::RequiresRegister()); |
4851 summary->set_temp(0, Location::RequiresRegister()); | 4847 summary->set_temp(0, Location::RequiresRegister()); |
4852 summary->set_out(0, Location::SameAsFirstInput()); | 4848 summary->set_out(0, Location::SameAsFirstInput()); |
4853 return summary; | 4849 return summary; |
4854 } | 4850 } |
4855 | 4851 |
4856 | 4852 |
4857 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4853 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4858 XmmRegister mask = locs()->in(0).fpu_reg(); | 4854 XmmRegister mask = locs()->in(0).fpu_reg(); |
4859 Register flag = locs()->in(1).reg(); | 4855 Register flag = locs()->in(1).reg(); |
4860 Register temp = locs()->temp(0).reg(); | 4856 Register temp = locs()->temp(0).reg(); |
4861 ASSERT(mask == locs()->out(0).fpu_reg()); | 4857 ASSERT(mask == locs()->out(0).fpu_reg()); |
4862 __ AddImmediate(RSP, Immediate(-16)); | 4858 __ AddImmediate(RSP, Immediate(-16)); |
4863 // Copy mask to stack. | 4859 // Copy mask to stack. |
4864 __ movups(Address(RSP, 0), mask); | 4860 __ movups(Address(RSP, 0), mask); |
4865 Label falsePath, exitPath; | 4861 Label falsePath, exitPath; |
4866 __ CompareObject(flag, Bool::True()); | 4862 __ CompareObject(flag, Bool::True()); |
4867 __ j(NOT_EQUAL, &falsePath); | 4863 __ j(NOT_EQUAL, &falsePath); |
4868 switch (op_kind()) { | 4864 switch (op_kind()) { |
4869 case MethodRecognizer::kInt32x4WithFlagX: | 4865 case MethodRecognizer::kInt32x4WithFlagX: |
4870 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4866 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
4871 __ movl(Address(RSP, 0), temp); | 4867 __ movl(Address(RSP, 0), temp); |
4872 __ jmp(&exitPath); | 4868 __ jmp(&exitPath); |
4873 __ Bind(&falsePath); | 4869 __ Bind(&falsePath); |
4874 __ LoadImmediate(temp, Immediate(0x0)); | 4870 __ LoadImmediate(temp, Immediate(0x0)); |
4875 __ movl(Address(RSP, 0), temp); | 4871 __ movl(Address(RSP, 0), temp); |
4876 break; | 4872 break; |
4877 case MethodRecognizer::kInt32x4WithFlagY: | 4873 case MethodRecognizer::kInt32x4WithFlagY: |
4878 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4874 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
4879 __ movl(Address(RSP, 4), temp); | 4875 __ movl(Address(RSP, 4), temp); |
4880 __ jmp(&exitPath); | 4876 __ jmp(&exitPath); |
4881 __ Bind(&falsePath); | 4877 __ Bind(&falsePath); |
4882 __ LoadImmediate(temp, Immediate(0x0)); | 4878 __ LoadImmediate(temp, Immediate(0x0)); |
4883 __ movl(Address(RSP, 4), temp); | 4879 __ movl(Address(RSP, 4), temp); |
4884 break; | 4880 break; |
4885 case MethodRecognizer::kInt32x4WithFlagZ: | 4881 case MethodRecognizer::kInt32x4WithFlagZ: |
4886 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4882 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
4887 __ movl(Address(RSP, 8), temp); | 4883 __ movl(Address(RSP, 8), temp); |
4888 __ jmp(&exitPath); | 4884 __ jmp(&exitPath); |
4889 __ Bind(&falsePath); | 4885 __ Bind(&falsePath); |
4890 __ LoadImmediate(temp, Immediate(0x0)); | 4886 __ LoadImmediate(temp, Immediate(0x0)); |
4891 __ movl(Address(RSP, 8), temp); | 4887 __ movl(Address(RSP, 8), temp); |
4892 break; | 4888 break; |
4893 case MethodRecognizer::kInt32x4WithFlagW: | 4889 case MethodRecognizer::kInt32x4WithFlagW: |
4894 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4890 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
4895 __ movl(Address(RSP, 12), temp); | 4891 __ movl(Address(RSP, 12), temp); |
4896 __ jmp(&exitPath); | 4892 __ jmp(&exitPath); |
4897 __ Bind(&falsePath); | 4893 __ Bind(&falsePath); |
4898 __ LoadImmediate(temp, Immediate(0x0)); | 4894 __ LoadImmediate(temp, Immediate(0x0)); |
4899 __ movl(Address(RSP, 12), temp); | 4895 __ movl(Address(RSP, 12), temp); |
4900 break; | 4896 break; |
4901 default: UNREACHABLE(); | 4897 default: |
| 4898 UNREACHABLE(); |
4902 } | 4899 } |
4903 __ Bind(&exitPath); | 4900 __ Bind(&exitPath); |
4904 // Copy mask back to register. | 4901 // Copy mask back to register. |
4905 __ movups(mask, Address(RSP, 0)); | 4902 __ movups(mask, Address(RSP, 0)); |
4906 __ AddImmediate(RSP, Immediate(16)); | 4903 __ AddImmediate(RSP, Immediate(16)); |
4907 } | 4904 } |
4908 | 4905 |
4909 | 4906 |
4910 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4907 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
4911 bool opt) const { | 4908 bool opt) const { |
4912 const intptr_t kNumInputs = 1; | 4909 const intptr_t kNumInputs = 1; |
4913 const intptr_t kNumTemps = 0; | 4910 const intptr_t kNumTemps = 0; |
4914 LocationSummary* summary = new(zone) LocationSummary( | 4911 LocationSummary* summary = new (zone) |
4915 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4912 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4916 summary->set_in(0, Location::RequiresFpuRegister()); | 4913 summary->set_in(0, Location::RequiresFpuRegister()); |
4917 summary->set_out(0, Location::SameAsFirstInput()); | 4914 summary->set_out(0, Location::SameAsFirstInput()); |
4918 return summary; | 4915 return summary; |
4919 } | 4916 } |
4920 | 4917 |
4921 | 4918 |
4922 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4919 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4923 // NOP. | 4920 // NOP. |
4924 } | 4921 } |
4925 | 4922 |
4926 | 4923 |
4927 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4924 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
4928 bool opt) const { | 4925 bool opt) const { |
4929 const intptr_t kNumInputs = 2; | 4926 const intptr_t kNumInputs = 2; |
4930 const intptr_t kNumTemps = 0; | 4927 const intptr_t kNumTemps = 0; |
4931 LocationSummary* summary = new(zone) LocationSummary( | 4928 LocationSummary* summary = new (zone) |
4932 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4933 summary->set_in(0, Location::RequiresFpuRegister()); | 4930 summary->set_in(0, Location::RequiresFpuRegister()); |
4934 summary->set_in(1, Location::RequiresFpuRegister()); | 4931 summary->set_in(1, Location::RequiresFpuRegister()); |
4935 summary->set_out(0, Location::SameAsFirstInput()); | 4932 summary->set_out(0, Location::SameAsFirstInput()); |
4936 return summary; | 4933 return summary; |
4937 } | 4934 } |
4938 | 4935 |
4939 | 4936 |
4940 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4937 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4941 XmmRegister left = locs()->in(0).fpu_reg(); | 4938 XmmRegister left = locs()->in(0).fpu_reg(); |
4942 XmmRegister right = locs()->in(1).fpu_reg(); | 4939 XmmRegister right = locs()->in(1).fpu_reg(); |
(...skipping 10 matching lines...) Expand all Loading... |
4953 case Token::kBIT_XOR: { | 4950 case Token::kBIT_XOR: { |
4954 __ xorps(left, right); | 4951 __ xorps(left, right); |
4955 break; | 4952 break; |
4956 } | 4953 } |
4957 case Token::kADD: | 4954 case Token::kADD: |
4958 __ addpl(left, right); | 4955 __ addpl(left, right); |
4959 break; | 4956 break; |
4960 case Token::kSUB: | 4957 case Token::kSUB: |
4961 __ subpl(left, right); | 4958 __ subpl(left, right); |
4962 break; | 4959 break; |
4963 default: UNREACHABLE(); | 4960 default: |
| 4961 UNREACHABLE(); |
4964 } | 4962 } |
4965 } | 4963 } |
4966 | 4964 |
4967 | 4965 |
4968 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4966 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
4969 bool opt) const { | 4967 bool opt) const { |
4970 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4968 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
4971 (kind() == MathUnaryInstr::kDoubleSquare)); | 4969 (kind() == MathUnaryInstr::kDoubleSquare)); |
4972 const intptr_t kNumInputs = 1; | 4970 const intptr_t kNumInputs = 1; |
4973 const intptr_t kNumTemps = 0; | 4971 const intptr_t kNumTemps = 0; |
4974 LocationSummary* summary = new(zone) LocationSummary( | 4972 LocationSummary* summary = new (zone) |
4975 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4976 summary->set_in(0, Location::RequiresFpuRegister()); | 4974 summary->set_in(0, Location::RequiresFpuRegister()); |
4977 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4975 if (kind() == MathUnaryInstr::kDoubleSquare) { |
4978 summary->set_out(0, Location::SameAsFirstInput()); | 4976 summary->set_out(0, Location::SameAsFirstInput()); |
4979 } else { | 4977 } else { |
4980 summary->set_out(0, Location::RequiresFpuRegister()); | 4978 summary->set_out(0, Location::RequiresFpuRegister()); |
4981 } | 4979 } |
4982 return summary; | 4980 return summary; |
4983 } | 4981 } |
4984 | 4982 |
4985 | 4983 |
4986 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4984 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4987 if (kind() == MathUnaryInstr::kSqrt) { | 4985 if (kind() == MathUnaryInstr::kSqrt) { |
4988 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4986 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
4989 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4987 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
4990 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4988 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
4991 __ mulsd(value_reg, value_reg); | 4989 __ mulsd(value_reg, value_reg); |
4992 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4990 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
4993 } else { | 4991 } else { |
4994 UNREACHABLE(); | 4992 UNREACHABLE(); |
4995 } | 4993 } |
4996 } | 4994 } |
4997 | 4995 |
4998 | 4996 |
4999 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4997 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
5000 Zone* zone, bool opt) const { | 4998 Zone* zone, |
| 4999 bool opt) const { |
5001 const intptr_t kNumTemps = 0; | 5000 const intptr_t kNumTemps = 0; |
5002 LocationSummary* summary = new(zone) LocationSummary( | 5001 LocationSummary* summary = new (zone) |
5003 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5002 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5004 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); | 5003 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); |
5005 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); | 5004 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); |
5006 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); | 5005 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); |
5007 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); | 5006 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); |
5008 summary->set_out(0, Location::RegisterLocation(RAX)); | 5007 summary->set_out(0, Location::RegisterLocation(RAX)); |
5009 return summary; | 5008 return summary; |
5010 } | 5009 } |
5011 | 5010 |
5012 | 5011 |
5013 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 5012 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
5014 FlowGraphCompiler* compiler) { | 5013 FlowGraphCompiler* compiler) { |
5015 | |
5016 // Save RSP. R13 is chosen because it is callee saved so we do not need to | 5014 // Save RSP. R13 is chosen because it is callee saved so we do not need to |
5017 // back it up before calling into the runtime. | 5015 // back it up before calling into the runtime. |
5018 static const Register kSavedSPReg = R13; | 5016 static const Register kSavedSPReg = R13; |
5019 __ movq(kSavedSPReg, RSP); | 5017 __ movq(kSavedSPReg, RSP); |
5020 __ ReserveAlignedFrameSpace(0); | 5018 __ ReserveAlignedFrameSpace(0); |
5021 | 5019 |
5022 // Call the function. Parameters are already in their correct spots. | 5020 // Call the function. Parameters are already in their correct spots. |
5023 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 5021 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
5024 | 5022 |
5025 // Restore RSP. | 5023 // Restore RSP. |
5026 __ movq(RSP, kSavedSPReg); | 5024 __ movq(RSP, kSavedSPReg); |
5027 } | 5025 } |
5028 | 5026 |
5029 | 5027 |
5030 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 5028 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
5031 bool opt) const { | 5029 bool opt) const { |
5032 const intptr_t kNumInputs = 1; | 5030 const intptr_t kNumInputs = 1; |
5033 return LocationSummary::Make(zone, | 5031 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
5034 kNumInputs, | |
5035 Location::SameAsFirstInput(), | |
5036 LocationSummary::kNoCall); | 5032 LocationSummary::kNoCall); |
5037 } | 5033 } |
5038 | 5034 |
5039 | 5035 |
5040 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5036 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5041 Register value = locs()->in(0).reg(); | 5037 Register value = locs()->in(0).reg(); |
5042 ASSERT(value == locs()->out(0).reg()); | 5038 ASSERT(value == locs()->out(0).reg()); |
5043 switch (op_kind()) { | 5039 switch (op_kind()) { |
5044 case Token::kNEGATE: { | 5040 case Token::kNEGATE: { |
5045 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 5041 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
5046 __ negq(value); | 5042 __ negq(value); |
5047 __ j(OVERFLOW, deopt); | 5043 __ j(OVERFLOW, deopt); |
5048 break; | 5044 break; |
5049 } | 5045 } |
5050 case Token::kBIT_NOT: | 5046 case Token::kBIT_NOT: |
5051 __ notq(value); | 5047 __ notq(value); |
5052 // Remove inverted smi-tag. | 5048 // Remove inverted smi-tag. |
5053 __ AndImmediate(value, Immediate(~kSmiTagMask)); | 5049 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
5054 break; | 5050 break; |
5055 default: | 5051 default: |
5056 UNREACHABLE(); | 5052 UNREACHABLE(); |
5057 } | 5053 } |
5058 } | 5054 } |
5059 | 5055 |
5060 | 5056 |
5061 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 5057 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
5062 bool opt) const { | 5058 bool opt) const { |
5063 const intptr_t kNumInputs = 1; | 5059 const intptr_t kNumInputs = 1; |
5064 const intptr_t kNumTemps = 0; | 5060 const intptr_t kNumTemps = 0; |
5065 LocationSummary* summary = new(zone) LocationSummary( | 5061 LocationSummary* summary = new (zone) |
5066 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5062 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5067 summary->set_in(0, Location::RequiresFpuRegister()); | 5063 summary->set_in(0, Location::RequiresFpuRegister()); |
5068 summary->set_out(0, Location::SameAsFirstInput()); | 5064 summary->set_out(0, Location::SameAsFirstInput()); |
5069 return summary; | 5065 return summary; |
5070 } | 5066 } |
5071 | 5067 |
5072 | 5068 |
5073 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5069 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5074 XmmRegister value = locs()->in(0).fpu_reg(); | 5070 XmmRegister value = locs()->in(0).fpu_reg(); |
5075 ASSERT(locs()->out(0).fpu_reg() == value); | 5071 ASSERT(locs()->out(0).fpu_reg() == value); |
5076 __ DoubleNegate(value); | 5072 __ DoubleNegate(value); |
5077 } | 5073 } |
5078 | 5074 |
5079 | 5075 |
5080 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 5076 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
5081 bool opt) const { | 5077 bool opt) const { |
5082 if (result_cid() == kDoubleCid) { | 5078 if (result_cid() == kDoubleCid) { |
5083 const intptr_t kNumInputs = 2; | 5079 const intptr_t kNumInputs = 2; |
5084 const intptr_t kNumTemps = 1; | 5080 const intptr_t kNumTemps = 1; |
5085 LocationSummary* summary = new(zone) LocationSummary( | 5081 LocationSummary* summary = new (zone) |
5086 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5082 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5087 summary->set_in(0, Location::RequiresFpuRegister()); | 5083 summary->set_in(0, Location::RequiresFpuRegister()); |
5088 summary->set_in(1, Location::RequiresFpuRegister()); | 5084 summary->set_in(1, Location::RequiresFpuRegister()); |
5089 // Reuse the left register so that code can be made shorter. | 5085 // Reuse the left register so that code can be made shorter. |
5090 summary->set_out(0, Location::SameAsFirstInput()); | 5086 summary->set_out(0, Location::SameAsFirstInput()); |
5091 summary->set_temp(0, Location::RequiresRegister()); | 5087 summary->set_temp(0, Location::RequiresRegister()); |
5092 return summary; | 5088 return summary; |
5093 } | 5089 } |
5094 ASSERT(result_cid() == kSmiCid); | 5090 ASSERT(result_cid() == kSmiCid); |
5095 const intptr_t kNumInputs = 2; | 5091 const intptr_t kNumInputs = 2; |
5096 const intptr_t kNumTemps = 0; | 5092 const intptr_t kNumTemps = 0; |
5097 LocationSummary* summary = new(zone) LocationSummary( | 5093 LocationSummary* summary = new (zone) |
5098 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5094 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5099 summary->set_in(0, Location::RequiresRegister()); | 5095 summary->set_in(0, Location::RequiresRegister()); |
5100 summary->set_in(1, Location::RequiresRegister()); | 5096 summary->set_in(1, Location::RequiresRegister()); |
5101 // Reuse the left register so that code can be made shorter. | 5097 // Reuse the left register so that code can be made shorter. |
5102 summary->set_out(0, Location::SameAsFirstInput()); | 5098 summary->set_out(0, Location::SameAsFirstInput()); |
5103 return summary; | 5099 return summary; |
5104 } | 5100 } |
5105 | 5101 |
5106 | 5102 |
5107 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5103 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5108 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 5104 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5161 ASSERT(result == left); | 5157 ASSERT(result == left); |
5162 if (is_min) { | 5158 if (is_min) { |
5163 __ cmovgeq(result, right); | 5159 __ cmovgeq(result, right); |
5164 } else { | 5160 } else { |
5165 __ cmovlessq(result, right); | 5161 __ cmovlessq(result, right); |
5166 } | 5162 } |
5167 } | 5163 } |
5168 | 5164 |
5169 | 5165 |
5170 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 5166 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
5171 bool opt) const { | 5167 bool opt) const { |
5172 const intptr_t kNumInputs = 1; | 5168 const intptr_t kNumInputs = 1; |
5173 const intptr_t kNumTemps = 0; | 5169 const intptr_t kNumTemps = 0; |
5174 LocationSummary* result = new(zone) LocationSummary( | 5170 LocationSummary* result = new (zone) |
5175 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5176 result->set_in(0, Location::RequiresRegister()); | 5172 result->set_in(0, Location::RequiresRegister()); |
5177 result->set_out(0, Location::RequiresFpuRegister()); | 5173 result->set_out(0, Location::RequiresFpuRegister()); |
5178 return result; | 5174 return result; |
5179 } | 5175 } |
5180 | 5176 |
5181 | 5177 |
5182 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5178 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5183 Register value = locs()->in(0).reg(); | 5179 Register value = locs()->in(0).reg(); |
5184 FpuRegister result = locs()->out(0).fpu_reg(); | 5180 FpuRegister result = locs()->out(0).fpu_reg(); |
5185 __ cvtsi2sdl(result, value); | 5181 __ cvtsi2sdl(result, value); |
5186 } | 5182 } |
5187 | 5183 |
5188 | 5184 |
5189 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 5185 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
5190 bool opt) const { | 5186 bool opt) const { |
5191 const intptr_t kNumInputs = 1; | 5187 const intptr_t kNumInputs = 1; |
5192 const intptr_t kNumTemps = 0; | 5188 const intptr_t kNumTemps = 0; |
5193 LocationSummary* result = new(zone) LocationSummary( | 5189 LocationSummary* result = new (zone) |
5194 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5190 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5195 result->set_in(0, Location::WritableRegister()); | 5191 result->set_in(0, Location::WritableRegister()); |
5196 result->set_out(0, Location::RequiresFpuRegister()); | 5192 result->set_out(0, Location::RequiresFpuRegister()); |
5197 return result; | 5193 return result; |
5198 } | 5194 } |
5199 | 5195 |
5200 | 5196 |
5201 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5197 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5202 Register value = locs()->in(0).reg(); | 5198 Register value = locs()->in(0).reg(); |
5203 FpuRegister result = locs()->out(0).fpu_reg(); | 5199 FpuRegister result = locs()->out(0).fpu_reg(); |
5204 __ SmiUntag(value); | 5200 __ SmiUntag(value); |
(...skipping 10 matching lines...) Expand all Loading... |
5215 | 5211 |
5216 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5212 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5217 UNIMPLEMENTED(); | 5213 UNIMPLEMENTED(); |
5218 } | 5214 } |
5219 | 5215 |
5220 | 5216 |
5221 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5217 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
5222 bool opt) const { | 5218 bool opt) const { |
5223 const intptr_t kNumInputs = 1; | 5219 const intptr_t kNumInputs = 1; |
5224 const intptr_t kNumTemps = 1; | 5220 const intptr_t kNumTemps = 1; |
5225 LocationSummary* result = new(zone) LocationSummary( | 5221 LocationSummary* result = new (zone) |
5226 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5222 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5227 result->set_in(0, Location::RegisterLocation(RCX)); | 5223 result->set_in(0, Location::RegisterLocation(RCX)); |
5228 result->set_out(0, Location::RegisterLocation(RAX)); | 5224 result->set_out(0, Location::RegisterLocation(RAX)); |
5229 result->set_temp(0, Location::RegisterLocation(RBX)); | 5225 result->set_temp(0, Location::RegisterLocation(RBX)); |
5230 return result; | 5226 return result; |
5231 } | 5227 } |
5232 | 5228 |
5233 | 5229 |
5234 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5230 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5235 Register result = locs()->out(0).reg(); | 5231 Register result = locs()->out(0).reg(); |
5236 Register value_obj = locs()->in(0).reg(); | 5232 Register value_obj = locs()->in(0).reg(); |
(...skipping 13 matching lines...) Expand all Loading... |
5250 __ SmiTag(result); | 5246 __ SmiTag(result); |
5251 __ jmp(&done); | 5247 __ jmp(&done); |
5252 __ Bind(&do_call); | 5248 __ Bind(&do_call); |
5253 ASSERT(instance_call()->HasICData()); | 5249 ASSERT(instance_call()->HasICData()); |
5254 const ICData& ic_data = *instance_call()->ic_data(); | 5250 const ICData& ic_data = *instance_call()->ic_data(); |
5255 ASSERT((ic_data.NumberOfChecks() == 1)); | 5251 ASSERT((ic_data.NumberOfChecks() == 1)); |
5256 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5252 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
5257 | 5253 |
5258 const intptr_t kNumberOfArguments = 1; | 5254 const intptr_t kNumberOfArguments = 1; |
5259 __ pushq(value_obj); | 5255 __ pushq(value_obj); |
5260 compiler->GenerateStaticCall(deopt_id(), | 5256 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
5261 instance_call()->token_pos(), | |
5262 target, | |
5263 kNumberOfArguments, | 5257 kNumberOfArguments, |
5264 Object::null_array(), // No argument names. | 5258 Object::null_array(), // No argument names. |
5265 locs(), | 5259 locs(), ICData::Handle()); |
5266 ICData::Handle()); | |
5267 __ Bind(&done); | 5260 __ Bind(&done); |
5268 } | 5261 } |
5269 | 5262 |
5270 | 5263 |
5271 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5264 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
5272 bool opt) const { | 5265 bool opt) const { |
5273 const intptr_t kNumInputs = 1; | 5266 const intptr_t kNumInputs = 1; |
5274 const intptr_t kNumTemps = 1; | 5267 const intptr_t kNumTemps = 1; |
5275 LocationSummary* result = new(zone) LocationSummary( | 5268 LocationSummary* result = new (zone) |
5276 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5269 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5277 result->set_in(0, Location::RequiresFpuRegister()); | 5270 result->set_in(0, Location::RequiresFpuRegister()); |
5278 result->set_out(0, Location::RequiresRegister()); | 5271 result->set_out(0, Location::RequiresRegister()); |
5279 result->set_temp(0, Location::RequiresRegister()); | 5272 result->set_temp(0, Location::RequiresRegister()); |
5280 return result; | 5273 return result; |
5281 } | 5274 } |
5282 | 5275 |
5283 | 5276 |
5284 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5277 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5285 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5278 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
5286 Register result = locs()->out(0).reg(); | 5279 Register result = locs()->out(0).reg(); |
5287 XmmRegister value = locs()->in(0).fpu_reg(); | 5280 XmmRegister value = locs()->in(0).fpu_reg(); |
5288 Register temp = locs()->temp(0).reg(); | 5281 Register temp = locs()->temp(0).reg(); |
5289 | 5282 |
5290 __ cvttsd2siq(result, value); | 5283 __ cvttsd2siq(result, value); |
5291 // Overflow is signalled with minint. | 5284 // Overflow is signalled with minint. |
5292 Label do_call, done; | 5285 Label do_call, done; |
5293 // Check for overflow and that it fits into Smi. | 5286 // Check for overflow and that it fits into Smi. |
5294 __ movq(temp, result); | 5287 __ movq(temp, result); |
5295 __ shlq(temp, Immediate(1)); | 5288 __ shlq(temp, Immediate(1)); |
5296 __ j(OVERFLOW, deopt); | 5289 __ j(OVERFLOW, deopt); |
5297 __ SmiTag(result); | 5290 __ SmiTag(result); |
5298 } | 5291 } |
5299 | 5292 |
5300 | 5293 |
5301 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5294 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
5302 bool opt) const { | 5295 bool opt) const { |
5303 const intptr_t kNumInputs = 1; | 5296 const intptr_t kNumInputs = 1; |
5304 const intptr_t kNumTemps = 0; | 5297 const intptr_t kNumTemps = 0; |
5305 LocationSummary* result = new(zone) LocationSummary( | 5298 LocationSummary* result = new (zone) |
5306 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5299 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5307 result->set_in(0, Location::RequiresFpuRegister()); | 5300 result->set_in(0, Location::RequiresFpuRegister()); |
5308 result->set_out(0, Location::RequiresFpuRegister()); | 5301 result->set_out(0, Location::RequiresFpuRegister()); |
5309 return result; | 5302 return result; |
5310 } | 5303 } |
5311 | 5304 |
5312 | 5305 |
5313 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5306 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5314 XmmRegister value = locs()->in(0).fpu_reg(); | 5307 XmmRegister value = locs()->in(0).fpu_reg(); |
5315 XmmRegister result = locs()->out(0).fpu_reg(); | 5308 XmmRegister result = locs()->out(0).fpu_reg(); |
5316 switch (recognized_kind()) { | 5309 switch (recognized_kind()) { |
5317 case MethodRecognizer::kDoubleTruncate: | 5310 case MethodRecognizer::kDoubleTruncate: |
5318 __ roundsd(result, value, Assembler::kRoundToZero); | 5311 __ roundsd(result, value, Assembler::kRoundToZero); |
5319 break; | 5312 break; |
5320 case MethodRecognizer::kDoubleFloor: | 5313 case MethodRecognizer::kDoubleFloor: |
5321 __ roundsd(result, value, Assembler::kRoundDown); | 5314 __ roundsd(result, value, Assembler::kRoundDown); |
5322 break; | 5315 break; |
5323 case MethodRecognizer::kDoubleCeil: | 5316 case MethodRecognizer::kDoubleCeil: |
5324 __ roundsd(result, value, Assembler::kRoundUp); | 5317 __ roundsd(result, value, Assembler::kRoundUp); |
5325 break; | 5318 break; |
5326 default: | 5319 default: |
5327 UNREACHABLE(); | 5320 UNREACHABLE(); |
5328 } | 5321 } |
5329 } | 5322 } |
5330 | 5323 |
5331 | 5324 |
5332 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5325 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
5333 bool opt) const { | 5326 bool opt) const { |
5334 const intptr_t kNumInputs = 1; | 5327 const intptr_t kNumInputs = 1; |
5335 const intptr_t kNumTemps = 0; | 5328 const intptr_t kNumTemps = 0; |
5336 LocationSummary* result = new(zone) LocationSummary( | 5329 LocationSummary* result = new (zone) |
5337 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5338 result->set_in(0, Location::RequiresFpuRegister()); | 5331 result->set_in(0, Location::RequiresFpuRegister()); |
5339 result->set_out(0, Location::SameAsFirstInput()); | 5332 result->set_out(0, Location::SameAsFirstInput()); |
5340 return result; | 5333 return result; |
5341 } | 5334 } |
5342 | 5335 |
5343 | 5336 |
5344 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5337 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5345 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5338 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5346 } | 5339 } |
5347 | 5340 |
5348 | 5341 |
5349 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5342 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
5350 bool opt) const { | 5343 bool opt) const { |
5351 const intptr_t kNumInputs = 1; | 5344 const intptr_t kNumInputs = 1; |
5352 const intptr_t kNumTemps = 0; | 5345 const intptr_t kNumTemps = 0; |
5353 LocationSummary* result = new(zone) LocationSummary( | 5346 LocationSummary* result = new (zone) |
5354 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5347 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5355 result->set_in(0, Location::RequiresFpuRegister()); | 5348 result->set_in(0, Location::RequiresFpuRegister()); |
5356 result->set_out(0, Location::SameAsFirstInput()); | 5349 result->set_out(0, Location::SameAsFirstInput()); |
5357 return result; | 5350 return result; |
5358 } | 5351 } |
5359 | 5352 |
5360 | 5353 |
5361 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5354 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5362 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5355 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5363 } | 5356 } |
5364 | 5357 |
5365 | 5358 |
5366 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5359 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
5367 bool opt) const { | 5360 bool opt) const { |
5368 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 5361 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
5369 // double arguments and XMM0 to return the result. Unfortunately | 5362 // double arguments and XMM0 to return the result. Unfortunately |
5370 // currently we can't specify these registers because ParallelMoveResolver | 5363 // currently we can't specify these registers because ParallelMoveResolver |
5371 // assumes that XMM0 is free at all times. | 5364 // assumes that XMM0 is free at all times. |
5372 // TODO(vegorov): allow XMM0 to be used. | 5365 // TODO(vegorov): allow XMM0 to be used. |
5373 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5366 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5374 const intptr_t kNumTemps = | 5367 const intptr_t kNumTemps = |
5375 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5368 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
5376 LocationSummary* result = new(zone) LocationSummary( | 5369 LocationSummary* result = new (zone) |
5377 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5370 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5378 ASSERT(R13 != CALLEE_SAVED_TEMP); | 5371 ASSERT(R13 != CALLEE_SAVED_TEMP); |
5379 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); | 5372 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); |
5380 result->set_temp(0, Location::RegisterLocation(R13)); | 5373 result->set_temp(0, Location::RegisterLocation(R13)); |
5381 result->set_in(0, Location::FpuRegisterLocation(XMM2)); | 5374 result->set_in(0, Location::FpuRegisterLocation(XMM2)); |
5382 if (InputCount() == 2) { | 5375 if (InputCount() == 2) { |
5383 result->set_in(1, Location::FpuRegisterLocation(XMM1)); | 5376 result->set_in(1, Location::FpuRegisterLocation(XMM1)); |
5384 } | 5377 } |
5385 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5378 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5386 // Temp index 1. | 5379 // Temp index 1. |
5387 result->set_temp(1, Location::RegisterLocation(RAX)); | 5380 result->set_temp(1, Location::RegisterLocation(RAX)); |
(...skipping 23 matching lines...) Expand all Loading... |
5411 static void InvokeDoublePow(FlowGraphCompiler* compiler, | 5404 static void InvokeDoublePow(FlowGraphCompiler* compiler, |
5412 InvokeMathCFunctionInstr* instr) { | 5405 InvokeMathCFunctionInstr* instr) { |
5413 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow); | 5406 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow); |
5414 const intptr_t kInputCount = 2; | 5407 const intptr_t kInputCount = 2; |
5415 ASSERT(instr->InputCount() == kInputCount); | 5408 ASSERT(instr->InputCount() == kInputCount); |
5416 LocationSummary* locs = instr->locs(); | 5409 LocationSummary* locs = instr->locs(); |
5417 | 5410 |
5418 XmmRegister base = locs->in(0).fpu_reg(); | 5411 XmmRegister base = locs->in(0).fpu_reg(); |
5419 XmmRegister exp = locs->in(1).fpu_reg(); | 5412 XmmRegister exp = locs->in(1).fpu_reg(); |
5420 XmmRegister result = locs->out(0).fpu_reg(); | 5413 XmmRegister result = locs->out(0).fpu_reg(); |
5421 Register temp = | 5414 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); |
5422 locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); | |
5423 XmmRegister zero_temp = | 5415 XmmRegister zero_temp = |
5424 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); | 5416 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); |
5425 | 5417 |
5426 __ xorps(zero_temp, zero_temp); | 5418 __ xorps(zero_temp, zero_temp); |
5427 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 5419 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
5428 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5420 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
5429 | 5421 |
5430 Label check_base, skip_call; | 5422 Label check_base, skip_call; |
5431 // exponent == 0.0 -> return 1.0; | 5423 // exponent == 0.0 -> return 1.0; |
5432 __ comisd(exp, zero_temp); | 5424 __ comisd(exp, zero_temp); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5481 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); | 5473 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); |
5482 // Return NaN. | 5474 // Return NaN. |
5483 __ Bind(&return_nan); | 5475 __ Bind(&return_nan); |
5484 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); | 5476 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); |
5485 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5477 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
5486 __ jmp(&skip_call); | 5478 __ jmp(&skip_call); |
5487 | 5479 |
5488 Label do_pow, return_zero; | 5480 Label do_pow, return_zero; |
5489 __ Bind(&try_sqrt); | 5481 __ Bind(&try_sqrt); |
5490 // Before calling pow, check if we could use sqrt instead of pow. | 5482 // Before calling pow, check if we could use sqrt instead of pow. |
5491 __ LoadObject(temp, | 5483 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(kNegInfinity))); |
5492 Double::ZoneHandle(Double::NewCanonical(kNegInfinity))); | |
5493 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5484 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
5494 // base == -Infinity -> call pow; | 5485 // base == -Infinity -> call pow; |
5495 __ comisd(base, result); | 5486 __ comisd(base, result); |
5496 __ j(EQUAL, &do_pow, Assembler::kNearJump); | 5487 __ j(EQUAL, &do_pow, Assembler::kNearJump); |
5497 | 5488 |
5498 // exponent == 0.5 ? | 5489 // exponent == 0.5 ? |
5499 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); | 5490 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); |
5500 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5491 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
5501 __ comisd(exp, result); | 5492 __ comisd(exp, result); |
5502 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); | 5493 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5546 // Restore RSP. | 5537 // Restore RSP. |
5547 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 5538 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
5548 } | 5539 } |
5549 | 5540 |
5550 | 5541 |
5551 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5542 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
5552 bool opt) const { | 5543 bool opt) const { |
5553 // Only use this instruction in optimized code. | 5544 // Only use this instruction in optimized code. |
5554 ASSERT(opt); | 5545 ASSERT(opt); |
5555 const intptr_t kNumInputs = 1; | 5546 const intptr_t kNumInputs = 1; |
5556 LocationSummary* summary = new(zone) LocationSummary( | 5547 LocationSummary* summary = |
5557 zone, kNumInputs, 0, LocationSummary::kNoCall); | 5548 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
5558 if (representation() == kUnboxedDouble) { | 5549 if (representation() == kUnboxedDouble) { |
5559 if (index() == 0) { | 5550 if (index() == 0) { |
5560 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 5551 summary->set_in( |
5561 Location::Any())); | 5552 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
5562 } else { | 5553 } else { |
5563 ASSERT(index() == 1); | 5554 ASSERT(index() == 1); |
5564 summary->set_in(0, Location::Pair(Location::Any(), | 5555 summary->set_in( |
5565 Location::RequiresFpuRegister())); | 5556 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
5566 } | 5557 } |
5567 summary->set_out(0, Location::RequiresFpuRegister()); | 5558 summary->set_out(0, Location::RequiresFpuRegister()); |
5568 } else { | 5559 } else { |
5569 ASSERT(representation() == kTagged); | 5560 ASSERT(representation() == kTagged); |
5570 if (index() == 0) { | 5561 if (index() == 0) { |
5571 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5562 summary->set_in( |
5572 Location::Any())); | 5563 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
5573 } else { | 5564 } else { |
5574 ASSERT(index() == 1); | 5565 ASSERT(index() == 1); |
5575 summary->set_in(0, Location::Pair(Location::Any(), | 5566 summary->set_in( |
5576 Location::RequiresRegister())); | 5567 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
5577 } | 5568 } |
5578 summary->set_out(0, Location::RequiresRegister()); | 5569 summary->set_out(0, Location::RequiresRegister()); |
5579 } | 5570 } |
5580 return summary; | 5571 return summary; |
5581 } | 5572 } |
5582 | 5573 |
5583 | 5574 |
5584 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5575 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5585 ASSERT(locs()->in(0).IsPairLocation()); | 5576 ASSERT(locs()->in(0).IsPairLocation()); |
5586 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5577 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5587 Location in_loc = pair->At(index()); | 5578 Location in_loc = pair->At(index()); |
5588 if (representation() == kUnboxedDouble) { | 5579 if (representation() == kUnboxedDouble) { |
5589 XmmRegister out = locs()->out(0).fpu_reg(); | 5580 XmmRegister out = locs()->out(0).fpu_reg(); |
5590 XmmRegister in = in_loc.fpu_reg(); | 5581 XmmRegister in = in_loc.fpu_reg(); |
5591 __ movaps(out, in); | 5582 __ movaps(out, in); |
5592 } else { | 5583 } else { |
5593 ASSERT(representation() == kTagged); | 5584 ASSERT(representation() == kTagged); |
5594 Register out = locs()->out(0).reg(); | 5585 Register out = locs()->out(0).reg(); |
5595 Register in = in_loc.reg(); | 5586 Register in = in_loc.reg(); |
5596 __ movq(out, in); | 5587 __ movq(out, in); |
5597 } | 5588 } |
5598 } | 5589 } |
5599 | 5590 |
5600 | 5591 |
5601 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5592 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
5602 bool opt) const { | 5593 bool opt) const { |
5603 if (kind() == MergedMathInstr::kTruncDivMod) { | 5594 if (kind() == MergedMathInstr::kTruncDivMod) { |
5604 const intptr_t kNumInputs = 2; | 5595 const intptr_t kNumInputs = 2; |
5605 const intptr_t kNumTemps = 0; | 5596 const intptr_t kNumTemps = 0; |
5606 LocationSummary* summary = new(zone) LocationSummary( | 5597 LocationSummary* summary = new (zone) |
5607 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5598 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5608 // Both inputs must be writable because they will be untagged. | 5599 // Both inputs must be writable because they will be untagged. |
5609 summary->set_in(0, Location::RegisterLocation(RAX)); | 5600 summary->set_in(0, Location::RegisterLocation(RAX)); |
5610 summary->set_in(1, Location::WritableRegister()); | 5601 summary->set_in(1, Location::WritableRegister()); |
5611 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), | 5602 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
5612 Location::RegisterLocation(RDX))); | 5603 Location::RegisterLocation(RDX))); |
5613 return summary; | 5604 return summary; |
5614 } | 5605 } |
5615 if (kind() == MergedMathInstr::kSinCos) { | 5606 if (kind() == MergedMathInstr::kSinCos) { |
5616 const intptr_t kNumInputs = 1; | 5607 const intptr_t kNumInputs = 1; |
5617 const intptr_t kNumTemps = 1; | 5608 const intptr_t kNumTemps = 1; |
5618 LocationSummary* summary = new(zone) LocationSummary( | 5609 LocationSummary* summary = new (zone) |
5619 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5610 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5620 // Because we always call into the runtime (LocationSummary::kCall) we | 5611 // Because we always call into the runtime (LocationSummary::kCall) we |
5621 // must specify each input, temp, and output register explicitly. | 5612 // must specify each input, temp, and output register explicitly. |
5622 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5613 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
5623 // R13 is chosen because it is callee saved so we do not need to back it | 5614 // R13 is chosen because it is callee saved so we do not need to back it |
5624 // up before calling into the runtime. | 5615 // up before calling into the runtime. |
5625 summary->set_temp(0, Location::RegisterLocation(R13)); | 5616 summary->set_temp(0, Location::RegisterLocation(R13)); |
5626 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), | 5617 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), |
5627 Location::FpuRegisterLocation(XMM3))); | 5618 Location::FpuRegisterLocation(XMM3))); |
5628 return summary; | 5619 return summary; |
5629 } | 5620 } |
5630 UNIMPLEMENTED(); | 5621 UNIMPLEMENTED(); |
5631 return NULL; | 5622 return NULL; |
5632 } | 5623 } |
5633 | 5624 |
5634 | 5625 |
5635 | 5626 typedef void (*SinCosCFunction)(double x, double* res_sin, double* res_cos); |
5636 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | |
5637 | 5627 |
5638 extern const RuntimeEntry kSinCosRuntimeEntry( | 5628 extern const RuntimeEntry kSinCosRuntimeEntry( |
5639 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 5629 "libc_sincos", |
5640 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 5630 reinterpret_cast<RuntimeFunction>(static_cast<SinCosCFunction>(&SinCos)), |
| 5631 1, |
| 5632 true, |
| 5633 true); |
5641 | 5634 |
5642 | 5635 |
5643 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5636 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5644 Label* deopt = NULL; | 5637 Label* deopt = NULL; |
5645 if (CanDeoptimize()) { | 5638 if (CanDeoptimize()) { |
5646 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5639 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5647 } | 5640 } |
5648 if (kind() == MergedMathInstr::kTruncDivMod) { | 5641 if (kind() == MergedMathInstr::kTruncDivMod) { |
5649 Register left = locs()->in(0).reg(); | 5642 Register left = locs()->in(0).reg(); |
5650 Register right = locs()->in(1).reg(); | 5643 Register right = locs()->in(1).reg(); |
5651 ASSERT(locs()->out(0).IsPairLocation()); | 5644 ASSERT(locs()->out(0).IsPairLocation()); |
5652 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5645 PairLocation* pair = locs()->out(0).AsPairLocation(); |
5653 Register result1 = pair->At(0).reg(); | 5646 Register result1 = pair->At(0).reg(); |
5654 Register result2 = pair->At(1).reg(); | 5647 Register result2 = pair->At(1).reg(); |
5655 Label not_32bit, done; | 5648 Label not_32bit, done; |
5656 Register temp = RDX; | 5649 Register temp = RDX; |
(...skipping 25 matching lines...) Expand all Loading... |
5682 __ cdq(); | 5675 __ cdq(); |
5683 __ idivl(right); | 5676 __ idivl(right); |
5684 __ movsxd(RAX, RAX); | 5677 __ movsxd(RAX, RAX); |
5685 __ movsxd(RDX, RDX); | 5678 __ movsxd(RDX, RDX); |
5686 __ jmp(&done); | 5679 __ jmp(&done); |
5687 | 5680 |
5688 // Divide using 64bit idiv. | 5681 // Divide using 64bit idiv. |
5689 __ Bind(¬_32bit); | 5682 __ Bind(¬_32bit); |
5690 __ SmiUntag(left); | 5683 __ SmiUntag(left); |
5691 __ SmiUntag(right); | 5684 __ SmiUntag(right); |
5692 __ cqo(); // Sign extend RAX -> RDX:RAX. | 5685 __ cqo(); // Sign extend RAX -> RDX:RAX. |
5693 __ idivq(right); // RAX: quotient, RDX: remainder. | 5686 __ idivq(right); // RAX: quotient, RDX: remainder. |
5694 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5687 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
5695 // case we cannot tag the result. | 5688 // case we cannot tag the result. |
5696 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); | 5689 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); |
5697 __ j(EQUAL, deopt); | 5690 __ j(EQUAL, deopt); |
5698 __ Bind(&done); | 5691 __ Bind(&done); |
5699 | 5692 |
5700 // Modulo correction (RDX). | 5693 // Modulo correction (RDX). |
5701 // res = left % right; | 5694 // res = left % right; |
5702 // if (res < 0) { | 5695 // if (res < 0) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5755 // .... | 5748 // .... |
5756 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); | 5749 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); |
5757 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); | 5750 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); |
5758 | 5751 |
5759 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); | 5752 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); |
5760 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); | 5753 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); |
5761 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 5754 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
5762 | 5755 |
5763 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); | 5756 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); |
5764 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. | 5757 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. |
5765 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. | 5758 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. |
5766 // Restore RSP. | 5759 // Restore RSP. |
5767 __ movq(RSP, locs()->temp(0).reg()); | 5760 __ movq(RSP, locs()->temp(0).reg()); |
5768 | 5761 |
5769 return; | 5762 return; |
5770 } | 5763 } |
5771 UNIMPLEMENTED(); | 5764 UNIMPLEMENTED(); |
5772 } | 5765 } |
5773 | 5766 |
5774 | 5767 |
5775 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5768 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5776 Zone* zone, bool opt) const { | 5769 Zone* zone, |
| 5770 bool opt) const { |
5777 return MakeCallSummary(zone); | 5771 return MakeCallSummary(zone); |
5778 } | 5772 } |
5779 | 5773 |
5780 | 5774 |
5781 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 5775 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5782 bool opt) const { | |
5783 comparison()->InitializeLocationSummary(zone, opt); | 5776 comparison()->InitializeLocationSummary(zone, opt); |
5784 // Branches don't produce a result. | 5777 // Branches don't produce a result. |
5785 comparison()->locs()->set_out(0, Location::NoLocation()); | 5778 comparison()->locs()->set_out(0, Location::NoLocation()); |
5786 return comparison()->locs(); | 5779 return comparison()->locs(); |
5787 } | 5780 } |
5788 | 5781 |
5789 | 5782 |
5790 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5783 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5791 comparison()->EmitBranchCode(compiler, this); | 5784 comparison()->EmitBranchCode(compiler, this); |
5792 } | 5785 } |
5793 | 5786 |
5794 | 5787 |
5795 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5788 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5796 bool opt) const { | 5789 bool opt) const { |
5797 const intptr_t kNumInputs = 1; | 5790 const intptr_t kNumInputs = 1; |
5798 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5791 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
5799 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5792 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5800 LocationSummary* summary = new(zone) LocationSummary( | 5793 LocationSummary* summary = new (zone) |
5801 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5802 summary->set_in(0, Location::RequiresRegister()); | 5795 summary->set_in(0, Location::RequiresRegister()); |
5803 if (!IsNullCheck()) { | 5796 if (!IsNullCheck()) { |
5804 summary->set_temp(0, Location::RequiresRegister()); | 5797 summary->set_temp(0, Location::RequiresRegister()); |
5805 if (need_mask_temp) { | 5798 if (need_mask_temp) { |
5806 summary->set_temp(1, Location::RequiresRegister()); | 5799 summary->set_temp(1, Location::RequiresRegister()); |
5807 } | 5800 } |
5808 } | 5801 } |
5809 return summary; | 5802 return summary; |
5810 } | 5803 } |
5811 | 5804 |
5812 | 5805 |
5813 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5806 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5814 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5807 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
5815 ICData::kDeoptCheckClass, | |
5816 licm_hoisted_ ? ICData::kHoisted : 0); | 5808 licm_hoisted_ ? ICData::kHoisted : 0); |
5817 if (IsNullCheck()) { | 5809 if (IsNullCheck()) { |
5818 __ CompareObject(locs()->in(0).reg(), | 5810 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
5819 Object::null_object()); | |
5820 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; | 5811 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; |
5821 __ j(cond, deopt); | 5812 __ j(cond, deopt); |
5822 return; | 5813 return; |
5823 } | 5814 } |
5824 | 5815 |
5825 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5816 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
5826 (unary_checks().NumberOfChecks() > 1)); | 5817 (unary_checks().NumberOfChecks() > 1)); |
5827 Register value = locs()->in(0).reg(); | 5818 Register value = locs()->in(0).reg(); |
5828 Register temp = locs()->temp(0).reg(); | 5819 Register temp = locs()->temp(0).reg(); |
5829 Label is_ok; | 5820 Label is_ok; |
(...skipping 16 matching lines...) Expand all Loading... |
5846 if (!IsDenseMask(mask)) { | 5837 if (!IsDenseMask(mask)) { |
5847 // Only need mask if there are missing numbers in the range. | 5838 // Only need mask if there are missing numbers in the range. |
5848 ASSERT(cids_.length() > 2); | 5839 ASSERT(cids_.length() > 2); |
5849 Register mask_reg = locs()->temp(1).reg(); | 5840 Register mask_reg = locs()->temp(1).reg(); |
5850 __ movq(mask_reg, Immediate(mask)); | 5841 __ movq(mask_reg, Immediate(mask)); |
5851 __ btq(mask_reg, temp); | 5842 __ btq(mask_reg, temp); |
5852 __ j(NOT_CARRY, deopt); | 5843 __ j(NOT_CARRY, deopt); |
5853 } | 5844 } |
5854 } else { | 5845 } else { |
5855 GrowableArray<CidTarget> sorted_ic_data; | 5846 GrowableArray<CidTarget> sorted_ic_data; |
5856 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5847 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
5857 &sorted_ic_data, | |
5858 /* drop_smi = */ true); | 5848 /* drop_smi = */ true); |
5859 const intptr_t num_checks = sorted_ic_data.length(); | 5849 const intptr_t num_checks = sorted_ic_data.length(); |
5860 const bool use_near_jump = num_checks < 5; | 5850 const bool use_near_jump = num_checks < 5; |
5861 for (intptr_t i = 0; i < num_checks; i++) { | 5851 for (intptr_t i = 0; i < num_checks; i++) { |
5862 const intptr_t cid = sorted_ic_data[i].cid; | 5852 const intptr_t cid = sorted_ic_data[i].cid; |
5863 __ cmpl(temp, Immediate(cid)); | 5853 __ cmpl(temp, Immediate(cid)); |
5864 if (i == (num_checks - 1)) { | 5854 if (i == (num_checks - 1)) { |
5865 __ j(NOT_EQUAL, deopt); | 5855 __ j(NOT_EQUAL, deopt); |
5866 } else { | 5856 } else { |
5867 if (use_near_jump) { | 5857 if (use_near_jump) { |
5868 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 5858 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
5869 } else { | 5859 } else { |
5870 __ j(EQUAL, &is_ok); | 5860 __ j(EQUAL, &is_ok); |
5871 } | 5861 } |
5872 } | 5862 } |
5873 } | 5863 } |
5874 } | 5864 } |
5875 __ Bind(&is_ok); | 5865 __ Bind(&is_ok); |
5876 } | 5866 } |
5877 | 5867 |
5878 | 5868 |
5879 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5869 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5880 bool opt) const { | 5870 bool opt) const { |
5881 const intptr_t kNumInputs = 1; | 5871 const intptr_t kNumInputs = 1; |
5882 const intptr_t kNumTemps = 0; | 5872 const intptr_t kNumTemps = 0; |
5883 LocationSummary* summary = new(zone) LocationSummary( | 5873 LocationSummary* summary = new (zone) |
5884 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5874 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5885 summary->set_in(0, Location::RequiresRegister()); | 5875 summary->set_in(0, Location::RequiresRegister()); |
5886 return summary; | 5876 return summary; |
5887 } | 5877 } |
5888 | 5878 |
5889 | 5879 |
5890 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5880 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5891 Register value = locs()->in(0).reg(); | 5881 Register value = locs()->in(0).reg(); |
5892 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5882 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
5893 ICData::kDeoptCheckSmi, | |
5894 licm_hoisted_ ? ICData::kHoisted : 0); | 5883 licm_hoisted_ ? ICData::kHoisted : 0); |
5895 __ BranchIfNotSmi(value, deopt); | 5884 __ BranchIfNotSmi(value, deopt); |
5896 } | 5885 } |
5897 | 5886 |
5898 | 5887 |
5899 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5888 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5900 bool opt) const { | 5889 bool opt) const { |
5901 const intptr_t kNumInputs = 1; | 5890 const intptr_t kNumInputs = 1; |
5902 const intptr_t kNumTemps = 0; | 5891 const intptr_t kNumTemps = 0; |
5903 LocationSummary* summary = new(zone) LocationSummary( | 5892 LocationSummary* summary = new (zone) |
5904 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5893 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5905 summary->set_in(0, Location::RequiresRegister()); | 5894 summary->set_in(0, Location::RequiresRegister()); |
5906 return summary; | 5895 return summary; |
5907 } | 5896 } |
5908 | 5897 |
5909 | 5898 |
5910 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5899 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5911 Register value = locs()->in(0).reg(); | 5900 Register value = locs()->in(0).reg(); |
5912 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5901 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
5913 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_))); | 5902 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_))); |
5914 __ j(NOT_ZERO, deopt); | 5903 __ j(NOT_ZERO, deopt); |
5915 } | 5904 } |
5916 | 5905 |
5917 | 5906 |
5918 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5907 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
5919 bool opt) const { | 5908 bool opt) const { |
5920 const intptr_t kNumInputs = 2; | 5909 const intptr_t kNumInputs = 2; |
5921 const intptr_t kNumTemps = 0; | 5910 const intptr_t kNumTemps = 0; |
5922 LocationSummary* locs = new(zone) LocationSummary( | 5911 LocationSummary* locs = new (zone) LocationSummary( |
5923 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5912 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
5924 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5913 locs->set_in(kLengthPos, Location::RequiresRegister()); |
5925 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5914 locs->set_in(kIndexPos, Location::RequiresRegister()); |
5926 return locs; | 5915 return locs; |
5927 } | 5916 } |
5928 | 5917 |
5929 | 5918 |
5930 class RangeErrorSlowPath : public SlowPathCode { | 5919 class RangeErrorSlowPath : public SlowPathCode { |
5931 public: | 5920 public: |
5932 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5921 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
5933 : instruction_(instruction), try_index_(try_index) { } | 5922 : instruction_(instruction), try_index_(try_index) {} |
5934 | 5923 |
5935 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5924 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5936 if (Assembler::EmittingComments()) { | 5925 if (Assembler::EmittingComments()) { |
5937 __ Comment("slow path check bound operation"); | 5926 __ Comment("slow path check bound operation"); |
5938 } | 5927 } |
5939 __ Bind(entry_label()); | 5928 __ Bind(entry_label()); |
5940 LocationSummary* locs = instruction_->locs(); | 5929 LocationSummary* locs = instruction_->locs(); |
5941 __ pushq(locs->in(0).reg()); | 5930 __ pushq(locs->in(0).reg()); |
5942 __ pushq(locs->in(1).reg()); | 5931 __ pushq(locs->in(1).reg()); |
5943 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5932 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
5944 compiler->pc_descriptors_list()->AddDescriptor( | 5933 compiler->pc_descriptors_list()->AddDescriptor( |
5945 RawPcDescriptors::kOther, | 5934 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
5946 compiler->assembler()->CodeSize(), | 5935 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
5947 instruction_->deopt_id(), | |
5948 instruction_->token_pos(), | |
5949 try_index_); | |
5950 compiler->RecordSafepoint(locs, 2); | 5936 compiler->RecordSafepoint(locs, 2); |
5951 __ int3(); | 5937 __ int3(); |
5952 } | 5938 } |
5953 | 5939 |
5954 private: | 5940 private: |
5955 GenericCheckBoundInstr* instruction_; | 5941 GenericCheckBoundInstr* instruction_; |
5956 intptr_t try_index_; | 5942 intptr_t try_index_; |
5957 }; | 5943 }; |
5958 | 5944 |
5959 | 5945 |
(...skipping 12 matching lines...) Expand all Loading... |
5972 } | 5958 } |
5973 __ cmpq(index, length); | 5959 __ cmpq(index, length); |
5974 __ j(ABOVE_EQUAL, slow_path->entry_label()); | 5960 __ j(ABOVE_EQUAL, slow_path->entry_label()); |
5975 } | 5961 } |
5976 | 5962 |
5977 | 5963 |
5978 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5964 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
5979 bool opt) const { | 5965 bool opt) const { |
5980 const intptr_t kNumInputs = 2; | 5966 const intptr_t kNumInputs = 2; |
5981 const intptr_t kNumTemps = 0; | 5967 const intptr_t kNumTemps = 0; |
5982 LocationSummary* locs = new(zone) LocationSummary( | 5968 LocationSummary* locs = new (zone) |
5983 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5984 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5970 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
5985 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5971 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
5986 return locs; | 5972 return locs; |
5987 } | 5973 } |
5988 | 5974 |
5989 | 5975 |
5990 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5976 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5991 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5977 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
5992 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5978 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
5993 Label* deopt = compiler->AddDeoptStub( | 5979 Label* deopt = |
5994 deopt_id(), | 5980 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
5995 ICData::kDeoptCheckArrayBound, | |
5996 flags); | |
5997 | 5981 |
5998 Location length_loc = locs()->in(kLengthPos); | 5982 Location length_loc = locs()->in(kLengthPos); |
5999 Location index_loc = locs()->in(kIndexPos); | 5983 Location index_loc = locs()->in(kIndexPos); |
6000 | 5984 |
6001 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5985 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
6002 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5986 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
6003 Smi::Cast(index_loc.constant()).Value()) || | 5987 Smi::Cast(index_loc.constant()).Value()) || |
6004 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5988 (Smi::Cast(index_loc.constant()).Value() < 0)); |
6005 // Unconditionally deoptimize for constant bounds checks because they | 5989 // Unconditionally deoptimize for constant bounds checks because they |
6006 // only occur only when index is out-of-bounds. | 5990 // only occur only when index is out-of-bounds. |
6007 __ jmp(deopt); | 5991 __ jmp(deopt); |
6008 return; | 5992 return; |
6009 } | 5993 } |
6010 | 5994 |
6011 const intptr_t index_cid = index()->Type()->ToCid(); | 5995 const intptr_t index_cid = index()->Type()->ToCid(); |
6012 if (index_loc.IsConstant()) { | 5996 if (index_loc.IsConstant()) { |
6013 Register length = length_loc.reg(); | 5997 Register length = length_loc.reg(); |
6014 const Smi& index = Smi::Cast(index_loc.constant()); | 5998 const Smi& index = Smi::Cast(index_loc.constant()); |
6015 __ CompareImmediate( | 5999 __ CompareImmediate(length, |
6016 length, Immediate(reinterpret_cast<int64_t>(index.raw()))); | 6000 Immediate(reinterpret_cast<int64_t>(index.raw()))); |
6017 __ j(BELOW_EQUAL, deopt); | 6001 __ j(BELOW_EQUAL, deopt); |
6018 } else if (length_loc.IsConstant()) { | 6002 } else if (length_loc.IsConstant()) { |
6019 const Smi& length = Smi::Cast(length_loc.constant()); | 6003 const Smi& length = Smi::Cast(length_loc.constant()); |
6020 Register index = index_loc.reg(); | 6004 Register index = index_loc.reg(); |
6021 if (index_cid != kSmiCid) { | 6005 if (index_cid != kSmiCid) { |
6022 __ BranchIfNotSmi(index, deopt); | 6006 __ BranchIfNotSmi(index, deopt); |
6023 } | 6007 } |
6024 if (length.Value() == Smi::kMaxValue) { | 6008 if (length.Value() == Smi::kMaxValue) { |
6025 __ testq(index, index); | 6009 __ testq(index, index); |
6026 __ j(NEGATIVE, deopt); | 6010 __ j(NEGATIVE, deopt); |
6027 } else { | 6011 } else { |
6028 __ CompareImmediate( | 6012 __ CompareImmediate(index, |
6029 index, Immediate(reinterpret_cast<int64_t>(length.raw()))); | 6013 Immediate(reinterpret_cast<int64_t>(length.raw()))); |
6030 __ j(ABOVE_EQUAL, deopt); | 6014 __ j(ABOVE_EQUAL, deopt); |
6031 } | 6015 } |
6032 } else { | 6016 } else { |
6033 Register length = length_loc.reg(); | 6017 Register length = length_loc.reg(); |
6034 Register index = index_loc.reg(); | 6018 Register index = index_loc.reg(); |
6035 if (index_cid != kSmiCid) { | 6019 if (index_cid != kSmiCid) { |
6036 __ BranchIfNotSmi(index, deopt); | 6020 __ BranchIfNotSmi(index, deopt); |
6037 } | 6021 } |
6038 __ cmpq(index, length); | 6022 __ cmpq(index, length); |
6039 __ j(ABOVE_EQUAL, deopt); | 6023 __ j(ABOVE_EQUAL, deopt); |
6040 } | 6024 } |
6041 } | 6025 } |
6042 | 6026 |
6043 | 6027 |
6044 template<typename OperandType> | 6028 template <typename OperandType> |
6045 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, | 6029 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, |
6046 Token::Kind op_kind, | 6030 Token::Kind op_kind, |
6047 Register left, | 6031 Register left, |
6048 const OperandType& right, | 6032 const OperandType& right, |
6049 Label* deopt) { | 6033 Label* deopt) { |
6050 switch (op_kind) { | 6034 switch (op_kind) { |
6051 case Token::kADD: | 6035 case Token::kADD: |
6052 __ addq(left, right); | 6036 __ addq(left, right); |
6053 break; | 6037 break; |
6054 case Token::kSUB: | 6038 case Token::kSUB: |
(...skipping 15 matching lines...) Expand all Loading... |
6070 UNREACHABLE(); | 6054 UNREACHABLE(); |
6071 } | 6055 } |
6072 if (deopt != NULL) __ j(OVERFLOW, deopt); | 6056 if (deopt != NULL) __ j(OVERFLOW, deopt); |
6073 } | 6057 } |
6074 | 6058 |
6075 | 6059 |
6076 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6060 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6077 bool opt) const { | 6061 bool opt) const { |
6078 const intptr_t kNumInputs = 2; | 6062 const intptr_t kNumInputs = 2; |
6079 const intptr_t kNumTemps = 0; | 6063 const intptr_t kNumTemps = 0; |
6080 LocationSummary* summary = new(zone) LocationSummary( | 6064 LocationSummary* summary = new (zone) |
6081 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6065 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6082 summary->set_in(0, Location::RequiresRegister()); | 6066 summary->set_in(0, Location::RequiresRegister()); |
6083 summary->set_in(1, Location::RequiresRegister()); | 6067 summary->set_in(1, Location::RequiresRegister()); |
6084 summary->set_out(0, Location::SameAsFirstInput()); | 6068 summary->set_out(0, Location::SameAsFirstInput()); |
6085 return summary; | 6069 return summary; |
6086 } | 6070 } |
6087 | 6071 |
6088 | 6072 |
6089 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6073 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6090 const Register left = locs()->in(0).reg(); | 6074 const Register left = locs()->in(0).reg(); |
6091 const Register right = locs()->in(1).reg(); | 6075 const Register right = locs()->in(1).reg(); |
6092 const Register out = locs()->out(0).reg(); | 6076 const Register out = locs()->out(0).reg(); |
6093 | 6077 |
6094 ASSERT(out == left); | 6078 ASSERT(out == left); |
6095 | 6079 |
6096 Label* deopt = NULL; | 6080 Label* deopt = NULL; |
6097 if (CanDeoptimize()) { | 6081 if (CanDeoptimize()) { |
6098 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6082 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6099 } | 6083 } |
6100 | 6084 |
6101 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | 6085 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
6102 } | 6086 } |
6103 | 6087 |
6104 | 6088 |
6105 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6089 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6106 bool opt) const { | 6090 bool opt) const { |
6107 const intptr_t kNumInputs = 1; | 6091 const intptr_t kNumInputs = 1; |
6108 const intptr_t kNumTemps = 0; | 6092 const intptr_t kNumTemps = 0; |
6109 LocationSummary* summary = new(zone) LocationSummary( | 6093 LocationSummary* summary = new (zone) |
6110 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6094 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6111 summary->set_in(0, Location::RequiresRegister()); | 6095 summary->set_in(0, Location::RequiresRegister()); |
6112 summary->set_out(0, Location::SameAsFirstInput()); | 6096 summary->set_out(0, Location::SameAsFirstInput()); |
6113 return summary; | 6097 return summary; |
6114 } | 6098 } |
6115 | 6099 |
6116 | 6100 |
6117 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6101 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6118 ASSERT(op_kind() == Token::kBIT_NOT); | 6102 ASSERT(op_kind() == Token::kBIT_NOT); |
6119 const Register left = locs()->in(0).reg(); | 6103 const Register left = locs()->in(0).reg(); |
6120 const Register out = locs()->out(0).reg(); | 6104 const Register out = locs()->out(0).reg(); |
6121 ASSERT(out == left); | 6105 ASSERT(out == left); |
6122 __ notq(left); | 6106 __ notq(left); |
6123 } | 6107 } |
6124 | 6108 |
6125 | 6109 |
6126 static const intptr_t kMintShiftCountLimit = 63; | 6110 static const intptr_t kMintShiftCountLimit = 63; |
6127 | 6111 |
6128 bool ShiftMintOpInstr::has_shift_count_check() const { | 6112 bool ShiftMintOpInstr::has_shift_count_check() const { |
6129 return !RangeUtils::IsWithin( | 6113 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
6130 right()->definition()->range(), 0, kMintShiftCountLimit); | 6114 kMintShiftCountLimit); |
6131 } | 6115 } |
6132 | 6116 |
6133 | 6117 |
6134 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6118 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
6135 bool opt) const { | 6119 bool opt) const { |
6136 const intptr_t kNumInputs = 2; | 6120 const intptr_t kNumInputs = 2; |
6137 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 6121 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
6138 LocationSummary* summary = new(zone) LocationSummary( | 6122 LocationSummary* summary = new (zone) |
6139 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6123 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6140 summary->set_in(0, Location::RequiresRegister()); | 6124 summary->set_in(0, Location::RequiresRegister()); |
6141 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 6125 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
6142 if (kNumTemps > 0) { | 6126 if (kNumTemps > 0) { |
6143 summary->set_temp(0, Location::RequiresRegister()); | 6127 summary->set_temp(0, Location::RequiresRegister()); |
6144 } | 6128 } |
6145 summary->set_out(0, Location::SameAsFirstInput()); | 6129 summary->set_out(0, Location::SameAsFirstInput()); |
6146 return summary; | 6130 return summary; |
6147 } | 6131 } |
6148 | 6132 |
6149 | 6133 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6231 | 6215 |
6232 CompileType UnaryUint32OpInstr::ComputeType() const { | 6216 CompileType UnaryUint32OpInstr::ComputeType() const { |
6233 return CompileType::FromCid(kSmiCid); | 6217 return CompileType::FromCid(kSmiCid); |
6234 } | 6218 } |
6235 | 6219 |
6236 | 6220 |
6237 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6221 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6238 bool opt) const { | 6222 bool opt) const { |
6239 const intptr_t kNumInputs = 2; | 6223 const intptr_t kNumInputs = 2; |
6240 const intptr_t kNumTemps = 0; | 6224 const intptr_t kNumTemps = 0; |
6241 LocationSummary* summary = new(zone) LocationSummary( | 6225 LocationSummary* summary = new (zone) |
6242 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6226 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6243 summary->set_in(0, Location::RequiresRegister()); | 6227 summary->set_in(0, Location::RequiresRegister()); |
6244 summary->set_in(1, Location::RequiresRegister()); | 6228 summary->set_in(1, Location::RequiresRegister()); |
6245 summary->set_out(0, Location::SameAsFirstInput()); | 6229 summary->set_out(0, Location::SameAsFirstInput()); |
6246 return summary; | 6230 return summary; |
6247 } | 6231 } |
6248 | 6232 |
6249 | 6233 |
6250 template<typename OperandType> | 6234 template <typename OperandType> |
6251 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 6235 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
6252 Token::Kind op_kind, | 6236 Token::Kind op_kind, |
6253 Register left, | 6237 Register left, |
6254 const OperandType& right, | 6238 const OperandType& right, |
6255 Label* deopt) { | 6239 Label* deopt) { |
6256 switch (op_kind) { | 6240 switch (op_kind) { |
6257 case Token::kADD: | 6241 case Token::kADD: |
6258 __ addl(left, right); | 6242 __ addl(left, right); |
6259 break; | 6243 break; |
6260 case Token::kSUB: | 6244 case Token::kSUB: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6296 default: | 6280 default: |
6297 UNREACHABLE(); | 6281 UNREACHABLE(); |
6298 } | 6282 } |
6299 } | 6283 } |
6300 | 6284 |
6301 | 6285 |
6302 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6286 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
6303 bool opt) const { | 6287 bool opt) const { |
6304 const intptr_t kNumInputs = 2; | 6288 const intptr_t kNumInputs = 2; |
6305 const intptr_t kNumTemps = 0; | 6289 const intptr_t kNumTemps = 0; |
6306 LocationSummary* summary = new(zone) LocationSummary( | 6290 LocationSummary* summary = new (zone) |
6307 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6291 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6308 summary->set_in(0, Location::RequiresRegister()); | 6292 summary->set_in(0, Location::RequiresRegister()); |
6309 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 6293 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
6310 summary->set_out(0, Location::SameAsFirstInput()); | 6294 summary->set_out(0, Location::SameAsFirstInput()); |
6311 return summary; | 6295 return summary; |
6312 } | 6296 } |
6313 | 6297 |
6314 | 6298 |
6315 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6299 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6316 const intptr_t kShifterLimit = 31; | 6300 const intptr_t kShifterLimit = 31; |
6317 | 6301 |
6318 Register left = locs()->in(0).reg(); | 6302 Register left = locs()->in(0).reg(); |
6319 Register out = locs()->out(0).reg(); | 6303 Register out = locs()->out(0).reg(); |
6320 ASSERT(left == out); | 6304 ASSERT(left == out); |
6321 | 6305 |
6322 | 6306 |
6323 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6307 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6324 | 6308 |
6325 if (locs()->in(1).IsConstant()) { | 6309 if (locs()->in(1).IsConstant()) { |
6326 // Shifter is constant. | 6310 // Shifter is constant. |
6327 | 6311 |
6328 const Object& constant = locs()->in(1).constant(); | 6312 const Object& constant = locs()->in(1).constant(); |
6329 ASSERT(constant.IsSmi()); | 6313 ASSERT(constant.IsSmi()); |
6330 const intptr_t shift_value = Smi::Cast(constant).Value(); | 6314 const intptr_t shift_value = Smi::Cast(constant).Value(); |
6331 | 6315 |
6332 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 6316 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
6333 switch (op_kind()) { | 6317 switch (op_kind()) { |
6334 case Token::kSHR: | 6318 case Token::kSHR: |
6335 __ shrl(left, Immediate(shift_value)); | 6319 __ shrl(left, Immediate(shift_value)); |
6336 break; | 6320 break; |
6337 case Token::kSHL: | 6321 case Token::kSHL: |
6338 __ shll(left, Immediate(shift_value)); | 6322 __ shll(left, Immediate(shift_value)); |
6339 break; | 6323 break; |
6340 default: | 6324 default: |
6341 UNREACHABLE(); | 6325 UNREACHABLE(); |
6342 } | 6326 } |
6343 return; | 6327 return; |
6344 } | 6328 } |
6345 | 6329 |
6346 // Non constant shift value. | 6330 // Non constant shift value. |
6347 | 6331 |
6348 Register shifter = locs()->in(1).reg(); | 6332 Register shifter = locs()->in(1).reg(); |
6349 ASSERT(shifter == RCX); | 6333 ASSERT(shifter == RCX); |
6350 | 6334 |
6351 Label done; | 6335 Label done; |
6352 Label zero; | 6336 Label zero; |
6353 | 6337 |
6354 // TODO(johnmccutchan): Use range information to avoid these checks. | 6338 // TODO(johnmccutchan): Use range information to avoid these checks. |
6355 __ SmiUntag(shifter); | 6339 __ SmiUntag(shifter); |
6356 __ cmpq(shifter, Immediate(0)); | 6340 __ cmpq(shifter, Immediate(0)); |
6357 // If shift value is < 0, deoptimize. | 6341 // If shift value is < 0, deoptimize. |
6358 __ j(NEGATIVE, deopt); | 6342 __ j(NEGATIVE, deopt); |
6359 __ cmpq(shifter, Immediate(kShifterLimit)); | 6343 __ cmpq(shifter, Immediate(kShifterLimit)); |
6360 // If shift value is >= 32, return zero. | 6344 // If shift value is >= 32, return zero. |
6361 __ j(ABOVE, &zero); | 6345 __ j(ABOVE, &zero); |
6362 | 6346 |
6363 // Do the shift. | 6347 // Do the shift. |
6364 switch (op_kind()) { | 6348 switch (op_kind()) { |
6365 case Token::kSHR: | 6349 case Token::kSHR: |
6366 __ shrl(left, shifter); | 6350 __ shrl(left, shifter); |
6367 __ jmp(&done); | 6351 __ jmp(&done); |
6368 break; | 6352 break; |
6369 case Token::kSHL: | 6353 case Token::kSHL: |
6370 __ shll(left, shifter); | 6354 __ shll(left, shifter); |
6371 __ jmp(&done); | 6355 __ jmp(&done); |
6372 break; | 6356 break; |
6373 default: | 6357 default: |
6374 UNREACHABLE(); | 6358 UNREACHABLE(); |
6375 } | 6359 } |
6376 | 6360 |
6377 __ Bind(&zero); | 6361 __ Bind(&zero); |
6378 // Shift was greater than 31 bits, just return zero. | 6362 // Shift was greater than 31 bits, just return zero. |
6379 __ xorq(left, left); | 6363 __ xorq(left, left); |
6380 | 6364 |
6381 // Exit path. | 6365 // Exit path. |
6382 __ Bind(&done); | 6366 __ Bind(&done); |
6383 } | 6367 } |
6384 | 6368 |
6385 | 6369 |
6386 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6370 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6387 bool opt) const { | 6371 bool opt) const { |
6388 const intptr_t kNumInputs = 1; | 6372 const intptr_t kNumInputs = 1; |
6389 const intptr_t kNumTemps = 0; | 6373 const intptr_t kNumTemps = 0; |
6390 LocationSummary* summary = new(zone) LocationSummary( | 6374 LocationSummary* summary = new (zone) |
6391 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6375 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6392 summary->set_in(0, Location::RequiresRegister()); | 6376 summary->set_in(0, Location::RequiresRegister()); |
6393 summary->set_out(0, Location::SameAsFirstInput()); | 6377 summary->set_out(0, Location::SameAsFirstInput()); |
6394 return summary; | 6378 return summary; |
6395 } | 6379 } |
6396 | 6380 |
6397 | 6381 |
6398 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6382 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6399 Register out = locs()->out(0).reg(); | 6383 Register out = locs()->out(0).reg(); |
6400 ASSERT(locs()->in(0).reg() == out); | 6384 ASSERT(locs()->in(0).reg() == out); |
6401 | 6385 |
6402 ASSERT(op_kind() == Token::kBIT_NOT); | 6386 ASSERT(op_kind() == Token::kBIT_NOT); |
6403 | 6387 |
6404 __ notl(out); | 6388 __ notl(out); |
6405 } | 6389 } |
6406 | 6390 |
6407 | 6391 |
6408 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 6392 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
6409 | 6393 |
6410 | 6394 |
6411 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6395 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
6412 bool opt) const { | 6396 bool opt) const { |
6413 const intptr_t kNumInputs = 1; | 6397 const intptr_t kNumInputs = 1; |
6414 const intptr_t kNumTemps = 0; | 6398 const intptr_t kNumTemps = 0; |
6415 LocationSummary* summary = new(zone) LocationSummary( | 6399 LocationSummary* summary = new (zone) |
6416 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6400 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6417 if (from() == kUnboxedMint) { | 6401 if (from() == kUnboxedMint) { |
6418 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6402 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
6419 summary->set_in(0, Location::RequiresRegister()); | 6403 summary->set_in(0, Location::RequiresRegister()); |
6420 summary->set_out(0, Location::SameAsFirstInput()); | 6404 summary->set_out(0, Location::SameAsFirstInput()); |
6421 } else if (to() == kUnboxedMint) { | 6405 } else if (to() == kUnboxedMint) { |
6422 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); | 6406 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
6423 summary->set_in(0, Location::RequiresRegister()); | 6407 summary->set_in(0, Location::RequiresRegister()); |
6424 summary->set_out(0, Location::SameAsFirstInput()); | 6408 summary->set_out(0, Location::SameAsFirstInput()); |
6425 } else { | 6409 } else { |
6426 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6410 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6480 // Sign extend. | 6464 // Sign extend. |
6481 ASSERT(from() == kUnboxedInt32); | 6465 ASSERT(from() == kUnboxedInt32); |
6482 __ movsxd(out, value); | 6466 __ movsxd(out, value); |
6483 } | 6467 } |
6484 } else { | 6468 } else { |
6485 UNREACHABLE(); | 6469 UNREACHABLE(); |
6486 } | 6470 } |
6487 } | 6471 } |
6488 | 6472 |
6489 | 6473 |
6490 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 6474 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6491 bool opt) const { | 6475 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6492 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
6493 } | 6476 } |
6494 | 6477 |
6495 | 6478 |
6496 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6479 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6497 compiler->GenerateRuntimeCall(token_pos(), | 6480 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
6498 deopt_id(), | |
6499 kThrowRuntimeEntry, | |
6500 1, | |
6501 locs()); | 6481 locs()); |
6502 __ int3(); | 6482 __ int3(); |
6503 } | 6483 } |
6504 | 6484 |
6505 | 6485 |
6506 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 6486 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6507 bool opt) const { | 6487 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6508 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
6509 } | 6488 } |
6510 | 6489 |
6511 | 6490 |
6512 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6491 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6513 compiler->SetNeedsStacktrace(catch_try_index()); | 6492 compiler->SetNeedsStacktrace(catch_try_index()); |
6514 compiler->GenerateRuntimeCall(token_pos(), | 6493 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
6515 deopt_id(), | 6494 2, locs()); |
6516 kReThrowRuntimeEntry, | |
6517 2, | |
6518 locs()); | |
6519 __ int3(); | 6495 __ int3(); |
6520 } | 6496 } |
6521 | 6497 |
6522 | 6498 |
6523 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 6499 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6524 bool opt) const { | 6500 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6525 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
6526 } | 6501 } |
6527 | 6502 |
6528 | 6503 |
6529 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6504 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6530 __ Stop(message()); | 6505 __ Stop(message()); |
6531 } | 6506 } |
6532 | 6507 |
6533 | 6508 |
6534 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6509 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6535 if (!compiler->CanFallThroughTo(normal_entry())) { | 6510 if (!compiler->CanFallThroughTo(normal_entry())) { |
6536 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6511 __ jmp(compiler->GetJumpLabel(normal_entry())); |
6537 } | 6512 } |
6538 } | 6513 } |
6539 | 6514 |
6540 | 6515 |
6541 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 6516 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6542 bool opt) const { | 6517 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6543 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
6544 } | 6518 } |
6545 | 6519 |
6546 | 6520 |
6547 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6521 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6548 if (!compiler->is_optimizing()) { | 6522 if (!compiler->is_optimizing()) { |
6549 if (FLAG_reorder_basic_blocks) { | 6523 if (FLAG_reorder_basic_blocks) { |
6550 compiler->EmitEdgeCounter(block()->preorder_number()); | 6524 compiler->EmitEdgeCounter(block()->preorder_number()); |
6551 } | 6525 } |
6552 // Add a deoptimization descriptor for deoptimizing instructions that | 6526 // Add a deoptimization descriptor for deoptimizing instructions that |
6553 // may be inserted before this instruction. | 6527 // may be inserted before this instruction. |
6554 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6528 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
6555 GetDeoptId(), | |
6556 TokenPosition::kNoSource); | 6529 TokenPosition::kNoSource); |
6557 } | 6530 } |
6558 if (HasParallelMove()) { | 6531 if (HasParallelMove()) { |
6559 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6532 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
6560 } | 6533 } |
6561 | 6534 |
6562 // We can fall through if the successor is the next block in the list. | 6535 // We can fall through if the successor is the next block in the list. |
6563 // Otherwise, we need a jump. | 6536 // Otherwise, we need a jump. |
6564 if (!compiler->CanFallThroughTo(successor())) { | 6537 if (!compiler->CanFallThroughTo(successor())) { |
6565 __ jmp(compiler->GetJumpLabel(successor())); | 6538 __ jmp(compiler->GetJumpLabel(successor())); |
6566 } | 6539 } |
6567 } | 6540 } |
6568 | 6541 |
6569 | 6542 |
6570 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6543 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
6571 bool opt) const { | 6544 bool opt) const { |
6572 const intptr_t kNumInputs = 1; | 6545 const intptr_t kNumInputs = 1; |
6573 const intptr_t kNumTemps = 1; | 6546 const intptr_t kNumTemps = 1; |
6574 | 6547 |
6575 LocationSummary* summary = new(zone) LocationSummary( | 6548 LocationSummary* summary = new (zone) |
6576 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6549 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6577 | 6550 |
6578 summary->set_in(0, Location::RequiresRegister()); | 6551 summary->set_in(0, Location::RequiresRegister()); |
6579 summary->set_temp(0, Location::RequiresRegister()); | 6552 summary->set_temp(0, Location::RequiresRegister()); |
6580 | 6553 |
6581 return summary; | 6554 return summary; |
6582 } | 6555 } |
6583 | 6556 |
6584 | 6557 |
6585 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6558 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6586 Register offset_reg = locs()->in(0).reg(); | 6559 Register offset_reg = locs()->in(0).reg(); |
6587 Register target_address_reg = locs()->temp(0).reg(); | 6560 Register target_address_reg = locs()->temp(0).reg(); |
6588 | 6561 |
6589 { | 6562 { |
6590 const intptr_t kRIPRelativeLeaqSize = 7; | 6563 const intptr_t kRIPRelativeLeaqSize = 7; |
6591 const intptr_t entry_to_rip_offset = | 6564 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; |
6592 __ CodeSize() + kRIPRelativeLeaqSize; | |
6593 __ leaq(target_address_reg, | 6565 __ leaq(target_address_reg, |
6594 Address::AddressRIPRelative(-entry_to_rip_offset)); | 6566 Address::AddressRIPRelative(-entry_to_rip_offset)); |
6595 ASSERT(__ CodeSize() == entry_to_rip_offset); | 6567 ASSERT(__ CodeSize() == entry_to_rip_offset); |
6596 } | 6568 } |
6597 | 6569 |
6598 // Load from [current frame pointer] + kPcMarkerSlotFromFp. | 6570 // Load from [current frame pointer] + kPcMarkerSlotFromFp. |
6599 | 6571 |
6600 // Calculate the final absolute address. | 6572 // Calculate the final absolute address. |
6601 if (offset()->definition()->representation() == kTagged) { | 6573 if (offset()->definition()->representation() == kTagged) { |
6602 __ SmiUntag(offset_reg); | 6574 __ SmiUntag(offset_reg); |
6603 } | 6575 } |
6604 __ addq(target_address_reg, offset_reg); | 6576 __ addq(target_address_reg, offset_reg); |
6605 | 6577 |
6606 // Jump to the absolute address. | 6578 // Jump to the absolute address. |
6607 __ jmp(target_address_reg); | 6579 __ jmp(target_address_reg); |
6608 } | 6580 } |
6609 | 6581 |
6610 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 6582 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
6611 bool opt) const { | 6583 bool opt) const { |
6612 const intptr_t kNumInputs = 2; | 6584 const intptr_t kNumInputs = 2; |
6613 const intptr_t kNumTemps = 0; | 6585 const intptr_t kNumTemps = 0; |
6614 if (needs_number_check()) { | 6586 if (needs_number_check()) { |
6615 LocationSummary* locs = new(zone) LocationSummary( | 6587 LocationSummary* locs = new (zone) |
6616 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6588 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6617 locs->set_in(0, Location::RegisterLocation(RAX)); | 6589 locs->set_in(0, Location::RegisterLocation(RAX)); |
6618 locs->set_in(1, Location::RegisterLocation(RCX)); | 6590 locs->set_in(1, Location::RegisterLocation(RCX)); |
6619 locs->set_out(0, Location::RegisterLocation(RAX)); | 6591 locs->set_out(0, Location::RegisterLocation(RAX)); |
6620 return locs; | 6592 return locs; |
6621 } | 6593 } |
6622 LocationSummary* locs = new(zone) LocationSummary( | 6594 LocationSummary* locs = new (zone) |
6623 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6595 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6624 locs->set_in(0, Location::RegisterOrConstant(left())); | 6596 locs->set_in(0, Location::RegisterOrConstant(left())); |
6625 // Only one of the inputs can be a constant. Choose register if the first one | 6597 // Only one of the inputs can be a constant. Choose register if the first one |
6626 // is a constant. | 6598 // is a constant. |
6627 locs->set_in(1, locs->in(0).IsConstant() | 6599 locs->set_in(1, locs->in(0).IsConstant() |
6628 ? Location::RequiresRegister() | 6600 ? Location::RequiresRegister() |
6629 : Location::RegisterOrConstant(right())); | 6601 : Location::RegisterOrConstant(right())); |
6630 locs->set_out(0, Location::RequiresRegister()); | 6602 locs->set_out(0, Location::RequiresRegister()); |
6631 return locs; | 6603 return locs; |
6632 } | 6604 } |
6633 | 6605 |
6634 | 6606 |
6635 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6607 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
6636 BranchLabels labels) { | 6608 BranchLabels labels) { |
6637 Location left = locs()->in(0); | 6609 Location left = locs()->in(0); |
6638 Location right = locs()->in(1); | 6610 Location right = locs()->in(1); |
6639 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6611 ASSERT(!left.IsConstant() || !right.IsConstant()); |
6640 Condition true_condition; | 6612 Condition true_condition; |
6641 if (left.IsConstant()) { | 6613 if (left.IsConstant()) { |
6642 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 6614 true_condition = compiler->EmitEqualityRegConstCompare( |
6643 left.constant(), | 6615 right.reg(), left.constant(), needs_number_check(), token_pos()); |
6644 needs_number_check(), | |
6645 token_pos()); | |
6646 } else if (right.IsConstant()) { | 6616 } else if (right.IsConstant()) { |
6647 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 6617 true_condition = compiler->EmitEqualityRegConstCompare( |
6648 right.constant(), | 6618 left.reg(), right.constant(), needs_number_check(), token_pos()); |
6649 needs_number_check(), | |
6650 token_pos()); | |
6651 } else { | 6619 } else { |
6652 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 6620 true_condition = compiler->EmitEqualityRegRegCompare( |
6653 right.reg(), | 6621 left.reg(), right.reg(), needs_number_check(), token_pos()); |
6654 needs_number_check(), | |
6655 token_pos()); | |
6656 } | 6622 } |
6657 if (kind() != Token::kEQ_STRICT) { | 6623 if (kind() != Token::kEQ_STRICT) { |
6658 ASSERT(kind() == Token::kNE_STRICT); | 6624 ASSERT(kind() == Token::kNE_STRICT); |
6659 true_condition = NegateCondition(true_condition); | 6625 true_condition = NegateCondition(true_condition); |
6660 } | 6626 } |
6661 return true_condition; | 6627 return true_condition; |
6662 } | 6628 } |
6663 | 6629 |
6664 | 6630 |
6665 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6631 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6666 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6632 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
6667 | 6633 |
6668 Label is_true, is_false; | 6634 Label is_true, is_false; |
6669 BranchLabels labels = { &is_true, &is_false, &is_false }; | 6635 BranchLabels labels = {&is_true, &is_false, &is_false}; |
6670 | 6636 |
6671 Condition true_condition = EmitComparisonCode(compiler, labels); | 6637 Condition true_condition = EmitComparisonCode(compiler, labels); |
6672 EmitBranchOnCondition(compiler, true_condition, labels); | 6638 EmitBranchOnCondition(compiler, true_condition, labels); |
6673 | 6639 |
6674 Register result = locs()->out(0).reg(); | 6640 Register result = locs()->out(0).reg(); |
6675 Label done; | 6641 Label done; |
6676 __ Bind(&is_false); | 6642 __ Bind(&is_false); |
6677 __ LoadObject(result, Bool::False()); | 6643 __ LoadObject(result, Bool::False()); |
6678 __ jmp(&done); | 6644 __ jmp(&done); |
6679 __ Bind(&is_true); | 6645 __ Bind(&is_true); |
6680 __ LoadObject(result, Bool::True()); | 6646 __ LoadObject(result, Bool::True()); |
6681 __ Bind(&done); | 6647 __ Bind(&done); |
6682 } | 6648 } |
6683 | 6649 |
6684 | 6650 |
6685 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 6651 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
6686 BranchInstr* branch) { | 6652 BranchInstr* branch) { |
6687 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6653 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
6688 | 6654 |
6689 BranchLabels labels = compiler->CreateBranchLabels(branch); | 6655 BranchLabels labels = compiler->CreateBranchLabels(branch); |
6690 Condition true_condition = EmitComparisonCode(compiler, labels); | 6656 Condition true_condition = EmitComparisonCode(compiler, labels); |
6691 EmitBranchOnCondition(compiler, true_condition, labels); | 6657 EmitBranchOnCondition(compiler, true_condition, labels); |
6692 } | 6658 } |
6693 | 6659 |
6694 | 6660 |
6695 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6661 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
6696 bool opt) const { | 6662 bool opt) const { |
6697 const intptr_t kNumInputs = 1; | 6663 const intptr_t kNumInputs = 1; |
6698 const intptr_t kNumTemps = 0; | 6664 const intptr_t kNumTemps = 0; |
6699 LocationSummary* summary = new(zone) LocationSummary( | 6665 LocationSummary* summary = new (zone) |
6700 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6701 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. | 6667 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. |
6702 summary->set_out(0, Location::RegisterLocation(RAX)); | 6668 summary->set_out(0, Location::RegisterLocation(RAX)); |
6703 return summary; | 6669 return summary; |
6704 } | 6670 } |
6705 | 6671 |
6706 | 6672 |
6707 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6673 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6708 // Arguments descriptor is expected in R10. | 6674 // Arguments descriptor is expected in R10. |
6709 intptr_t argument_count = ArgumentCount(); | 6675 intptr_t argument_count = ArgumentCount(); |
6710 const Array& arguments_descriptor = | 6676 const Array& arguments_descriptor = Array::ZoneHandle( |
6711 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 6677 ArgumentsDescriptor::New(argument_count, argument_names())); |
6712 argument_names())); | |
6713 __ LoadObject(R10, arguments_descriptor); | 6678 __ LoadObject(R10, arguments_descriptor); |
6714 | 6679 |
6715 // Function in RAX. | 6680 // Function in RAX. |
6716 ASSERT(locs()->in(0).reg() == RAX); | 6681 ASSERT(locs()->in(0).reg() == RAX); |
6717 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 6682 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
6718 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 6683 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
6719 | 6684 |
6720 // RAX: Function. | 6685 // RAX: Function. |
6721 // R10: Arguments descriptor array. | 6686 // R10: Arguments descriptor array. |
6722 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 6687 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
6723 __ xorq(RBX, RBX); | 6688 __ xorq(RBX, RBX); |
6724 __ call(RCX); | 6689 __ call(RCX); |
6725 compiler->RecordSafepoint(locs()); | 6690 compiler->RecordSafepoint(locs()); |
6726 // Marks either the continuation point in unoptimized code or the | 6691 // Marks either the continuation point in unoptimized code or the |
6727 // deoptimization point in optimized code, after call. | 6692 // deoptimization point in optimized code, after call. |
6728 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 6693 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
6729 if (compiler->is_optimizing()) { | 6694 if (compiler->is_optimizing()) { |
6730 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6695 compiler->AddDeoptIndexAtCall(deopt_id_after); |
6731 } | 6696 } |
6732 // Add deoptimization continuation point after the call and before the | 6697 // Add deoptimization continuation point after the call and before the |
6733 // arguments are removed. | 6698 // arguments are removed. |
6734 // In optimized code this descriptor is needed for exception handling. | 6699 // In optimized code this descriptor is needed for exception handling. |
6735 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6700 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
6736 deopt_id_after, | |
6737 token_pos()); | 6701 token_pos()); |
6738 __ Drop(argument_count); | 6702 __ Drop(argument_count); |
6739 } | 6703 } |
6740 | 6704 |
6741 | 6705 |
6742 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6706 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
6743 bool opt) const { | 6707 bool opt) const { |
6744 return LocationSummary::Make(zone, | 6708 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
6745 1, | |
6746 Location::RequiresRegister(), | |
6747 LocationSummary::kNoCall); | 6709 LocationSummary::kNoCall); |
6748 } | 6710 } |
6749 | 6711 |
6750 | 6712 |
6751 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6713 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6752 Register value = locs()->in(0).reg(); | 6714 Register value = locs()->in(0).reg(); |
6753 Register result = locs()->out(0).reg(); | 6715 Register result = locs()->out(0).reg(); |
6754 | 6716 |
6755 Label done; | 6717 Label done; |
6756 __ LoadObject(result, Bool::True()); | 6718 __ LoadObject(result, Bool::True()); |
6757 __ CompareRegisters(result, value); | 6719 __ CompareRegisters(result, value); |
6758 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6720 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
6759 __ LoadObject(result, Bool::False()); | 6721 __ LoadObject(result, Bool::False()); |
6760 __ Bind(&done); | 6722 __ Bind(&done); |
6761 } | 6723 } |
6762 | 6724 |
6763 | 6725 |
6764 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6726 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
6765 bool opt) const { | 6727 bool opt) const { |
6766 return MakeCallSummary(zone); | 6728 return MakeCallSummary(zone); |
6767 } | 6729 } |
6768 | 6730 |
6769 | 6731 |
6770 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6732 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6771 const Code& stub = Code::ZoneHandle( | 6733 const Code& stub = Code::ZoneHandle( |
6772 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6734 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
6773 const StubEntry stub_entry(stub); | 6735 const StubEntry stub_entry(stub); |
6774 compiler->GenerateCall(token_pos(), | 6736 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
6775 stub_entry, | |
6776 RawPcDescriptors::kOther, | |
6777 locs()); | 6737 locs()); |
6778 compiler->AddStubCallTarget(stub); | 6738 compiler->AddStubCallTarget(stub); |
6779 __ Drop(ArgumentCount()); // Discard arguments. | 6739 __ Drop(ArgumentCount()); // Discard arguments. |
6780 } | 6740 } |
6781 | 6741 |
6782 | 6742 |
6783 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6743 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6784 ASSERT(!compiler->is_optimizing()); | 6744 ASSERT(!compiler->is_optimizing()); |
6785 __ CallPatchable(*StubCode::DebugStepCheck_entry()); | 6745 __ CallPatchable(*StubCode::DebugStepCheck_entry()); |
6786 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 6746 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
6787 compiler->RecordSafepoint(locs()); | 6747 compiler->RecordSafepoint(locs()); |
6788 } | 6748 } |
6789 | 6749 |
6790 | 6750 |
6791 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 6751 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
6792 Zone* zone, bool opt) const { | 6752 bool opt) const { |
6793 const intptr_t kNumInputs = 1; | 6753 const intptr_t kNumInputs = 1; |
6794 const intptr_t kNumTemps = 0; | 6754 const intptr_t kNumTemps = 0; |
6795 LocationSummary* locs = new(zone) LocationSummary( | 6755 LocationSummary* locs = new (zone) |
6796 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6797 locs->set_in(0, Location::RegisterLocation(RAX)); | 6757 locs->set_in(0, Location::RegisterLocation(RAX)); |
6798 locs->set_out(0, Location::RegisterLocation(RAX)); | 6758 locs->set_out(0, Location::RegisterLocation(RAX)); |
6799 return locs; | 6759 return locs; |
6800 } | 6760 } |
6801 | 6761 |
6802 | 6762 |
6803 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6763 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6804 const Register typed_data = locs()->in(0).reg(); | 6764 const Register typed_data = locs()->in(0).reg(); |
6805 const Register result = locs()->out(0).reg(); | 6765 const Register result = locs()->out(0).reg(); |
6806 __ PushObject(Object::null_object()); | 6766 __ PushObject(Object::null_object()); |
6807 __ pushq(typed_data); | 6767 __ pushq(typed_data); |
6808 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 6768 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6809 deopt_id(), | 6769 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6810 kGrowRegExpStackRuntimeEntry, | |
6811 1, | |
6812 locs()); | |
6813 __ Drop(1); | 6770 __ Drop(1); |
6814 __ popq(result); | 6771 __ popq(result); |
6815 } | 6772 } |
6816 | 6773 |
6817 | 6774 |
6818 } // namespace dart | 6775 } // namespace dart |
6819 | 6776 |
6820 #undef __ | 6777 #undef __ |
6821 | 6778 |
6822 #endif // defined TARGET_ARCH_X64 | 6779 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |