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 16 matching lines...) Expand all Loading... |
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 = | 31 LocationSummary* result = |
32 new (zone) LocationSummary(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 | |
38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 37 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
39 bool opt) const { | 38 bool opt) const { |
40 const intptr_t kNumInputs = 1; | 39 const intptr_t kNumInputs = 1; |
41 const intptr_t kNumTemps = 0; | 40 const intptr_t kNumTemps = 0; |
42 LocationSummary* locs = new (zone) | 41 LocationSummary* locs = new (zone) |
43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 42 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
44 locs->set_in(0, Location::AnyOrConstant(value())); | 43 locs->set_in(0, Location::AnyOrConstant(value())); |
45 return locs; | 44 return locs; |
46 } | 45 } |
47 | 46 |
48 | |
49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 47 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 48 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
51 // where PushArgument is handled by BindInstr::EmitNativeCode. | 49 // where PushArgument is handled by BindInstr::EmitNativeCode. |
52 if (compiler->is_optimizing()) { | 50 if (compiler->is_optimizing()) { |
53 Location value = locs()->in(0); | 51 Location value = locs()->in(0); |
54 if (value.IsRegister()) { | 52 if (value.IsRegister()) { |
55 __ pushq(value.reg()); | 53 __ pushq(value.reg()); |
56 } else if (value.IsConstant()) { | 54 } else if (value.IsConstant()) { |
57 __ PushObject(value.constant()); | 55 __ PushObject(value.constant()); |
58 } else { | 56 } else { |
59 ASSERT(value.IsStackSlot()); | 57 ASSERT(value.IsStackSlot()); |
60 __ pushq(value.ToStackSlotAddress()); | 58 __ pushq(value.ToStackSlotAddress()); |
61 } | 59 } |
62 } | 60 } |
63 } | 61 } |
64 | 62 |
65 | |
66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 63 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
67 const intptr_t kNumInputs = 1; | 64 const intptr_t kNumInputs = 1; |
68 const intptr_t kNumTemps = 0; | 65 const intptr_t kNumTemps = 0; |
69 LocationSummary* locs = new (zone) | 66 LocationSummary* locs = new (zone) |
70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 67 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
71 locs->set_in(0, Location::RegisterLocation(RAX)); | 68 locs->set_in(0, Location::RegisterLocation(RAX)); |
72 return locs; | 69 return locs; |
73 } | 70 } |
74 | 71 |
75 | |
76 // Attempt optimized compilation at return instruction instead of at the entry. | 72 // Attempt optimized compilation at return instruction instead of at the entry. |
77 // The entry needs to be patchable, no inlined objects are allowed in the area | 73 // The entry needs to be patchable, no inlined objects are allowed in the area |
78 // that will be overwritten by the patch instruction: a jump). | 74 // that will be overwritten by the patch instruction: a jump). |
79 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 75 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
80 Register result = locs()->in(0).reg(); | 76 Register result = locs()->in(0).reg(); |
81 ASSERT(result == RAX); | 77 ASSERT(result == RAX); |
82 | 78 |
83 if (compiler->intrinsic_mode()) { | 79 if (compiler->intrinsic_mode()) { |
84 // Intrinsics don't have a frame. | 80 // Intrinsics don't have a frame. |
85 __ ret(); | 81 __ ret(); |
(...skipping 14 matching lines...) Expand all Loading... |
100 __ Bind(&done); | 96 __ Bind(&done); |
101 #endif | 97 #endif |
102 ASSERT(__ constant_pool_allowed()); | 98 ASSERT(__ constant_pool_allowed()); |
103 __ LeaveDartFrame(); // Disallows constant pool use. | 99 __ LeaveDartFrame(); // Disallows constant pool use. |
104 __ ret(); | 100 __ ret(); |
105 // This ReturnInstr may be emitted out of order by the optimizer. The next | 101 // This ReturnInstr may be emitted out of order by the optimizer. The next |
106 // block may be a target expecting a properly set constant pool pointer. | 102 // block may be a target expecting a properly set constant pool pointer. |
107 __ set_constant_pool_allowed(true); | 103 __ set_constant_pool_allowed(true); |
108 } | 104 } |
109 | 105 |
110 | |
111 static Condition NegateCondition(Condition condition) { | 106 static Condition NegateCondition(Condition condition) { |
112 switch (condition) { | 107 switch (condition) { |
113 case EQUAL: | 108 case EQUAL: |
114 return NOT_EQUAL; | 109 return NOT_EQUAL; |
115 case NOT_EQUAL: | 110 case NOT_EQUAL: |
116 return EQUAL; | 111 return EQUAL; |
117 case LESS: | 112 case LESS: |
118 return GREATER_EQUAL; | 113 return GREATER_EQUAL; |
119 case LESS_EQUAL: | 114 case LESS_EQUAL: |
120 return GREATER; | 115 return GREATER; |
(...skipping 12 matching lines...) Expand all Loading... |
133 case PARITY_EVEN: | 128 case PARITY_EVEN: |
134 return PARITY_ODD; | 129 return PARITY_ODD; |
135 case PARITY_ODD: | 130 case PARITY_ODD: |
136 return PARITY_EVEN; | 131 return PARITY_EVEN; |
137 default: | 132 default: |
138 UNIMPLEMENTED(); | 133 UNIMPLEMENTED(); |
139 return EQUAL; | 134 return EQUAL; |
140 } | 135 } |
141 } | 136 } |
142 | 137 |
143 | |
144 // Detect pattern when one value is zero and another is a power of 2. | 138 // Detect pattern when one value is zero and another is a power of 2. |
145 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 139 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
146 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 140 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
147 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 141 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
148 } | 142 } |
149 | 143 |
150 | |
151 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 144 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
152 bool opt) const { | 145 bool opt) const { |
153 comparison()->InitializeLocationSummary(zone, opt); | 146 comparison()->InitializeLocationSummary(zone, opt); |
154 // TODO(vegorov): support byte register constraints in the register allocator. | 147 // TODO(vegorov): support byte register constraints in the register allocator. |
155 comparison()->locs()->set_out(0, Location::RegisterLocation(RDX)); | 148 comparison()->locs()->set_out(0, Location::RegisterLocation(RDX)); |
156 return comparison()->locs(); | 149 return comparison()->locs(); |
157 } | 150 } |
158 | 151 |
159 | |
160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 152 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
161 ASSERT(locs()->out(0).reg() == RDX); | 153 ASSERT(locs()->out(0).reg() == RDX); |
162 | 154 |
163 // Clear upper part of the out register. We are going to use setcc on it | 155 // Clear upper part of the out register. We are going to use setcc on it |
164 // which is a byte move. | 156 // which is a byte move. |
165 __ xorq(RDX, RDX); | 157 __ xorq(RDX, RDX); |
166 | 158 |
167 // Emit comparison code. This must not overwrite the result register. | 159 // Emit comparison code. This must not overwrite the result register. |
168 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | 160 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
169 // the labels or returning an invalid condition. | 161 // the labels or returning an invalid condition. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } else { | 193 } else { |
202 __ decq(RDX); | 194 __ decq(RDX); |
203 __ AndImmediate( | 195 __ AndImmediate( |
204 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 196 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
205 if (false_value != 0) { | 197 if (false_value != 0) { |
206 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); | 198 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); |
207 } | 199 } |
208 } | 200 } |
209 } | 201 } |
210 | 202 |
211 | |
212 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 203 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
213 bool opt) const { | 204 bool opt) const { |
214 const intptr_t kNumInputs = 0; | 205 const intptr_t kNumInputs = 0; |
215 const intptr_t stack_index = (local().index() < 0) | 206 const intptr_t stack_index = (local().index() < 0) |
216 ? kFirstLocalSlotFromFp - local().index() | 207 ? kFirstLocalSlotFromFp - local().index() |
217 : kParamEndSlotFromFp - local().index(); | 208 : kParamEndSlotFromFp - local().index(); |
218 return LocationSummary::Make(zone, kNumInputs, | 209 return LocationSummary::Make(zone, kNumInputs, |
219 Location::StackSlot(stack_index), | 210 Location::StackSlot(stack_index), |
220 LocationSummary::kNoCall); | 211 LocationSummary::kNoCall); |
221 } | 212 } |
222 | 213 |
223 | |
224 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 214 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
225 ASSERT(!compiler->is_optimizing()); | 215 ASSERT(!compiler->is_optimizing()); |
226 // Nothing to do. | 216 // Nothing to do. |
227 } | 217 } |
228 | 218 |
229 | |
230 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 219 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
231 bool opt) const { | 220 bool opt) const { |
232 const intptr_t kNumInputs = 1; | 221 const intptr_t kNumInputs = 1; |
233 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 222 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
234 LocationSummary::kNoCall); | 223 LocationSummary::kNoCall); |
235 } | 224 } |
236 | 225 |
237 | |
238 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 226 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
239 Register value = locs()->in(0).reg(); | 227 Register value = locs()->in(0).reg(); |
240 Register result = locs()->out(0).reg(); | 228 Register result = locs()->out(0).reg(); |
241 ASSERT(result == value); // Assert that register assignment is correct. | 229 ASSERT(result == value); // Assert that register assignment is correct. |
242 __ movq(Address(RBP, local().index() * kWordSize), value); | 230 __ movq(Address(RBP, local().index() * kWordSize), value); |
243 } | 231 } |
244 | 232 |
245 | |
246 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 233 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
247 bool opt) const { | 234 bool opt) const { |
248 const intptr_t kNumInputs = 0; | 235 const intptr_t kNumInputs = 0; |
249 return LocationSummary::Make(zone, kNumInputs, | 236 return LocationSummary::Make(zone, kNumInputs, |
250 Assembler::IsSafe(value()) | 237 Assembler::IsSafe(value()) |
251 ? Location::Constant(this) | 238 ? Location::Constant(this) |
252 : Location::RequiresRegister(), | 239 : Location::RequiresRegister(), |
253 LocationSummary::kNoCall); | 240 LocationSummary::kNoCall); |
254 } | 241 } |
255 | 242 |
256 | |
257 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 243 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
258 // The register allocator drops constant definitions that have no uses. | 244 // The register allocator drops constant definitions that have no uses. |
259 Location out = locs()->out(0); | 245 Location out = locs()->out(0); |
260 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 246 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
261 if (out.IsRegister()) { | 247 if (out.IsRegister()) { |
262 Register result = out.reg(); | 248 Register result = out.reg(); |
263 __ LoadObject(result, value()); | 249 __ LoadObject(result, value()); |
264 } | 250 } |
265 } | 251 } |
266 | 252 |
267 | |
268 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 253 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
269 bool opt) const { | 254 bool opt) const { |
270 const intptr_t kNumInputs = 0; | 255 const intptr_t kNumInputs = 0; |
271 const intptr_t kNumTemps = 0; | 256 const intptr_t kNumTemps = 0; |
272 LocationSummary* locs = new (zone) | 257 LocationSummary* locs = new (zone) |
273 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
274 switch (representation()) { | 259 switch (representation()) { |
275 case kUnboxedDouble: | 260 case kUnboxedDouble: |
276 locs->set_out(0, Location::RequiresFpuRegister()); | 261 locs->set_out(0, Location::RequiresFpuRegister()); |
277 break; | 262 break; |
278 case kUnboxedInt32: | 263 case kUnboxedInt32: |
279 locs->set_out(0, Location::RequiresRegister()); | 264 locs->set_out(0, Location::RequiresRegister()); |
280 break; | 265 break; |
281 default: | 266 default: |
282 UNREACHABLE(); | 267 UNREACHABLE(); |
283 break; | 268 break; |
284 } | 269 } |
285 return locs; | 270 return locs; |
286 } | 271 } |
287 | 272 |
288 | |
289 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 273 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
290 // The register allocator drops constant definitions that have no uses. | 274 // The register allocator drops constant definitions that have no uses. |
291 if (!locs()->out(0).IsInvalid()) { | 275 if (!locs()->out(0).IsInvalid()) { |
292 switch (representation()) { | 276 switch (representation()) { |
293 case kUnboxedDouble: { | 277 case kUnboxedDouble: { |
294 XmmRegister result = locs()->out(0).fpu_reg(); | 278 XmmRegister result = locs()->out(0).fpu_reg(); |
295 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 279 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
296 __ xorps(result, result); | 280 __ xorps(result, result); |
297 } else { | 281 } else { |
298 __ LoadObject(TMP, value()); | 282 __ LoadObject(TMP, value()); |
299 __ movsd(result, FieldAddress(TMP, Double::value_offset())); | 283 __ movsd(result, FieldAddress(TMP, Double::value_offset())); |
300 } | 284 } |
301 break; | 285 break; |
302 } | 286 } |
303 case kUnboxedInt32: | 287 case kUnboxedInt32: |
304 __ movl(locs()->out(0).reg(), | 288 __ movl(locs()->out(0).reg(), |
305 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); | 289 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); |
306 break; | 290 break; |
307 default: | 291 default: |
308 UNREACHABLE(); | 292 UNREACHABLE(); |
309 } | 293 } |
310 } | 294 } |
311 } | 295 } |
312 | 296 |
313 | |
314 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 297 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
315 bool opt) const { | 298 bool opt) const { |
316 const intptr_t kNumInputs = 3; | 299 const intptr_t kNumInputs = 3; |
317 const intptr_t kNumTemps = 0; | 300 const intptr_t kNumTemps = 0; |
318 LocationSummary* summary = new (zone) | 301 LocationSummary* summary = new (zone) |
319 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 302 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
320 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 303 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
321 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. | 304 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
322 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. | 305 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
323 summary->set_out(0, Location::RegisterLocation(RAX)); | 306 summary->set_out(0, Location::RegisterLocation(RAX)); |
324 return summary; | 307 return summary; |
325 } | 308 } |
326 | 309 |
327 | |
328 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 310 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
329 bool opt) const { | 311 bool opt) const { |
330 const intptr_t kNumInputs = 1; | 312 const intptr_t kNumInputs = 1; |
331 const intptr_t kNumTemps = 0; | 313 const intptr_t kNumTemps = 0; |
332 LocationSummary* locs = new (zone) | 314 LocationSummary* locs = new (zone) |
333 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 315 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
334 locs->set_in(0, Location::RegisterLocation(RAX)); | 316 locs->set_in(0, Location::RegisterLocation(RAX)); |
335 locs->set_out(0, Location::RegisterLocation(RAX)); | 317 locs->set_out(0, Location::RegisterLocation(RAX)); |
336 return locs; | 318 return locs; |
337 } | 319 } |
338 | 320 |
339 | |
340 static void EmitAssertBoolean(Register reg, | 321 static void EmitAssertBoolean(Register reg, |
341 TokenPosition token_pos, | 322 TokenPosition token_pos, |
342 intptr_t deopt_id, | 323 intptr_t deopt_id, |
343 LocationSummary* locs, | 324 LocationSummary* locs, |
344 FlowGraphCompiler* compiler) { | 325 FlowGraphCompiler* compiler) { |
345 // Check that the type of the value is allowed in conditional context. | 326 // Check that the type of the value is allowed in conditional context. |
346 // Call the runtime if the object is not bool::true or bool::false. | 327 // Call the runtime if the object is not bool::true or bool::false. |
347 ASSERT(locs->always_calls()); | 328 ASSERT(locs->always_calls()); |
348 Label done; | 329 Label done; |
349 | 330 |
350 if (Isolate::Current()->type_checks()) { | 331 if (Isolate::Current()->type_checks()) { |
351 __ CompareObject(reg, Bool::True()); | 332 __ CompareObject(reg, Bool::True()); |
352 __ j(EQUAL, &done, Assembler::kNearJump); | 333 __ j(EQUAL, &done, Assembler::kNearJump); |
353 __ CompareObject(reg, Bool::False()); | 334 __ CompareObject(reg, Bool::False()); |
354 __ j(EQUAL, &done, Assembler::kNearJump); | 335 __ j(EQUAL, &done, Assembler::kNearJump); |
355 } else { | 336 } else { |
356 ASSERT(Isolate::Current()->asserts()); | 337 ASSERT(Isolate::Current()->asserts()); |
357 __ CompareObject(reg, Object::null_instance()); | 338 __ CompareObject(reg, Object::null_instance()); |
358 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 339 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
359 } | 340 } |
360 | 341 |
361 __ pushq(reg); // Push the source object. | 342 __ pushq(reg); // Push the source object. |
362 compiler->GenerateRuntimeCall(token_pos, deopt_id, | 343 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
363 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 344 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
364 // We should never return here. | 345 // We should never return here. |
365 __ int3(); | 346 __ int3(); |
366 __ Bind(&done); | 347 __ Bind(&done); |
367 } | 348 } |
368 | 349 |
369 | |
370 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 350 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
371 Register obj = locs()->in(0).reg(); | 351 Register obj = locs()->in(0).reg(); |
372 Register result = locs()->out(0).reg(); | 352 Register result = locs()->out(0).reg(); |
373 | 353 |
374 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 354 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
375 ASSERT(obj == result); | 355 ASSERT(obj == result); |
376 } | 356 } |
377 | 357 |
378 | |
379 static Condition TokenKindToIntCondition(Token::Kind kind) { | 358 static Condition TokenKindToIntCondition(Token::Kind kind) { |
380 switch (kind) { | 359 switch (kind) { |
381 case Token::kEQ: | 360 case Token::kEQ: |
382 return EQUAL; | 361 return EQUAL; |
383 case Token::kNE: | 362 case Token::kNE: |
384 return NOT_EQUAL; | 363 return NOT_EQUAL; |
385 case Token::kLT: | 364 case Token::kLT: |
386 return LESS; | 365 return LESS; |
387 case Token::kGT: | 366 case Token::kGT: |
388 return GREATER; | 367 return GREATER; |
389 case Token::kLTE: | 368 case Token::kLTE: |
390 return LESS_EQUAL; | 369 return LESS_EQUAL; |
391 case Token::kGTE: | 370 case Token::kGTE: |
392 return GREATER_EQUAL; | 371 return GREATER_EQUAL; |
393 default: | 372 default: |
394 UNREACHABLE(); | 373 UNREACHABLE(); |
395 return OVERFLOW; | 374 return OVERFLOW; |
396 } | 375 } |
397 } | 376 } |
398 | 377 |
399 | |
400 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 378 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
401 bool opt) const { | 379 bool opt) const { |
402 const intptr_t kNumInputs = 2; | 380 const intptr_t kNumInputs = 2; |
403 if (operation_cid() == kMintCid) { | 381 if (operation_cid() == kMintCid) { |
404 const intptr_t kNumTemps = 0; | 382 const intptr_t kNumTemps = 0; |
405 LocationSummary* locs = new (zone) | 383 LocationSummary* locs = new (zone) |
406 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 384 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
407 locs->set_in(0, Location::RequiresRegister()); | 385 locs->set_in(0, Location::RequiresRegister()); |
408 locs->set_in(1, Location::RequiresRegister()); | 386 locs->set_in(1, Location::RequiresRegister()); |
409 locs->set_out(0, Location::RequiresRegister()); | 387 locs->set_out(0, Location::RequiresRegister()); |
(...skipping 19 matching lines...) Expand all Loading... |
429 locs->set_in(1, locs->in(0).IsConstant() | 407 locs->set_in(1, locs->in(0).IsConstant() |
430 ? Location::RequiresRegister() | 408 ? Location::RequiresRegister() |
431 : Location::RegisterOrConstant(right())); | 409 : Location::RegisterOrConstant(right())); |
432 locs->set_out(0, Location::RequiresRegister()); | 410 locs->set_out(0, Location::RequiresRegister()); |
433 return locs; | 411 return locs; |
434 } | 412 } |
435 UNREACHABLE(); | 413 UNREACHABLE(); |
436 return NULL; | 414 return NULL; |
437 } | 415 } |
438 | 416 |
439 | |
440 static void LoadValueCid(FlowGraphCompiler* compiler, | 417 static void LoadValueCid(FlowGraphCompiler* compiler, |
441 Register value_cid_reg, | 418 Register value_cid_reg, |
442 Register value_reg, | 419 Register value_reg, |
443 Label* value_is_smi = NULL) { | 420 Label* value_is_smi = NULL) { |
444 Label done; | 421 Label done; |
445 if (value_is_smi == NULL) { | 422 if (value_is_smi == NULL) { |
446 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid)); | 423 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid)); |
447 } | 424 } |
448 __ testq(value_reg, Immediate(kSmiTagMask)); | 425 __ testq(value_reg, Immediate(kSmiTagMask)); |
449 if (value_is_smi == NULL) { | 426 if (value_is_smi == NULL) { |
450 __ j(ZERO, &done, Assembler::kNearJump); | 427 __ j(ZERO, &done, Assembler::kNearJump); |
451 } else { | 428 } else { |
452 __ j(ZERO, value_is_smi); | 429 __ j(ZERO, value_is_smi); |
453 } | 430 } |
454 __ LoadClassId(value_cid_reg, value_reg); | 431 __ LoadClassId(value_cid_reg, value_reg); |
455 __ Bind(&done); | 432 __ Bind(&done); |
456 } | 433 } |
457 | 434 |
458 | |
459 static Condition FlipCondition(Condition condition) { | 435 static Condition FlipCondition(Condition condition) { |
460 switch (condition) { | 436 switch (condition) { |
461 case EQUAL: | 437 case EQUAL: |
462 return EQUAL; | 438 return EQUAL; |
463 case NOT_EQUAL: | 439 case NOT_EQUAL: |
464 return NOT_EQUAL; | 440 return NOT_EQUAL; |
465 case LESS: | 441 case LESS: |
466 return GREATER; | 442 return GREATER; |
467 case LESS_EQUAL: | 443 case LESS_EQUAL: |
468 return GREATER_EQUAL; | 444 return GREATER_EQUAL; |
469 case GREATER: | 445 case GREATER: |
470 return LESS; | 446 return LESS; |
471 case GREATER_EQUAL: | 447 case GREATER_EQUAL: |
472 return LESS_EQUAL; | 448 return LESS_EQUAL; |
473 case BELOW: | 449 case BELOW: |
474 return ABOVE; | 450 return ABOVE; |
475 case BELOW_EQUAL: | 451 case BELOW_EQUAL: |
476 return ABOVE_EQUAL; | 452 return ABOVE_EQUAL; |
477 case ABOVE: | 453 case ABOVE: |
478 return BELOW; | 454 return BELOW; |
479 case ABOVE_EQUAL: | 455 case ABOVE_EQUAL: |
480 return BELOW_EQUAL; | 456 return BELOW_EQUAL; |
481 default: | 457 default: |
482 UNIMPLEMENTED(); | 458 UNIMPLEMENTED(); |
483 return EQUAL; | 459 return EQUAL; |
484 } | 460 } |
485 } | 461 } |
486 | 462 |
487 | |
488 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 463 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
489 Condition true_condition, | 464 Condition true_condition, |
490 BranchLabels labels) { | 465 BranchLabels labels) { |
491 if (labels.fall_through == labels.false_label) { | 466 if (labels.fall_through == labels.false_label) { |
492 // If the next block is the false successor, fall through to it. | 467 // If the next block is the false successor, fall through to it. |
493 __ j(true_condition, labels.true_label); | 468 __ j(true_condition, labels.true_label); |
494 } else { | 469 } else { |
495 // If the next block is not the false successor, branch to it. | 470 // If the next block is not the false successor, branch to it. |
496 Condition false_condition = NegateCondition(true_condition); | 471 Condition false_condition = NegateCondition(true_condition); |
497 __ j(false_condition, labels.false_label); | 472 __ j(false_condition, labels.false_label); |
498 | 473 |
499 // Fall through or jump to the true successor. | 474 // Fall through or jump to the true successor. |
500 if (labels.fall_through != labels.true_label) { | 475 if (labels.fall_through != labels.true_label) { |
501 __ jmp(labels.true_label); | 476 __ jmp(labels.true_label); |
502 } | 477 } |
503 } | 478 } |
504 } | 479 } |
505 | 480 |
506 | |
507 static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, | 481 static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, |
508 const LocationSummary& locs, | 482 const LocationSummary& locs, |
509 Token::Kind kind) { | 483 Token::Kind kind) { |
510 Location left = locs.in(0); | 484 Location left = locs.in(0); |
511 Location right = locs.in(1); | 485 Location right = locs.in(1); |
512 ASSERT(!left.IsConstant() || !right.IsConstant()); | 486 ASSERT(!left.IsConstant() || !right.IsConstant()); |
513 | 487 |
514 Condition true_condition = TokenKindToIntCondition(kind); | 488 Condition true_condition = TokenKindToIntCondition(kind); |
515 | 489 |
516 if (left.IsConstant()) { | 490 if (left.IsConstant()) { |
517 __ CompareObject(right.reg(), left.constant()); | 491 __ CompareObject(right.reg(), left.constant()); |
518 true_condition = FlipCondition(true_condition); | 492 true_condition = FlipCondition(true_condition); |
519 } else if (right.IsConstant()) { | 493 } else if (right.IsConstant()) { |
520 __ CompareObject(left.reg(), right.constant()); | 494 __ CompareObject(left.reg(), right.constant()); |
521 } else if (right.IsStackSlot()) { | 495 } else if (right.IsStackSlot()) { |
522 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 496 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
523 } else { | 497 } else { |
524 __ cmpq(left.reg(), right.reg()); | 498 __ cmpq(left.reg(), right.reg()); |
525 } | 499 } |
526 return true_condition; | 500 return true_condition; |
527 } | 501 } |
528 | 502 |
529 | |
530 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 503 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
531 switch (kind) { | 504 switch (kind) { |
532 case Token::kEQ: | 505 case Token::kEQ: |
533 return EQUAL; | 506 return EQUAL; |
534 case Token::kNE: | 507 case Token::kNE: |
535 return NOT_EQUAL; | 508 return NOT_EQUAL; |
536 case Token::kLT: | 509 case Token::kLT: |
537 return BELOW; | 510 return BELOW; |
538 case Token::kGT: | 511 case Token::kGT: |
539 return ABOVE; | 512 return ABOVE; |
540 case Token::kLTE: | 513 case Token::kLTE: |
541 return BELOW_EQUAL; | 514 return BELOW_EQUAL; |
542 case Token::kGTE: | 515 case Token::kGTE: |
543 return ABOVE_EQUAL; | 516 return ABOVE_EQUAL; |
544 default: | 517 default: |
545 UNREACHABLE(); | 518 UNREACHABLE(); |
546 return OVERFLOW; | 519 return OVERFLOW; |
547 } | 520 } |
548 } | 521 } |
549 | 522 |
550 | |
551 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 523 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
552 const LocationSummary& locs, | 524 const LocationSummary& locs, |
553 Token::Kind kind, | 525 Token::Kind kind, |
554 BranchLabels labels) { | 526 BranchLabels labels) { |
555 XmmRegister left = locs.in(0).fpu_reg(); | 527 XmmRegister left = locs.in(0).fpu_reg(); |
556 XmmRegister right = locs.in(1).fpu_reg(); | 528 XmmRegister right = locs.in(1).fpu_reg(); |
557 | 529 |
558 __ comisd(left, right); | 530 __ comisd(left, right); |
559 | 531 |
560 Condition true_condition = TokenKindToDoubleCondition(kind); | 532 Condition true_condition = TokenKindToDoubleCondition(kind); |
561 Label* nan_result = | 533 Label* nan_result = |
562 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; | 534 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
563 __ j(PARITY_EVEN, nan_result); | 535 __ j(PARITY_EVEN, nan_result); |
564 return true_condition; | 536 return true_condition; |
565 } | 537 } |
566 | 538 |
567 | |
568 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 539 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
569 BranchLabels labels) { | 540 BranchLabels labels) { |
570 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 541 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
571 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 542 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
572 } else { | 543 } else { |
573 ASSERT(operation_cid() == kDoubleCid); | 544 ASSERT(operation_cid() == kDoubleCid); |
574 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 545 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
575 } | 546 } |
576 } | 547 } |
577 | 548 |
578 | |
579 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 549 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
580 Label is_true, is_false; | 550 Label is_true, is_false; |
581 BranchLabels labels = {&is_true, &is_false, &is_false}; | 551 BranchLabels labels = {&is_true, &is_false, &is_false}; |
582 Condition true_condition = EmitComparisonCode(compiler, labels); | 552 Condition true_condition = EmitComparisonCode(compiler, labels); |
583 if (true_condition != INVALID_CONDITION) { | 553 if (true_condition != INVALID_CONDITION) { |
584 EmitBranchOnCondition(compiler, true_condition, labels); | 554 EmitBranchOnCondition(compiler, true_condition, labels); |
585 } | 555 } |
586 | 556 |
587 Register result = locs()->out(0).reg(); | 557 Register result = locs()->out(0).reg(); |
588 Label done; | 558 Label done; |
589 __ Bind(&is_false); | 559 __ Bind(&is_false); |
590 __ LoadObject(result, Bool::False()); | 560 __ LoadObject(result, Bool::False()); |
591 __ jmp(&done); | 561 __ jmp(&done); |
592 __ Bind(&is_true); | 562 __ Bind(&is_true); |
593 __ LoadObject(result, Bool::True()); | 563 __ LoadObject(result, Bool::True()); |
594 __ Bind(&done); | 564 __ Bind(&done); |
595 } | 565 } |
596 | 566 |
597 | |
598 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 567 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
599 BranchInstr* branch) { | 568 BranchInstr* branch) { |
600 BranchLabels labels = compiler->CreateBranchLabels(branch); | 569 BranchLabels labels = compiler->CreateBranchLabels(branch); |
601 Condition true_condition = EmitComparisonCode(compiler, labels); | 570 Condition true_condition = EmitComparisonCode(compiler, labels); |
602 if (true_condition != INVALID_CONDITION) { | 571 if (true_condition != INVALID_CONDITION) { |
603 EmitBranchOnCondition(compiler, true_condition, labels); | 572 EmitBranchOnCondition(compiler, true_condition, labels); |
604 } | 573 } |
605 } | 574 } |
606 | 575 |
607 | |
608 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 576 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
609 const intptr_t kNumInputs = 2; | 577 const intptr_t kNumInputs = 2; |
610 const intptr_t kNumTemps = 0; | 578 const intptr_t kNumTemps = 0; |
611 LocationSummary* locs = new (zone) | 579 LocationSummary* locs = new (zone) |
612 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 580 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
613 locs->set_in(0, Location::RequiresRegister()); | 581 locs->set_in(0, Location::RequiresRegister()); |
614 // Only one input can be a constant operand. The case of two constant | 582 // Only one input can be a constant operand. The case of two constant |
615 // operands should be handled by constant propagation. | 583 // operands should be handled by constant propagation. |
616 locs->set_in(1, Location::RegisterOrConstant(right())); | 584 locs->set_in(1, Location::RegisterOrConstant(right())); |
617 return locs; | 585 return locs; |
618 } | 586 } |
619 | 587 |
620 | |
621 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 588 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
622 BranchLabels labels) { | 589 BranchLabels labels) { |
623 Register left_reg = locs()->in(0).reg(); | 590 Register left_reg = locs()->in(0).reg(); |
624 Location right = locs()->in(1); | 591 Location right = locs()->in(1); |
625 if (right.IsConstant()) { | 592 if (right.IsConstant()) { |
626 ASSERT(right.constant().IsSmi()); | 593 ASSERT(right.constant().IsSmi()); |
627 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 594 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
628 __ TestImmediate(left_reg, Immediate(imm)); | 595 __ TestImmediate(left_reg, Immediate(imm)); |
629 } else { | 596 } else { |
630 __ testq(left_reg, right.reg()); | 597 __ testq(left_reg, right.reg()); |
631 } | 598 } |
632 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 599 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
633 return true_condition; | 600 return true_condition; |
634 } | 601 } |
635 | 602 |
636 | |
637 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 603 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
638 bool opt) const { | 604 bool opt) const { |
639 const intptr_t kNumInputs = 1; | 605 const intptr_t kNumInputs = 1; |
640 const intptr_t kNumTemps = 1; | 606 const intptr_t kNumTemps = 1; |
641 LocationSummary* locs = new (zone) | 607 LocationSummary* locs = new (zone) |
642 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 608 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
643 locs->set_in(0, Location::RequiresRegister()); | 609 locs->set_in(0, Location::RequiresRegister()); |
644 locs->set_temp(0, Location::RequiresRegister()); | 610 locs->set_temp(0, Location::RequiresRegister()); |
645 locs->set_out(0, Location::RequiresRegister()); | 611 locs->set_out(0, Location::RequiresRegister()); |
646 return locs; | 612 return locs; |
647 } | 613 } |
648 | 614 |
649 | |
650 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 615 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
651 BranchLabels labels) { | 616 BranchLabels labels) { |
652 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 617 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
653 Register val_reg = locs()->in(0).reg(); | 618 Register val_reg = locs()->in(0).reg(); |
654 Register cid_reg = locs()->temp(0).reg(); | 619 Register cid_reg = locs()->temp(0).reg(); |
655 | 620 |
656 Label* deopt = | 621 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
657 CanDeoptimize() | 622 deopt_id(), ICData::kDeoptTestCids, |
658 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 623 licm_hoisted_ ? ICData::kHoisted : 0) |
659 licm_hoisted_ ? ICData::kHoisted : 0) | 624 : NULL; |
660 : NULL; | |
661 | 625 |
662 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 626 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
663 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 627 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
664 ASSERT(data[0] == kSmiCid); | 628 ASSERT(data[0] == kSmiCid); |
665 bool result = data[1] == true_result; | 629 bool result = data[1] == true_result; |
666 __ testq(val_reg, Immediate(kSmiTagMask)); | 630 __ testq(val_reg, Immediate(kSmiTagMask)); |
667 __ j(ZERO, result ? labels.true_label : labels.false_label); | 631 __ j(ZERO, result ? labels.true_label : labels.false_label); |
668 __ LoadClassId(cid_reg, val_reg); | 632 __ LoadClassId(cid_reg, val_reg); |
669 for (intptr_t i = 2; i < data.length(); i += 2) { | 633 for (intptr_t i = 2; i < data.length(); i += 2) { |
670 const intptr_t test_cid = data[i]; | 634 const intptr_t test_cid = data[i]; |
(...skipping 12 matching lines...) Expand all Loading... |
683 __ jmp(target); | 647 __ jmp(target); |
684 } | 648 } |
685 } else { | 649 } else { |
686 __ jmp(deopt); | 650 __ jmp(deopt); |
687 } | 651 } |
688 // Dummy result as this method already did the jump, there's no need | 652 // Dummy result as this method already did the jump, there's no need |
689 // for the caller to branch on a condition. | 653 // for the caller to branch on a condition. |
690 return INVALID_CONDITION; | 654 return INVALID_CONDITION; |
691 } | 655 } |
692 | 656 |
693 | |
694 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 657 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
695 bool opt) const { | 658 bool opt) const { |
696 const intptr_t kNumInputs = 2; | 659 const intptr_t kNumInputs = 2; |
697 const intptr_t kNumTemps = 0; | 660 const intptr_t kNumTemps = 0; |
698 if (operation_cid() == kDoubleCid) { | 661 if (operation_cid() == kDoubleCid) { |
699 LocationSummary* summary = new (zone) | 662 LocationSummary* summary = new (zone) |
700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 663 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
701 summary->set_in(0, Location::RequiresFpuRegister()); | 664 summary->set_in(0, Location::RequiresFpuRegister()); |
702 summary->set_in(1, Location::RequiresFpuRegister()); | 665 summary->set_in(1, Location::RequiresFpuRegister()); |
703 summary->set_out(0, Location::RequiresRegister()); | 666 summary->set_out(0, Location::RequiresRegister()); |
(...skipping 12 matching lines...) Expand all Loading... |
716 summary->set_in(0, Location::RegisterOrConstant(left())); | 679 summary->set_in(0, Location::RegisterOrConstant(left())); |
717 // Only one input can be a constant operand. The case of two constant | 680 // Only one input can be a constant operand. The case of two constant |
718 // operands should be handled by constant propagation. | 681 // operands should be handled by constant propagation. |
719 summary->set_in(1, summary->in(0).IsConstant() | 682 summary->set_in(1, summary->in(0).IsConstant() |
720 ? Location::RequiresRegister() | 683 ? Location::RequiresRegister() |
721 : Location::RegisterOrConstant(right())); | 684 : Location::RegisterOrConstant(right())); |
722 summary->set_out(0, Location::RequiresRegister()); | 685 summary->set_out(0, Location::RequiresRegister()); |
723 return summary; | 686 return summary; |
724 } | 687 } |
725 | 688 |
726 | |
727 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 689 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
728 BranchLabels labels) { | 690 BranchLabels labels) { |
729 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 691 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
730 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 692 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
731 } else { | 693 } else { |
732 ASSERT(operation_cid() == kDoubleCid); | 694 ASSERT(operation_cid() == kDoubleCid); |
733 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 695 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
734 } | 696 } |
735 } | 697 } |
736 | 698 |
737 | |
738 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 699 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
739 bool opt) const { | 700 bool opt) const { |
740 return MakeCallSummary(zone); | 701 return MakeCallSummary(zone); |
741 } | 702 } |
742 | 703 |
743 | |
744 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 704 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
745 SetupNative(); | 705 SetupNative(); |
746 Register result = locs()->out(0).reg(); | 706 Register result = locs()->out(0).reg(); |
747 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 707 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
748 | 708 |
749 // Push the result place holder initialized to NULL. | 709 // Push the result place holder initialized to NULL. |
750 __ PushObject(Object::null_object()); | 710 __ PushObject(Object::null_object()); |
751 // Pass a pointer to the first argument in RAX. | 711 // Pass a pointer to the first argument in RAX. |
752 if (!function().HasOptionalParameters()) { | 712 if (!function().HasOptionalParameters()) { |
753 __ leaq(RAX, | 713 __ leaq(RAX, |
(...skipping 19 matching lines...) Expand all Loading... |
773 stub_entry = StubCode::CallNoScopeNative_entry(); | 733 stub_entry = StubCode::CallNoScopeNative_entry(); |
774 } | 734 } |
775 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 735 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
776 __ LoadNativeEntry(RBX, &label, kNotPatchable); | 736 __ LoadNativeEntry(RBX, &label, kNotPatchable); |
777 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 737 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
778 locs()); | 738 locs()); |
779 } | 739 } |
780 __ popq(result); | 740 __ popq(result); |
781 } | 741 } |
782 | 742 |
783 | |
784 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { | 743 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { |
785 if (!index->definition()->IsConstant()) return false; | 744 if (!index->definition()->IsConstant()) return false; |
786 const Object& constant = index->definition()->AsConstant()->value(); | 745 const Object& constant = index->definition()->AsConstant()->value(); |
787 if (!constant.IsSmi()) return false; | 746 if (!constant.IsSmi()) return false; |
788 const Smi& smi_const = Smi::Cast(constant); | 747 const Smi& smi_const = Smi::Cast(constant); |
789 const intptr_t scale = Instance::ElementSizeFor(cid); | 748 const intptr_t scale = Instance::ElementSizeFor(cid); |
790 const intptr_t data_offset = Instance::DataOffsetFor(cid); | 749 const intptr_t data_offset = Instance::DataOffsetFor(cid); |
791 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; | 750 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; |
792 return Utils::IsInt(32, disp); | 751 return Utils::IsInt(32, disp); |
793 } | 752 } |
794 | 753 |
795 | |
796 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 754 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
797 Zone* zone, | 755 Zone* zone, |
798 bool opt) const { | 756 bool opt) const { |
799 const intptr_t kNumInputs = 1; | 757 const intptr_t kNumInputs = 1; |
800 // TODO(fschneider): Allow immediate operands for the char code. | 758 // TODO(fschneider): Allow immediate operands for the char code. |
801 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 759 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
802 LocationSummary::kNoCall); | 760 LocationSummary::kNoCall); |
803 } | 761 } |
804 | 762 |
805 | |
806 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 763 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
807 FlowGraphCompiler* compiler) { | 764 FlowGraphCompiler* compiler) { |
808 ASSERT(compiler->is_optimizing()); | 765 ASSERT(compiler->is_optimizing()); |
809 Register char_code = locs()->in(0).reg(); | 766 Register char_code = locs()->in(0).reg(); |
810 Register result = locs()->out(0).reg(); | 767 Register result = locs()->out(0).reg(); |
811 | 768 |
812 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); | 769 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); |
813 __ movq(result, Address(result, char_code, | 770 __ movq(result, Address(result, char_code, |
814 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 771 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
815 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 772 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
816 } | 773 } |
817 | 774 |
818 | |
819 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 775 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
820 bool opt) const { | 776 bool opt) const { |
821 const intptr_t kNumInputs = 1; | 777 const intptr_t kNumInputs = 1; |
822 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 778 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
823 LocationSummary::kNoCall); | 779 LocationSummary::kNoCall); |
824 } | 780 } |
825 | 781 |
826 | |
827 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 782 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
828 ASSERT(cid_ == kOneByteStringCid); | 783 ASSERT(cid_ == kOneByteStringCid); |
829 Register str = locs()->in(0).reg(); | 784 Register str = locs()->in(0).reg(); |
830 Register result = locs()->out(0).reg(); | 785 Register result = locs()->out(0).reg(); |
831 Label is_one, done; | 786 Label is_one, done; |
832 __ movq(result, FieldAddress(str, String::length_offset())); | 787 __ movq(result, FieldAddress(str, String::length_offset())); |
833 __ cmpq(result, Immediate(Smi::RawValue(1))); | 788 __ cmpq(result, Immediate(Smi::RawValue(1))); |
834 __ j(EQUAL, &is_one, Assembler::kNearJump); | 789 __ j(EQUAL, &is_one, Assembler::kNearJump); |
835 __ movq(result, Immediate(Smi::RawValue(-1))); | 790 __ movq(result, Immediate(Smi::RawValue(-1))); |
836 __ jmp(&done); | 791 __ jmp(&done); |
837 __ Bind(&is_one); | 792 __ Bind(&is_one); |
838 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 793 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
839 __ SmiTag(result); | 794 __ SmiTag(result); |
840 __ Bind(&done); | 795 __ Bind(&done); |
841 } | 796 } |
842 | 797 |
843 | |
844 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 798 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
845 bool opt) const { | 799 bool opt) const { |
846 const intptr_t kNumInputs = 1; | 800 const intptr_t kNumInputs = 1; |
847 const intptr_t kNumTemps = 0; | 801 const intptr_t kNumTemps = 0; |
848 LocationSummary* summary = new (zone) | 802 LocationSummary* summary = new (zone) |
849 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 803 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
850 summary->set_in(0, Location::RegisterLocation(RAX)); | 804 summary->set_in(0, Location::RegisterLocation(RAX)); |
851 summary->set_out(0, Location::RegisterLocation(RAX)); | 805 summary->set_out(0, Location::RegisterLocation(RAX)); |
852 return summary; | 806 return summary; |
853 } | 807 } |
854 | 808 |
855 | |
856 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 809 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
857 Register array = locs()->in(0).reg(); | 810 Register array = locs()->in(0).reg(); |
858 __ pushq(array); | 811 __ pushq(array); |
859 const int kTypeArgsLen = 0; | 812 const int kTypeArgsLen = 0; |
860 const int kNumberOfArguments = 1; | 813 const int kNumberOfArguments = 1; |
861 const Array& kNoArgumentNames = Object::null_array(); | 814 const Array& kNoArgumentNames = Object::null_array(); |
862 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 815 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
863 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 816 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
864 args_info, locs(), ICData::Handle()); | 817 args_info, locs(), ICData::Handle()); |
865 ASSERT(locs()->out(0).reg() == RAX); | 818 ASSERT(locs()->out(0).reg() == RAX); |
866 } | 819 } |
867 | 820 |
868 | |
869 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 821 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
870 bool opt) const { | 822 bool opt) const { |
871 const intptr_t kNumInputs = 1; | 823 const intptr_t kNumInputs = 1; |
872 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 824 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
873 LocationSummary::kNoCall); | 825 LocationSummary::kNoCall); |
874 } | 826 } |
875 | 827 |
876 | |
877 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 828 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
878 Register obj = locs()->in(0).reg(); | 829 Register obj = locs()->in(0).reg(); |
879 Register result = locs()->out(0).reg(); | 830 Register result = locs()->out(0).reg(); |
880 if (object()->definition()->representation() == kUntagged) { | 831 if (object()->definition()->representation() == kUntagged) { |
881 __ movq(result, Address(obj, offset())); | 832 __ movq(result, Address(obj, offset())); |
882 } else { | 833 } else { |
883 ASSERT(object()->definition()->representation() == kTagged); | 834 ASSERT(object()->definition()->representation() == kTagged); |
884 __ movq(result, FieldAddress(obj, offset())); | 835 __ movq(result, FieldAddress(obj, offset())); |
885 } | 836 } |
886 } | 837 } |
887 | 838 |
888 | |
889 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 839 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
890 bool opt) const { | 840 bool opt) const { |
891 const intptr_t kNumInputs = 1; | 841 const intptr_t kNumInputs = 1; |
892 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 842 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
893 LocationSummary::kNoCall); | 843 LocationSummary::kNoCall); |
894 } | 844 } |
895 | 845 |
896 | |
897 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 846 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
898 const Register object = locs()->in(0).reg(); | 847 const Register object = locs()->in(0).reg(); |
899 const Register result = locs()->out(0).reg(); | 848 const Register result = locs()->out(0).reg(); |
900 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 849 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
901 if (CompileType::Smi().IsAssignableTo(value_type) || | 850 if (CompileType::Smi().IsAssignableTo(value_type) || |
902 value_type.IsTypeParameter()) { | 851 value_type.IsTypeParameter()) { |
903 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses | 852 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses |
904 // a conditional move instead---because it is slower, probably due to | 853 // a conditional move instead---because it is slower, probably due to |
905 // branch prediction usually working just fine in this case. | 854 // branch prediction usually working just fine in this case. |
906 Label load, done; | 855 Label load, done; |
907 __ testq(object, Immediate(kSmiTagMask)); | 856 __ testq(object, Immediate(kSmiTagMask)); |
908 __ j(NOT_ZERO, &load, Assembler::kNearJump); | 857 __ j(NOT_ZERO, &load, Assembler::kNearJump); |
909 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid))); | 858 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid))); |
910 __ jmp(&done); | 859 __ jmp(&done); |
911 __ Bind(&load); | 860 __ Bind(&load); |
912 __ LoadClassId(result, object); | 861 __ LoadClassId(result, object); |
913 __ SmiTag(result); | 862 __ SmiTag(result); |
914 __ Bind(&done); | 863 __ Bind(&done); |
915 } else { | 864 } else { |
916 __ LoadClassId(result, object); | 865 __ LoadClassId(result, object); |
917 __ SmiTag(result); | 866 __ SmiTag(result); |
918 } | 867 } |
919 } | 868 } |
920 | 869 |
921 | |
922 CompileType LoadIndexedInstr::ComputeType() const { | 870 CompileType LoadIndexedInstr::ComputeType() const { |
923 switch (class_id_) { | 871 switch (class_id_) { |
924 case kArrayCid: | 872 case kArrayCid: |
925 case kImmutableArrayCid: | 873 case kImmutableArrayCid: |
926 return CompileType::Dynamic(); | 874 return CompileType::Dynamic(); |
927 | 875 |
928 case kTypedDataFloat32ArrayCid: | 876 case kTypedDataFloat32ArrayCid: |
929 case kTypedDataFloat64ArrayCid: | 877 case kTypedDataFloat64ArrayCid: |
930 return CompileType::FromCid(kDoubleCid); | 878 return CompileType::FromCid(kDoubleCid); |
931 case kTypedDataFloat32x4ArrayCid: | 879 case kTypedDataFloat32x4ArrayCid: |
(...skipping 20 matching lines...) Expand all Loading... |
952 | 900 |
953 case kTypedDataInt64ArrayCid: | 901 case kTypedDataInt64ArrayCid: |
954 return CompileType::Int(); | 902 return CompileType::Int(); |
955 | 903 |
956 default: | 904 default: |
957 UNIMPLEMENTED(); | 905 UNIMPLEMENTED(); |
958 return CompileType::Dynamic(); | 906 return CompileType::Dynamic(); |
959 } | 907 } |
960 } | 908 } |
961 | 909 |
962 | |
963 Representation LoadIndexedInstr::representation() const { | 910 Representation LoadIndexedInstr::representation() const { |
964 switch (class_id_) { | 911 switch (class_id_) { |
965 case kArrayCid: | 912 case kArrayCid: |
966 case kImmutableArrayCid: | 913 case kImmutableArrayCid: |
967 case kTypedDataInt8ArrayCid: | 914 case kTypedDataInt8ArrayCid: |
968 case kTypedDataUint8ArrayCid: | 915 case kTypedDataUint8ArrayCid: |
969 case kTypedDataUint8ClampedArrayCid: | 916 case kTypedDataUint8ClampedArrayCid: |
970 case kExternalTypedDataUint8ArrayCid: | 917 case kExternalTypedDataUint8ArrayCid: |
971 case kExternalTypedDataUint8ClampedArrayCid: | 918 case kExternalTypedDataUint8ClampedArrayCid: |
972 case kTypedDataInt16ArrayCid: | 919 case kTypedDataInt16ArrayCid: |
(...skipping 17 matching lines...) Expand all Loading... |
990 case kTypedDataFloat32x4ArrayCid: | 937 case kTypedDataFloat32x4ArrayCid: |
991 return kUnboxedFloat32x4; | 938 return kUnboxedFloat32x4; |
992 case kTypedDataFloat64x2ArrayCid: | 939 case kTypedDataFloat64x2ArrayCid: |
993 return kUnboxedFloat64x2; | 940 return kUnboxedFloat64x2; |
994 default: | 941 default: |
995 UNIMPLEMENTED(); | 942 UNIMPLEMENTED(); |
996 return kTagged; | 943 return kTagged; |
997 } | 944 } |
998 } | 945 } |
999 | 946 |
1000 | |
1001 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 947 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1002 bool opt) const { | 948 bool opt) const { |
1003 const intptr_t kNumInputs = 2; | 949 const intptr_t kNumInputs = 2; |
1004 const intptr_t kNumTemps = 0; | 950 const intptr_t kNumTemps = 0; |
1005 LocationSummary* locs = new (zone) | 951 LocationSummary* locs = new (zone) |
1006 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 952 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1007 locs->set_in(0, Location::RequiresRegister()); | 953 locs->set_in(0, Location::RequiresRegister()); |
1008 // The smi index is either untagged (element size == 1), or it is left smi | 954 // The smi index is either untagged (element size == 1), or it is left smi |
1009 // tagged (for all element sizes > 1). | 955 // tagged (for all element sizes > 1). |
1010 if (index_scale() == 1) { | 956 if (index_scale() == 1) { |
(...skipping 11 matching lines...) Expand all Loading... |
1022 (representation() == kUnboxedFloat32x4) || | 968 (representation() == kUnboxedFloat32x4) || |
1023 (representation() == kUnboxedInt32x4) || | 969 (representation() == kUnboxedInt32x4) || |
1024 (representation() == kUnboxedFloat64x2)) { | 970 (representation() == kUnboxedFloat64x2)) { |
1025 locs->set_out(0, Location::RequiresFpuRegister()); | 971 locs->set_out(0, Location::RequiresFpuRegister()); |
1026 } else { | 972 } else { |
1027 locs->set_out(0, Location::RequiresRegister()); | 973 locs->set_out(0, Location::RequiresRegister()); |
1028 } | 974 } |
1029 return locs; | 975 return locs; |
1030 } | 976 } |
1031 | 977 |
1032 | |
1033 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 978 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1034 // The array register points to the backing store for external arrays. | 979 // The array register points to the backing store for external arrays. |
1035 const Register array = locs()->in(0).reg(); | 980 const Register array = locs()->in(0).reg(); |
1036 const Location index = locs()->in(1); | 981 const Location index = locs()->in(1); |
1037 | 982 |
1038 Address element_address = | 983 Address element_address = |
1039 index.IsRegister() | 984 index.IsRegister() |
1040 ? Assembler::ElementAddressForRegIndex( | 985 ? Assembler::ElementAddressForRegIndex( |
1041 IsExternal(), class_id(), index_scale(), array, index.reg()) | 986 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1042 : Assembler::ElementAddressForIntIndex( | 987 : Assembler::ElementAddressForIntIndex( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 __ movzxw(result, element_address); | 1072 __ movzxw(result, element_address); |
1128 __ SmiTag(result); | 1073 __ SmiTag(result); |
1129 break; | 1074 break; |
1130 default: | 1075 default: |
1131 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1076 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
1132 __ movq(result, element_address); | 1077 __ movq(result, element_address); |
1133 break; | 1078 break; |
1134 } | 1079 } |
1135 } | 1080 } |
1136 | 1081 |
1137 | |
1138 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1082 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
1139 bool opt) const { | 1083 bool opt) const { |
1140 const intptr_t kNumInputs = 2; | 1084 const intptr_t kNumInputs = 2; |
1141 const intptr_t kNumTemps = 0; | 1085 const intptr_t kNumTemps = 0; |
1142 LocationSummary* summary = new (zone) | 1086 LocationSummary* summary = new (zone) |
1143 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1087 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1144 summary->set_in(0, Location::RequiresRegister()); | 1088 summary->set_in(0, Location::RequiresRegister()); |
1145 // The smi index is either untagged (element size == 1), or it is left smi | 1089 // The smi index is either untagged (element size == 1), or it is left smi |
1146 // tagged (for all element sizes > 1). | 1090 // tagged (for all element sizes > 1). |
1147 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() | 1091 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() |
1148 : Location::RequiresRegister()); | 1092 : Location::RequiresRegister()); |
1149 summary->set_out(0, Location::RequiresRegister()); | 1093 summary->set_out(0, Location::RequiresRegister()); |
1150 return summary; | 1094 return summary; |
1151 } | 1095 } |
1152 | 1096 |
1153 | |
1154 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1097 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1155 // The string register points to the backing store for external strings. | 1098 // The string register points to the backing store for external strings. |
1156 const Register str = locs()->in(0).reg(); | 1099 const Register str = locs()->in(0).reg(); |
1157 const Location index = locs()->in(1); | 1100 const Location index = locs()->in(1); |
1158 | 1101 |
1159 Address element_address = Assembler::ElementAddressForRegIndex( | 1102 Address element_address = Assembler::ElementAddressForRegIndex( |
1160 IsExternal(), class_id(), index_scale(), str, index.reg()); | 1103 IsExternal(), class_id(), index_scale(), str, index.reg()); |
1161 | 1104 |
1162 if ((index_scale() == 1)) { | 1105 if ((index_scale() == 1)) { |
1163 __ SmiUntag(index.reg()); | 1106 __ SmiUntag(index.reg()); |
(...skipping 30 matching lines...) Expand all Loading... |
1194 UNREACHABLE(); | 1137 UNREACHABLE(); |
1195 } | 1138 } |
1196 __ SmiTag(result); | 1139 __ SmiTag(result); |
1197 break; | 1140 break; |
1198 default: | 1141 default: |
1199 UNREACHABLE(); | 1142 UNREACHABLE(); |
1200 break; | 1143 break; |
1201 } | 1144 } |
1202 } | 1145 } |
1203 | 1146 |
1204 | |
1205 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1147 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1206 intptr_t idx) const { | 1148 intptr_t idx) const { |
1207 if (idx == 0) return kNoRepresentation; | 1149 if (idx == 0) return kNoRepresentation; |
1208 if (idx == 1) return kTagged; | 1150 if (idx == 1) return kTagged; |
1209 ASSERT(idx == 2); | 1151 ASSERT(idx == 2); |
1210 switch (class_id_) { | 1152 switch (class_id_) { |
1211 case kArrayCid: | 1153 case kArrayCid: |
1212 case kOneByteStringCid: | 1154 case kOneByteStringCid: |
1213 case kTypedDataInt8ArrayCid: | 1155 case kTypedDataInt8ArrayCid: |
1214 case kTypedDataUint8ArrayCid: | 1156 case kTypedDataUint8ArrayCid: |
(...skipping 17 matching lines...) Expand all Loading... |
1232 case kTypedDataInt32x4ArrayCid: | 1174 case kTypedDataInt32x4ArrayCid: |
1233 return kUnboxedInt32x4; | 1175 return kUnboxedInt32x4; |
1234 case kTypedDataFloat64x2ArrayCid: | 1176 case kTypedDataFloat64x2ArrayCid: |
1235 return kUnboxedFloat64x2; | 1177 return kUnboxedFloat64x2; |
1236 default: | 1178 default: |
1237 UNIMPLEMENTED(); | 1179 UNIMPLEMENTED(); |
1238 return kTagged; | 1180 return kTagged; |
1239 } | 1181 } |
1240 } | 1182 } |
1241 | 1183 |
1242 | |
1243 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1184 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1244 bool opt) const { | 1185 bool opt) const { |
1245 const intptr_t kNumInputs = 3; | 1186 const intptr_t kNumInputs = 3; |
1246 const intptr_t kNumTemps = 0; | 1187 const intptr_t kNumTemps = 0; |
1247 LocationSummary* locs = new (zone) | 1188 LocationSummary* locs = new (zone) |
1248 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1249 locs->set_in(0, Location::RequiresRegister()); | 1190 locs->set_in(0, Location::RequiresRegister()); |
1250 // 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 |
1251 // tagged (for all element sizes > 1). | 1192 // tagged (for all element sizes > 1). |
1252 if (index_scale() == 1) { | 1193 if (index_scale() == 1) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 case kTypedDataFloat32x4ArrayCid: | 1237 case kTypedDataFloat32x4ArrayCid: |
1297 locs->set_in(2, Location::RequiresFpuRegister()); | 1238 locs->set_in(2, Location::RequiresFpuRegister()); |
1298 break; | 1239 break; |
1299 default: | 1240 default: |
1300 UNREACHABLE(); | 1241 UNREACHABLE(); |
1301 return NULL; | 1242 return NULL; |
1302 } | 1243 } |
1303 return locs; | 1244 return locs; |
1304 } | 1245 } |
1305 | 1246 |
1306 | |
1307 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1247 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1308 // The array register points to the backing store for external arrays. | 1248 // The array register points to the backing store for external arrays. |
1309 const Register array = locs()->in(0).reg(); | 1249 const Register array = locs()->in(0).reg(); |
1310 const Location index = locs()->in(1); | 1250 const Location index = locs()->in(1); |
1311 | 1251 |
1312 Address element_address = | 1252 Address element_address = |
1313 index.IsRegister() | 1253 index.IsRegister() |
1314 ? Assembler::ElementAddressForRegIndex( | 1254 ? Assembler::ElementAddressForRegIndex( |
1315 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1255 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1316 : Assembler::ElementAddressForIntIndex( | 1256 : Assembler::ElementAddressForIntIndex( |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 case kTypedDataInt32x4ArrayCid: | 1343 case kTypedDataInt32x4ArrayCid: |
1404 case kTypedDataFloat64x2ArrayCid: | 1344 case kTypedDataFloat64x2ArrayCid: |
1405 case kTypedDataFloat32x4ArrayCid: | 1345 case kTypedDataFloat32x4ArrayCid: |
1406 __ movups(element_address, locs()->in(2).fpu_reg()); | 1346 __ movups(element_address, locs()->in(2).fpu_reg()); |
1407 break; | 1347 break; |
1408 default: | 1348 default: |
1409 UNREACHABLE(); | 1349 UNREACHABLE(); |
1410 } | 1350 } |
1411 } | 1351 } |
1412 | 1352 |
1413 | |
1414 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1353 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1415 bool opt) const { | 1354 bool opt) const { |
1416 const intptr_t kNumInputs = 1; | 1355 const intptr_t kNumInputs = 1; |
1417 | 1356 |
1418 const intptr_t value_cid = value()->Type()->ToCid(); | 1357 const intptr_t value_cid = value()->Type()->ToCid(); |
1419 const intptr_t field_cid = field().guarded_cid(); | 1358 const intptr_t field_cid = field().guarded_cid(); |
1420 | 1359 |
1421 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1360 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1422 const bool needs_value_cid_temp_reg = | 1361 const bool needs_value_cid_temp_reg = |
1423 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1362 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
1424 const bool needs_field_temp_reg = emit_full_guard; | 1363 const bool needs_field_temp_reg = emit_full_guard; |
1425 | 1364 |
1426 intptr_t num_temps = 0; | 1365 intptr_t num_temps = 0; |
1427 if (needs_value_cid_temp_reg) { | 1366 if (needs_value_cid_temp_reg) { |
1428 num_temps++; | 1367 num_temps++; |
1429 } | 1368 } |
1430 if (needs_field_temp_reg) { | 1369 if (needs_field_temp_reg) { |
1431 num_temps++; | 1370 num_temps++; |
1432 } | 1371 } |
1433 | 1372 |
1434 LocationSummary* summary = new (zone) | 1373 LocationSummary* summary = new (zone) |
1435 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1374 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1436 summary->set_in(0, Location::RequiresRegister()); | 1375 summary->set_in(0, Location::RequiresRegister()); |
1437 | 1376 |
1438 for (intptr_t i = 0; i < num_temps; i++) { | 1377 for (intptr_t i = 0; i < num_temps; i++) { |
1439 summary->set_temp(i, Location::RequiresRegister()); | 1378 summary->set_temp(i, Location::RequiresRegister()); |
1440 } | 1379 } |
1441 | 1380 |
1442 | |
1443 return summary; | 1381 return summary; |
1444 } | 1382 } |
1445 | 1383 |
1446 | |
1447 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1384 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1448 ASSERT(sizeof(classid_t) == kInt16Size); | 1385 ASSERT(sizeof(classid_t) == kInt16Size); |
1449 const intptr_t value_cid = value()->Type()->ToCid(); | 1386 const intptr_t value_cid = value()->Type()->ToCid(); |
1450 const intptr_t field_cid = field().guarded_cid(); | 1387 const intptr_t field_cid = field().guarded_cid(); |
1451 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1388 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1452 | 1389 |
1453 if (field_cid == kDynamicCid) { | 1390 if (field_cid == kDynamicCid) { |
1454 if (Compiler::IsBackgroundCompilation()) { | 1391 if (Compiler::IsBackgroundCompilation()) { |
1455 // Field state changed while compiling. | 1392 // Field state changed while compiling. |
1456 Compiler::AbortBackgroundCompilation( | 1393 Compiler::AbortBackgroundCompilation( |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 __ j(NOT_EQUAL, fail); | 1505 __ j(NOT_EQUAL, fail); |
1569 } else { | 1506 } else { |
1570 // Both value's and field's class id is known. | 1507 // Both value's and field's class id is known. |
1571 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1508 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
1572 __ jmp(fail); | 1509 __ jmp(fail); |
1573 } | 1510 } |
1574 } | 1511 } |
1575 __ Bind(&ok); | 1512 __ Bind(&ok); |
1576 } | 1513 } |
1577 | 1514 |
1578 | |
1579 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1515 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1580 bool opt) const { | 1516 bool opt) const { |
1581 const intptr_t kNumInputs = 1; | 1517 const intptr_t kNumInputs = 1; |
1582 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1518 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1583 const intptr_t kNumTemps = 3; | 1519 const intptr_t kNumTemps = 3; |
1584 LocationSummary* summary = new (zone) | 1520 LocationSummary* summary = new (zone) |
1585 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1521 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1586 summary->set_in(0, Location::RequiresRegister()); | 1522 summary->set_in(0, Location::RequiresRegister()); |
1587 // We need temporaries for field object, length offset and expected length. | 1523 // We need temporaries for field object, length offset and expected length. |
1588 summary->set_temp(0, Location::RequiresRegister()); | 1524 summary->set_temp(0, Location::RequiresRegister()); |
1589 summary->set_temp(1, Location::RequiresRegister()); | 1525 summary->set_temp(1, Location::RequiresRegister()); |
1590 summary->set_temp(2, Location::RequiresRegister()); | 1526 summary->set_temp(2, Location::RequiresRegister()); |
1591 return summary; | 1527 return summary; |
1592 } else { | 1528 } else { |
1593 LocationSummary* summary = new (zone) | 1529 LocationSummary* summary = new (zone) |
1594 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 1530 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
1595 summary->set_in(0, Location::RequiresRegister()); | 1531 summary->set_in(0, Location::RequiresRegister()); |
1596 return summary; | 1532 return summary; |
1597 } | 1533 } |
1598 UNREACHABLE(); | 1534 UNREACHABLE(); |
1599 } | 1535 } |
1600 | 1536 |
1601 | |
1602 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1537 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1603 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1538 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1604 if (Compiler::IsBackgroundCompilation()) { | 1539 if (Compiler::IsBackgroundCompilation()) { |
1605 // Field state changed while compiling. | 1540 // Field state changed while compiling. |
1606 Compiler::AbortBackgroundCompilation( | 1541 Compiler::AbortBackgroundCompilation( |
1607 deopt_id(), | 1542 deopt_id(), |
1608 "GuardFieldLengthInstr: field state changed while compiling"); | 1543 "GuardFieldLengthInstr: field state changed while compiling"); |
1609 } | 1544 } |
1610 ASSERT(!compiler->is_optimizing()); | 1545 ASSERT(!compiler->is_optimizing()); |
1611 return; // Nothing to emit. | 1546 return; // Nothing to emit. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1662 ASSERT(field().guarded_list_length_in_object_offset() != | 1597 ASSERT(field().guarded_list_length_in_object_offset() != |
1663 Field::kUnknownLengthOffset); | 1598 Field::kUnknownLengthOffset); |
1664 | 1599 |
1665 __ CompareImmediate( | 1600 __ CompareImmediate( |
1666 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), | 1601 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
1667 Immediate(Smi::RawValue(field().guarded_list_length()))); | 1602 Immediate(Smi::RawValue(field().guarded_list_length()))); |
1668 __ j(NOT_EQUAL, deopt); | 1603 __ j(NOT_EQUAL, deopt); |
1669 } | 1604 } |
1670 } | 1605 } |
1671 | 1606 |
1672 | |
1673 class BoxAllocationSlowPath : public SlowPathCode { | 1607 class BoxAllocationSlowPath : public SlowPathCode { |
1674 public: | 1608 public: |
1675 BoxAllocationSlowPath(Instruction* instruction, | 1609 BoxAllocationSlowPath(Instruction* instruction, |
1676 const Class& cls, | 1610 const Class& cls, |
1677 Register result) | 1611 Register result) |
1678 : instruction_(instruction), cls_(cls), result_(result) {} | 1612 : instruction_(instruction), cls_(cls), result_(result) {} |
1679 | 1613 |
1680 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1614 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1681 if (Assembler::EmittingComments()) { | 1615 if (Assembler::EmittingComments()) { |
1682 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 1616 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1718 __ Bind(slow_path->exit_label()); | 1652 __ Bind(slow_path->exit_label()); |
1719 } | 1653 } |
1720 } | 1654 } |
1721 | 1655 |
1722 private: | 1656 private: |
1723 Instruction* instruction_; | 1657 Instruction* instruction_; |
1724 const Class& cls_; | 1658 const Class& cls_; |
1725 const Register result_; | 1659 const Register result_; |
1726 }; | 1660 }; |
1727 | 1661 |
1728 | |
1729 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1662 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
1730 bool opt) const { | 1663 bool opt) const { |
1731 const intptr_t kNumInputs = 2; | 1664 const intptr_t kNumInputs = 2; |
1732 const intptr_t kNumTemps = | 1665 const intptr_t kNumTemps = |
1733 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); | 1666 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
1734 LocationSummary* summary = new (zone) | 1667 LocationSummary* summary = new (zone) |
1735 LocationSummary(zone, kNumInputs, kNumTemps, | 1668 LocationSummary(zone, kNumInputs, kNumTemps, |
1736 ((IsUnboxedStore() && opt && is_initialization()) || | 1669 ((IsUnboxedStore() && opt && is_initialization()) || |
1737 IsPotentialUnboxedStore()) | 1670 IsPotentialUnboxedStore()) |
1738 ? LocationSummary::kCallOnSlowPath | 1671 ? LocationSummary::kCallOnSlowPath |
(...skipping 12 matching lines...) Expand all Loading... |
1751 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1684 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
1752 : Location::FpuRegisterLocation(XMM1)); | 1685 : Location::FpuRegisterLocation(XMM1)); |
1753 } else { | 1686 } else { |
1754 summary->set_in(1, ShouldEmitStoreBarrier() | 1687 summary->set_in(1, ShouldEmitStoreBarrier() |
1755 ? Location::WritableRegister() | 1688 ? Location::WritableRegister() |
1756 : Location::RegisterOrConstant(value())); | 1689 : Location::RegisterOrConstant(value())); |
1757 } | 1690 } |
1758 return summary; | 1691 return summary; |
1759 } | 1692 } |
1760 | 1693 |
1761 | |
1762 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1694 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
1763 StoreInstanceFieldInstr* instruction, | 1695 StoreInstanceFieldInstr* instruction, |
1764 Register box_reg, | 1696 Register box_reg, |
1765 const Class& cls, | 1697 const Class& cls, |
1766 Register instance_reg, | 1698 Register instance_reg, |
1767 intptr_t offset, | 1699 intptr_t offset, |
1768 Register temp) { | 1700 Register temp) { |
1769 Label done; | 1701 Label done; |
1770 __ movq(box_reg, FieldAddress(instance_reg, offset)); | 1702 __ movq(box_reg, FieldAddress(instance_reg, offset)); |
1771 __ CompareObject(box_reg, Object::null_object()); | 1703 __ CompareObject(box_reg, Object::null_object()); |
1772 __ j(NOT_EQUAL, &done); | 1704 __ j(NOT_EQUAL, &done); |
1773 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1705 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
1774 __ movq(temp, box_reg); | 1706 __ movq(temp, box_reg); |
1775 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); | 1707 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
1776 | 1708 |
1777 __ Bind(&done); | 1709 __ Bind(&done); |
1778 } | 1710 } |
1779 | 1711 |
1780 | |
1781 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1712 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1782 ASSERT(sizeof(classid_t) == kInt16Size); | 1713 ASSERT(sizeof(classid_t) == kInt16Size); |
1783 Label skip_store; | 1714 Label skip_store; |
1784 | 1715 |
1785 Register instance_reg = locs()->in(0).reg(); | 1716 Register instance_reg = locs()->in(0).reg(); |
1786 | 1717 |
1787 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1718 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1788 XmmRegister value = locs()->in(1).fpu_reg(); | 1719 XmmRegister value = locs()->in(1).fpu_reg(); |
1789 Register temp = locs()->temp(0).reg(); | 1720 Register temp = locs()->temp(0).reg(); |
1790 Register temp2 = locs()->temp(1).reg(); | 1721 Register temp2 = locs()->temp(1).reg(); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1922 } else { | 1853 } else { |
1923 Register value_reg = locs()->in(1).reg(); | 1854 Register value_reg = locs()->in(1).reg(); |
1924 __ StoreIntoObjectNoBarrier(instance_reg, | 1855 __ StoreIntoObjectNoBarrier(instance_reg, |
1925 FieldAddress(instance_reg, offset_in_bytes_), | 1856 FieldAddress(instance_reg, offset_in_bytes_), |
1926 value_reg); | 1857 value_reg); |
1927 } | 1858 } |
1928 } | 1859 } |
1929 __ Bind(&skip_store); | 1860 __ Bind(&skip_store); |
1930 } | 1861 } |
1931 | 1862 |
1932 | |
1933 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1863 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
1934 bool opt) const { | 1864 bool opt) const { |
1935 const intptr_t kNumInputs = 1; | 1865 const intptr_t kNumInputs = 1; |
1936 const intptr_t kNumTemps = 0; | 1866 const intptr_t kNumTemps = 0; |
1937 LocationSummary* summary = new (zone) | 1867 LocationSummary* summary = new (zone) |
1938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1868 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1939 summary->set_in(0, Location::RequiresRegister()); | 1869 summary->set_in(0, Location::RequiresRegister()); |
1940 summary->set_out(0, Location::RequiresRegister()); | 1870 summary->set_out(0, Location::RequiresRegister()); |
1941 return summary; | 1871 return summary; |
1942 } | 1872 } |
1943 | 1873 |
1944 | |
1945 // When the parser is building an implicit static getter for optimization, | 1874 // When the parser is building an implicit static getter for optimization, |
1946 // it can generate a function body where deoptimization ids do not line up | 1875 // it can generate a function body where deoptimization ids do not line up |
1947 // with the unoptimized code. | 1876 // with the unoptimized code. |
1948 // | 1877 // |
1949 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1878 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
1950 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1879 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1951 Register field = locs()->in(0).reg(); | 1880 Register field = locs()->in(0).reg(); |
1952 Register result = locs()->out(0).reg(); | 1881 Register result = locs()->out(0).reg(); |
1953 __ movq(result, FieldAddress(field, Field::static_value_offset())); | 1882 __ movq(result, FieldAddress(field, Field::static_value_offset())); |
1954 } | 1883 } |
1955 | 1884 |
1956 | |
1957 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1885 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
1958 bool opt) const { | 1886 bool opt) const { |
1959 LocationSummary* locs = | 1887 LocationSummary* locs = |
1960 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 1888 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
1961 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1889 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
1962 : Location::RequiresRegister()); | 1890 : Location::RequiresRegister()); |
1963 locs->set_temp(0, Location::RequiresRegister()); | 1891 locs->set_temp(0, Location::RequiresRegister()); |
1964 return locs; | 1892 return locs; |
1965 } | 1893 } |
1966 | 1894 |
1967 | |
1968 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1895 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1969 Register value = locs()->in(0).reg(); | 1896 Register value = locs()->in(0).reg(); |
1970 Register temp = locs()->temp(0).reg(); | 1897 Register temp = locs()->temp(0).reg(); |
1971 | 1898 |
1972 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1899 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
1973 if (this->value()->NeedsStoreBuffer()) { | 1900 if (this->value()->NeedsStoreBuffer()) { |
1974 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), | 1901 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
1975 value, CanValueBeSmi()); | 1902 value, CanValueBeSmi()); |
1976 } else { | 1903 } else { |
1977 __ StoreIntoObjectNoBarrier( | 1904 __ StoreIntoObjectNoBarrier( |
1978 temp, FieldAddress(temp, Field::static_value_offset()), value); | 1905 temp, FieldAddress(temp, Field::static_value_offset()), value); |
1979 } | 1906 } |
1980 } | 1907 } |
1981 | 1908 |
1982 | |
1983 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1909 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
1984 bool opt) const { | 1910 bool opt) const { |
1985 const intptr_t kNumInputs = 3; | 1911 const intptr_t kNumInputs = 3; |
1986 const intptr_t kNumTemps = 0; | 1912 const intptr_t kNumTemps = 0; |
1987 LocationSummary* summary = new (zone) | 1913 LocationSummary* summary = new (zone) |
1988 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1914 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
1989 summary->set_in(0, Location::RegisterLocation(RAX)); // Instance. | 1915 summary->set_in(0, Location::RegisterLocation(RAX)); // Instance. |
1990 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. | 1916 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
1991 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. | 1917 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
1992 summary->set_out(0, Location::RegisterLocation(RAX)); | 1918 summary->set_out(0, Location::RegisterLocation(RAX)); |
1993 return summary; | 1919 return summary; |
1994 } | 1920 } |
1995 | 1921 |
1996 | |
1997 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1922 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1998 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1923 ASSERT(locs()->in(0).reg() == RAX); // Value. |
1999 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. | 1924 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. |
2000 ASSERT(locs()->in(2).reg() == RCX); // Function type arguments. | 1925 ASSERT(locs()->in(2).reg() == RCX); // Function type arguments. |
2001 | 1926 |
2002 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 1927 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
2003 ASSERT(locs()->out(0).reg() == RAX); | 1928 ASSERT(locs()->out(0).reg() == RAX); |
2004 } | 1929 } |
2005 | 1930 |
2006 | |
2007 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 1931 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
2008 // use slow path stub. | 1932 // use slow path stub. |
2009 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 1933 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
2010 bool opt) const { | 1934 bool opt) const { |
2011 const intptr_t kNumInputs = 2; | 1935 const intptr_t kNumInputs = 2; |
2012 const intptr_t kNumTemps = 0; | 1936 const intptr_t kNumTemps = 0; |
2013 LocationSummary* locs = new (zone) | 1937 LocationSummary* locs = new (zone) |
2014 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2015 locs->set_in(0, Location::RegisterLocation(RBX)); | 1939 locs->set_in(0, Location::RegisterLocation(RBX)); |
2016 locs->set_in(1, Location::RegisterLocation(R10)); | 1940 locs->set_in(1, Location::RegisterLocation(R10)); |
2017 locs->set_out(0, Location::RegisterLocation(RAX)); | 1941 locs->set_out(0, Location::RegisterLocation(RAX)); |
2018 return locs; | 1942 return locs; |
2019 } | 1943 } |
2020 | 1944 |
2021 | |
2022 // Inlines array allocation for known constant values. | 1945 // Inlines array allocation for known constant values. |
2023 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 1946 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
2024 intptr_t num_elements, | 1947 intptr_t num_elements, |
2025 Label* slow_path, | 1948 Label* slow_path, |
2026 Label* done) { | 1949 Label* done) { |
2027 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 1950 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
2028 const Register kLengthReg = R10; | 1951 const Register kLengthReg = R10; |
2029 const Register kElemTypeReg = RBX; | 1952 const Register kElemTypeReg = RBX; |
2030 const intptr_t instance_size = Array::InstanceSize(num_elements); | 1953 const intptr_t instance_size = Array::InstanceSize(num_elements); |
2031 | 1954 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2063 __ Bind(&init_loop); | 1986 __ Bind(&init_loop); |
2064 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); | 1987 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); |
2065 __ addq(RDI, Immediate(kWordSize)); | 1988 __ addq(RDI, Immediate(kWordSize)); |
2066 __ cmpq(RDI, RCX); | 1989 __ cmpq(RDI, RCX); |
2067 __ j(BELOW, &init_loop, Assembler::kNearJump); | 1990 __ j(BELOW, &init_loop, Assembler::kNearJump); |
2068 } | 1991 } |
2069 } | 1992 } |
2070 __ jmp(done, Assembler::kNearJump); | 1993 __ jmp(done, Assembler::kNearJump); |
2071 } | 1994 } |
2072 | 1995 |
2073 | |
2074 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1996 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2075 // Allocate the array. R10 = length, RBX = element type. | 1997 // Allocate the array. R10 = length, RBX = element type. |
2076 const Register kLengthReg = R10; | 1998 const Register kLengthReg = R10; |
2077 const Register kElemTypeReg = RBX; | 1999 const Register kElemTypeReg = RBX; |
2078 const Register kResultReg = RAX; | 2000 const Register kResultReg = RAX; |
2079 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2001 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
2080 ASSERT(locs()->in(1).reg() == kLengthReg); | 2002 ASSERT(locs()->in(1).reg() == kLengthReg); |
2081 | 2003 |
2082 Label slow_path, done; | 2004 Label slow_path, done; |
2083 if (compiler->is_optimizing() && !FLAG_precompiled_mode && | 2005 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
(...skipping 20 matching lines...) Expand all Loading... |
2104 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2026 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2105 StubCode::AllocateArray_entry()->code()); | 2027 StubCode::AllocateArray_entry()->code()); |
2106 compiler->AddStubCallTarget(stub); | 2028 compiler->AddStubCallTarget(stub); |
2107 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), | 2029 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), |
2108 *StubCode::AllocateArray_entry(), | 2030 *StubCode::AllocateArray_entry(), |
2109 RawPcDescriptors::kOther, locs()); | 2031 RawPcDescriptors::kOther, locs()); |
2110 __ Bind(&done); | 2032 __ Bind(&done); |
2111 ASSERT(locs()->out(0).reg() == kResultReg); | 2033 ASSERT(locs()->out(0).reg() == kResultReg); |
2112 } | 2034 } |
2113 | 2035 |
2114 | |
2115 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2036 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2116 bool opt) const { | 2037 bool opt) const { |
2117 const intptr_t kNumInputs = 1; | 2038 const intptr_t kNumInputs = 1; |
2118 const intptr_t kNumTemps = | 2039 const intptr_t kNumTemps = |
2119 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2040 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
2120 LocationSummary* locs = new (zone) LocationSummary( | 2041 LocationSummary* locs = new (zone) LocationSummary( |
2121 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 2042 zone, kNumInputs, kNumTemps, |
2122 ? LocationSummary::kNoCall | 2043 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall |
2123 : LocationSummary::kCallOnSlowPath); | 2044 : LocationSummary::kCallOnSlowPath); |
2124 | 2045 |
2125 locs->set_in(0, Location::RequiresRegister()); | 2046 locs->set_in(0, Location::RequiresRegister()); |
2126 | 2047 |
2127 if (IsUnboxedLoad() && opt) { | 2048 if (IsUnboxedLoad() && opt) { |
2128 locs->set_temp(0, Location::RequiresRegister()); | 2049 locs->set_temp(0, Location::RequiresRegister()); |
2129 } else if (IsPotentialUnboxedLoad()) { | 2050 } else if (IsPotentialUnboxedLoad()) { |
2130 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2051 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
2131 : Location::FpuRegisterLocation(XMM1)); | 2052 : Location::FpuRegisterLocation(XMM1)); |
2132 locs->set_temp(1, Location::RequiresRegister()); | 2053 locs->set_temp(1, Location::RequiresRegister()); |
2133 } | 2054 } |
2134 locs->set_out(0, Location::RequiresRegister()); | 2055 locs->set_out(0, Location::RequiresRegister()); |
2135 return locs; | 2056 return locs; |
2136 } | 2057 } |
2137 | 2058 |
2138 | |
2139 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2059 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2140 ASSERT(sizeof(classid_t) == kInt16Size); | 2060 ASSERT(sizeof(classid_t) == kInt16Size); |
2141 Register instance_reg = locs()->in(0).reg(); | 2061 Register instance_reg = locs()->in(0).reg(); |
2142 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2062 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
2143 XmmRegister result = locs()->out(0).fpu_reg(); | 2063 XmmRegister result = locs()->out(0).fpu_reg(); |
2144 Register temp = locs()->temp(0).reg(); | 2064 Register temp = locs()->temp(0).reg(); |
2145 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2065 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2146 intptr_t cid = field()->UnboxedFieldCid(); | 2066 intptr_t cid = field()->UnboxedFieldCid(); |
2147 switch (cid) { | 2067 switch (cid) { |
2148 case kDoubleCid: | 2068 case kDoubleCid: |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2227 __ movups(FieldAddress(result, Float64x2::value_offset()), value); | 2147 __ movups(FieldAddress(result, Float64x2::value_offset()), value); |
2228 __ jmp(&done); | 2148 __ jmp(&done); |
2229 } | 2149 } |
2230 | 2150 |
2231 __ Bind(&load_pointer); | 2151 __ Bind(&load_pointer); |
2232 } | 2152 } |
2233 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); | 2153 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); |
2234 __ Bind(&done); | 2154 __ Bind(&done); |
2235 } | 2155 } |
2236 | 2156 |
2237 | |
2238 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2157 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2239 bool opt) const { | 2158 bool opt) const { |
2240 const intptr_t kNumInputs = 2; | 2159 const intptr_t kNumInputs = 2; |
2241 const intptr_t kNumTemps = 0; | 2160 const intptr_t kNumTemps = 0; |
2242 LocationSummary* locs = new (zone) | 2161 LocationSummary* locs = new (zone) |
2243 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2162 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2244 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. | 2163 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
2245 locs->set_in(1, Location::RegisterLocation(RDX)); // Function type args. | 2164 locs->set_in(1, Location::RegisterLocation(RDX)); // Function type args. |
2246 locs->set_out(0, Location::RegisterLocation(RAX)); | 2165 locs->set_out(0, Location::RegisterLocation(RAX)); |
2247 return locs; | 2166 return locs; |
2248 } | 2167 } |
2249 | 2168 |
2250 | |
2251 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2169 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2252 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2170 Register instantiator_type_args_reg = locs()->in(0).reg(); |
2253 Register function_type_args_reg = locs()->in(1).reg(); | 2171 Register function_type_args_reg = locs()->in(1).reg(); |
2254 Register result_reg = locs()->out(0).reg(); | 2172 Register result_reg = locs()->out(0).reg(); |
2255 | 2173 |
2256 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2174 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
2257 // 'function_type_args_reg' is a TypeArguments object (or null). | 2175 // 'function_type_args_reg' is a TypeArguments object (or null). |
2258 // A runtime call to instantiate the type is required. | 2176 // A runtime call to instantiate the type is required. |
2259 __ PushObject(Object::null_object()); // Make room for the result. | 2177 __ PushObject(Object::null_object()); // Make room for the result. |
2260 __ PushObject(type()); | 2178 __ PushObject(type()); |
2261 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. | 2179 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
2262 __ pushq(function_type_args_reg); // Push function type arguments. | 2180 __ pushq(function_type_args_reg); // Push function type arguments. |
2263 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2181 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2264 kInstantiateTypeRuntimeEntry, 3, locs()); | 2182 kInstantiateTypeRuntimeEntry, 3, locs()); |
2265 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. | 2183 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
2266 __ popq(result_reg); // Pop instantiated type. | 2184 __ popq(result_reg); // Pop instantiated type. |
2267 } | 2185 } |
2268 | 2186 |
2269 | |
2270 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2187 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2271 Zone* zone, | 2188 Zone* zone, |
2272 bool opt) const { | 2189 bool opt) const { |
2273 const intptr_t kNumInputs = 2; | 2190 const intptr_t kNumInputs = 2; |
2274 const intptr_t kNumTemps = 0; | 2191 const intptr_t kNumTemps = 0; |
2275 LocationSummary* locs = new (zone) | 2192 LocationSummary* locs = new (zone) |
2276 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2193 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2277 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. | 2194 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
2278 locs->set_in(1, Location::RegisterLocation(RCX)); // Function type args. | 2195 locs->set_in(1, Location::RegisterLocation(RCX)); // Function type args. |
2279 locs->set_out(0, Location::RegisterLocation(RAX)); | 2196 locs->set_out(0, Location::RegisterLocation(RAX)); |
2280 return locs; | 2197 return locs; |
2281 } | 2198 } |
2282 | 2199 |
2283 | |
2284 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2200 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2285 FlowGraphCompiler* compiler) { | 2201 FlowGraphCompiler* compiler) { |
2286 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2202 Register instantiator_type_args_reg = locs()->in(0).reg(); |
2287 Register function_type_args_reg = locs()->in(1).reg(); | 2203 Register function_type_args_reg = locs()->in(1).reg(); |
2288 Register result_reg = locs()->out(0).reg(); | 2204 Register result_reg = locs()->out(0).reg(); |
2289 ASSERT(instantiator_type_args_reg == RAX); | 2205 ASSERT(instantiator_type_args_reg == RAX); |
2290 ASSERT(instantiator_type_args_reg == result_reg); | 2206 ASSERT(instantiator_type_args_reg == result_reg); |
2291 | 2207 |
2292 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2208 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
2293 // 'function_type_args_reg' is a TypeArguments object (or null). | 2209 // 'function_type_args_reg' is a TypeArguments object (or null). |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2341 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. | 2257 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
2342 __ pushq(function_type_args_reg); // Push function type arguments. | 2258 __ pushq(function_type_args_reg); // Push function type arguments. |
2343 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2259 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2344 kInstantiateTypeArgumentsRuntimeEntry, 3, | 2260 kInstantiateTypeArgumentsRuntimeEntry, 3, |
2345 locs()); | 2261 locs()); |
2346 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. | 2262 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
2347 __ popq(result_reg); // Pop instantiated type arguments. | 2263 __ popq(result_reg); // Pop instantiated type arguments. |
2348 __ Bind(&type_arguments_instantiated); | 2264 __ Bind(&type_arguments_instantiated); |
2349 } | 2265 } |
2350 | 2266 |
2351 | |
2352 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2267 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2353 Zone* zone, | 2268 Zone* zone, |
2354 bool opt) const { | 2269 bool opt) const { |
2355 ASSERT(opt); | 2270 ASSERT(opt); |
2356 const intptr_t kNumInputs = 0; | 2271 const intptr_t kNumInputs = 0; |
2357 const intptr_t kNumTemps = 2; | 2272 const intptr_t kNumTemps = 2; |
2358 LocationSummary* locs = new (zone) LocationSummary( | 2273 LocationSummary* locs = new (zone) LocationSummary( |
2359 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2274 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2360 locs->set_temp(0, Location::RegisterLocation(R10)); | 2275 locs->set_temp(0, Location::RegisterLocation(R10)); |
2361 locs->set_temp(1, Location::RegisterLocation(R13)); | 2276 locs->set_temp(1, Location::RegisterLocation(R13)); |
2362 locs->set_out(0, Location::RegisterLocation(RAX)); | 2277 locs->set_out(0, Location::RegisterLocation(RAX)); |
2363 return locs; | 2278 return locs; |
2364 } | 2279 } |
2365 | 2280 |
2366 | |
2367 class AllocateContextSlowPath : public SlowPathCode { | 2281 class AllocateContextSlowPath : public SlowPathCode { |
2368 public: | 2282 public: |
2369 explicit AllocateContextSlowPath( | 2283 explicit AllocateContextSlowPath( |
2370 AllocateUninitializedContextInstr* instruction) | 2284 AllocateUninitializedContextInstr* instruction) |
2371 : instruction_(instruction) {} | 2285 : instruction_(instruction) {} |
2372 | 2286 |
2373 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2287 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2374 __ Comment("AllocateContextSlowPath"); | 2288 __ Comment("AllocateContextSlowPath"); |
2375 __ Bind(entry_label()); | 2289 __ Bind(entry_label()); |
2376 | 2290 |
(...skipping 11 matching lines...) Expand all Loading... |
2388 RawPcDescriptors::kOther, locs); | 2302 RawPcDescriptors::kOther, locs); |
2389 ASSERT(instruction_->locs()->out(0).reg() == RAX); | 2303 ASSERT(instruction_->locs()->out(0).reg() == RAX); |
2390 compiler->RestoreLiveRegisters(instruction_->locs()); | 2304 compiler->RestoreLiveRegisters(instruction_->locs()); |
2391 __ jmp(exit_label()); | 2305 __ jmp(exit_label()); |
2392 } | 2306 } |
2393 | 2307 |
2394 private: | 2308 private: |
2395 AllocateUninitializedContextInstr* instruction_; | 2309 AllocateUninitializedContextInstr* instruction_; |
2396 }; | 2310 }; |
2397 | 2311 |
2398 | |
2399 void AllocateUninitializedContextInstr::EmitNativeCode( | 2312 void AllocateUninitializedContextInstr::EmitNativeCode( |
2400 FlowGraphCompiler* compiler) { | 2313 FlowGraphCompiler* compiler) { |
2401 ASSERT(compiler->is_optimizing()); | 2314 ASSERT(compiler->is_optimizing()); |
2402 Register temp = locs()->temp(0).reg(); | 2315 Register temp = locs()->temp(0).reg(); |
2403 Register result = locs()->out(0).reg(); | 2316 Register result = locs()->out(0).reg(); |
2404 // Try allocate the object. | 2317 // Try allocate the object. |
2405 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2318 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2406 compiler->AddSlowPathCode(slow_path); | 2319 compiler->AddSlowPathCode(slow_path); |
2407 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2320 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2408 | 2321 |
2409 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2322 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2410 Assembler::kFarJump, | 2323 Assembler::kFarJump, |
2411 result, // instance | 2324 result, // instance |
2412 temp, // end address | 2325 temp, // end address |
2413 locs()->temp(1).reg()); | 2326 locs()->temp(1).reg()); |
2414 | 2327 |
2415 // Setup up number of context variables field. | 2328 // Setup up number of context variables field. |
2416 __ movq(FieldAddress(result, Context::num_variables_offset()), | 2329 __ movq(FieldAddress(result, Context::num_variables_offset()), |
2417 Immediate(num_context_variables())); | 2330 Immediate(num_context_variables())); |
2418 | 2331 |
2419 __ Bind(slow_path->exit_label()); | 2332 __ Bind(slow_path->exit_label()); |
2420 } | 2333 } |
2421 | 2334 |
2422 | |
2423 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2335 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2424 bool opt) const { | 2336 bool opt) const { |
2425 const intptr_t kNumInputs = 0; | 2337 const intptr_t kNumInputs = 0; |
2426 const intptr_t kNumTemps = 1; | 2338 const intptr_t kNumTemps = 1; |
2427 LocationSummary* locs = new (zone) | 2339 LocationSummary* locs = new (zone) |
2428 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2340 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2429 locs->set_temp(0, Location::RegisterLocation(R10)); | 2341 locs->set_temp(0, Location::RegisterLocation(R10)); |
2430 locs->set_out(0, Location::RegisterLocation(RAX)); | 2342 locs->set_out(0, Location::RegisterLocation(RAX)); |
2431 return locs; | 2343 return locs; |
2432 } | 2344 } |
2433 | 2345 |
2434 | |
2435 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2436 ASSERT(locs()->temp(0).reg() == R10); | 2347 ASSERT(locs()->temp(0).reg() == R10); |
2437 ASSERT(locs()->out(0).reg() == RAX); | 2348 ASSERT(locs()->out(0).reg() == RAX); |
2438 | 2349 |
2439 __ LoadImmediate(R10, Immediate(num_context_variables())); | 2350 __ LoadImmediate(R10, Immediate(num_context_variables())); |
2440 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 2351 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2441 RawPcDescriptors::kOther, locs()); | 2352 RawPcDescriptors::kOther, locs()); |
2442 } | 2353 } |
2443 | 2354 |
2444 | |
2445 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2355 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2446 bool opt) const { | 2356 bool opt) const { |
2447 const intptr_t kNumInputs = 1; | 2357 const intptr_t kNumInputs = 1; |
2448 const intptr_t kNumTemps = 1; | 2358 const intptr_t kNumTemps = 1; |
2449 LocationSummary* locs = new (zone) | 2359 LocationSummary* locs = new (zone) |
2450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2360 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2451 locs->set_in(0, Location::RegisterLocation(RAX)); | 2361 locs->set_in(0, Location::RegisterLocation(RAX)); |
2452 locs->set_temp(0, Location::RegisterLocation(RCX)); | 2362 locs->set_temp(0, Location::RegisterLocation(RCX)); |
2453 return locs; | 2363 return locs; |
2454 } | 2364 } |
2455 | 2365 |
2456 | |
2457 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2366 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2458 Register field = locs()->in(0).reg(); | 2367 Register field = locs()->in(0).reg(); |
2459 Register temp = locs()->temp(0).reg(); | 2368 Register temp = locs()->temp(0).reg(); |
2460 | 2369 |
2461 Label call_runtime, no_call; | 2370 Label call_runtime, no_call; |
2462 | 2371 |
2463 __ movq(temp, FieldAddress(field, Field::static_value_offset())); | 2372 __ movq(temp, FieldAddress(field, Field::static_value_offset())); |
2464 __ CompareObject(temp, Object::sentinel()); | 2373 __ CompareObject(temp, Object::sentinel()); |
2465 __ j(EQUAL, &call_runtime); | 2374 __ j(EQUAL, &call_runtime); |
2466 | 2375 |
2467 __ CompareObject(temp, Object::transition_sentinel()); | 2376 __ CompareObject(temp, Object::transition_sentinel()); |
2468 __ j(NOT_EQUAL, &no_call); | 2377 __ j(NOT_EQUAL, &no_call); |
2469 | 2378 |
2470 __ Bind(&call_runtime); | 2379 __ Bind(&call_runtime); |
2471 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2380 __ PushObject(Object::null_object()); // Make room for (unused) result. |
2472 __ pushq(field); | 2381 __ pushq(field); |
2473 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2382 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2474 kInitStaticFieldRuntimeEntry, 1, locs()); | 2383 kInitStaticFieldRuntimeEntry, 1, locs()); |
2475 __ Drop(2); // Remove argument and unused result. | 2384 __ Drop(2); // Remove argument and unused result. |
2476 __ Bind(&no_call); | 2385 __ Bind(&no_call); |
2477 } | 2386 } |
2478 | 2387 |
2479 | |
2480 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2388 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2481 bool opt) const { | 2389 bool opt) const { |
2482 const intptr_t kNumInputs = 1; | 2390 const intptr_t kNumInputs = 1; |
2483 const intptr_t kNumTemps = 0; | 2391 const intptr_t kNumTemps = 0; |
2484 LocationSummary* locs = new (zone) | 2392 LocationSummary* locs = new (zone) |
2485 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2393 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2486 locs->set_in(0, Location::RegisterLocation(RAX)); | 2394 locs->set_in(0, Location::RegisterLocation(RAX)); |
2487 locs->set_out(0, Location::RegisterLocation(RAX)); | 2395 locs->set_out(0, Location::RegisterLocation(RAX)); |
2488 return locs; | 2396 return locs; |
2489 } | 2397 } |
2490 | 2398 |
2491 | |
2492 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2399 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2493 Register context_value = locs()->in(0).reg(); | 2400 Register context_value = locs()->in(0).reg(); |
2494 Register result = locs()->out(0).reg(); | 2401 Register result = locs()->out(0).reg(); |
2495 | 2402 |
2496 __ PushObject(Object::null_object()); // Make room for the result. | 2403 __ PushObject(Object::null_object()); // Make room for the result. |
2497 __ pushq(context_value); | 2404 __ pushq(context_value); |
2498 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2405 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2499 kCloneContextRuntimeEntry, 1, locs()); | 2406 kCloneContextRuntimeEntry, 1, locs()); |
2500 __ popq(result); // Remove argument. | 2407 __ popq(result); // Remove argument. |
2501 __ popq(result); // Get result (cloned context). | 2408 __ popq(result); // Get result (cloned context). |
2502 } | 2409 } |
2503 | 2410 |
2504 | |
2505 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2411 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2506 bool opt) const { | 2412 bool opt) const { |
2507 UNREACHABLE(); | 2413 UNREACHABLE(); |
2508 return NULL; | 2414 return NULL; |
2509 } | 2415 } |
2510 | 2416 |
2511 | |
2512 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2417 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2513 __ Bind(compiler->GetJumpLabel(this)); | 2418 __ Bind(compiler->GetJumpLabel(this)); |
2514 compiler->AddExceptionHandler(catch_try_index(), try_index(), | 2419 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2515 compiler->assembler()->CodeSize(), | 2420 compiler->assembler()->CodeSize(), |
2516 handler_token_pos(), is_generated(), | 2421 handler_token_pos(), is_generated(), |
2517 catch_handler_types_, needs_stacktrace()); | 2422 catch_handler_types_, needs_stacktrace()); |
2518 // On lazy deoptimization we patch the optimized code here to enter the | 2423 // On lazy deoptimization we patch the optimized code here to enter the |
2519 // deoptimization stub. | 2424 // deoptimization stub. |
2520 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2425 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2521 if (compiler->is_optimizing()) { | 2426 if (compiler->is_optimizing()) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2574 FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())), | 2479 FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())), |
2575 kStackTraceObjectReg); | 2480 kStackTraceObjectReg); |
2576 } else { | 2481 } else { |
2577 __ movq(Address(RBP, exception_var().index() * kWordSize), | 2482 __ movq(Address(RBP, exception_var().index() * kWordSize), |
2578 kExceptionObjectReg); | 2483 kExceptionObjectReg); |
2579 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 2484 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
2580 kStackTraceObjectReg); | 2485 kStackTraceObjectReg); |
2581 } | 2486 } |
2582 } | 2487 } |
2583 | 2488 |
2584 | |
2585 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2489 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2586 bool opt) const { | 2490 bool opt) const { |
2587 const intptr_t kNumInputs = 0; | 2491 const intptr_t kNumInputs = 0; |
2588 const intptr_t kNumTemps = 1; | 2492 const intptr_t kNumTemps = 1; |
2589 LocationSummary* summary = new (zone) LocationSummary( | 2493 LocationSummary* summary = new (zone) LocationSummary( |
2590 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2494 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2591 summary->set_temp(0, Location::RequiresRegister()); | 2495 summary->set_temp(0, Location::RequiresRegister()); |
2592 return summary; | 2496 return summary; |
2593 } | 2497 } |
2594 | 2498 |
2595 | |
2596 class CheckStackOverflowSlowPath : public SlowPathCode { | 2499 class CheckStackOverflowSlowPath : public SlowPathCode { |
2597 public: | 2500 public: |
2598 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2501 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2599 : instruction_(instruction) {} | 2502 : instruction_(instruction) {} |
2600 | 2503 |
2601 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2504 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2602 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { | 2505 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { |
2603 __ Comment("CheckStackOverflowSlowPathOsr"); | 2506 __ Comment("CheckStackOverflowSlowPathOsr"); |
2604 __ Bind(osr_entry_label()); | 2507 __ Bind(osr_entry_label()); |
2605 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), | 2508 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), |
(...skipping 16 matching lines...) Expand all Loading... |
2622 // In unoptimized code, record loop stack checks as possible OSR entries. | 2525 // In unoptimized code, record loop stack checks as possible OSR entries. |
2623 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2526 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
2624 instruction_->deopt_id(), | 2527 instruction_->deopt_id(), |
2625 TokenPosition::kNoSource); | 2528 TokenPosition::kNoSource); |
2626 } | 2529 } |
2627 compiler->pending_deoptimization_env_ = NULL; | 2530 compiler->pending_deoptimization_env_ = NULL; |
2628 compiler->RestoreLiveRegisters(instruction_->locs()); | 2531 compiler->RestoreLiveRegisters(instruction_->locs()); |
2629 __ jmp(exit_label()); | 2532 __ jmp(exit_label()); |
2630 } | 2533 } |
2631 | 2534 |
2632 | |
2633 Label* osr_entry_label() { | 2535 Label* osr_entry_label() { |
2634 ASSERT(Isolate::Current()->use_osr()); | 2536 ASSERT(Isolate::Current()->use_osr()); |
2635 return &osr_entry_label_; | 2537 return &osr_entry_label_; |
2636 } | 2538 } |
2637 | 2539 |
2638 private: | 2540 private: |
2639 CheckStackOverflowInstr* instruction_; | 2541 CheckStackOverflowInstr* instruction_; |
2640 Label osr_entry_label_; | 2542 Label osr_entry_label_; |
2641 }; | 2543 }; |
2642 | 2544 |
2643 | |
2644 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2545 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2645 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2546 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
2646 compiler->AddSlowPathCode(slow_path); | 2547 compiler->AddSlowPathCode(slow_path); |
2647 | 2548 |
2648 Register temp = locs()->temp(0).reg(); | 2549 Register temp = locs()->temp(0).reg(); |
2649 // Generate stack overflow check. | 2550 // Generate stack overflow check. |
2650 __ cmpq(RSP, Address(THR, Thread::stack_limit_offset())); | 2551 __ cmpq(RSP, Address(THR, Thread::stack_limit_offset())); |
2651 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2552 __ j(BELOW_EQUAL, slow_path->entry_label()); |
2652 if (compiler->CanOSRFunction() && in_loop()) { | 2553 if (compiler->CanOSRFunction() && in_loop()) { |
2653 // In unoptimized code check the usage counter to trigger OSR at loop | 2554 // In unoptimized code check the usage counter to trigger OSR at loop |
2654 // stack checks. Use progressively higher thresholds for more deeply | 2555 // stack checks. Use progressively higher thresholds for more deeply |
2655 // nested loops to attempt to hit outer loops with OSR when possible. | 2556 // nested loops to attempt to hit outer loops with OSR when possible. |
2656 __ LoadObject(temp, compiler->parsed_function().function()); | 2557 __ LoadObject(temp, compiler->parsed_function().function()); |
2657 int32_t threshold = | 2558 int32_t threshold = |
2658 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2559 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2659 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), | 2560 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), |
2660 Immediate(threshold)); | 2561 Immediate(threshold)); |
2661 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2562 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
2662 } | 2563 } |
2663 if (compiler->ForceSlowPathForStackOverflow()) { | 2564 if (compiler->ForceSlowPathForStackOverflow()) { |
2664 __ jmp(slow_path->entry_label()); | 2565 __ jmp(slow_path->entry_label()); |
2665 } | 2566 } |
2666 __ Bind(slow_path->exit_label()); | 2567 __ Bind(slow_path->exit_label()); |
2667 } | 2568 } |
2668 | 2569 |
2669 | |
2670 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2570 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2671 BinarySmiOpInstr* shift_left) { | 2571 BinarySmiOpInstr* shift_left) { |
2672 const LocationSummary& locs = *shift_left->locs(); | 2572 const LocationSummary& locs = *shift_left->locs(); |
2673 Register left = locs.in(0).reg(); | 2573 Register left = locs.in(0).reg(); |
2674 Register result = locs.out(0).reg(); | 2574 Register result = locs.out(0).reg(); |
2675 ASSERT(left == result); | 2575 ASSERT(left == result); |
2676 Label* deopt = shift_left->CanDeoptimize() | 2576 Label* deopt = shift_left->CanDeoptimize() |
2677 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 2577 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
2678 ICData::kDeoptBinarySmiOp) | 2578 ICData::kDeoptBinarySmiOp) |
2679 : NULL; | 2579 : NULL; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 // Overflow test (preserve temp and right); | 2673 // Overflow test (preserve temp and right); |
2774 __ shlq(left, right); | 2674 __ shlq(left, right); |
2775 __ sarq(left, right); | 2675 __ sarq(left, right); |
2776 __ cmpq(left, temp); | 2676 __ cmpq(left, temp); |
2777 __ j(NOT_EQUAL, deopt); // Overflow. | 2677 __ j(NOT_EQUAL, deopt); // Overflow. |
2778 // Shift for result now we know there is no overflow. | 2678 // Shift for result now we know there is no overflow. |
2779 __ shlq(left, right); | 2679 __ shlq(left, right); |
2780 } | 2680 } |
2781 } | 2681 } |
2782 | 2682 |
2783 | |
2784 class CheckedSmiSlowPath : public SlowPathCode { | 2683 class CheckedSmiSlowPath : public SlowPathCode { |
2785 public: | 2684 public: |
2786 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2685 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
2787 : instruction_(instruction), try_index_(try_index) {} | 2686 : instruction_(instruction), try_index_(try_index) {} |
2788 | 2687 |
2789 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2688 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2790 if (Assembler::EmittingComments()) { | 2689 if (Assembler::EmittingComments()) { |
2791 __ Comment("slow path smi operation"); | 2690 __ Comment("slow path smi operation"); |
2792 } | 2691 } |
2793 __ Bind(entry_label()); | 2692 __ Bind(entry_label()); |
(...skipping 21 matching lines...) Expand all Loading... |
2815 compiler->RestoreLiveRegisters(locs); | 2714 compiler->RestoreLiveRegisters(locs); |
2816 __ jmp(exit_label()); | 2715 __ jmp(exit_label()); |
2817 compiler->pending_deoptimization_env_ = NULL; | 2716 compiler->pending_deoptimization_env_ = NULL; |
2818 } | 2717 } |
2819 | 2718 |
2820 private: | 2719 private: |
2821 CheckedSmiOpInstr* instruction_; | 2720 CheckedSmiOpInstr* instruction_; |
2822 intptr_t try_index_; | 2721 intptr_t try_index_; |
2823 }; | 2722 }; |
2824 | 2723 |
2825 | |
2826 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2724 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
2827 bool opt) const { | 2725 bool opt) const { |
2828 bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR); | 2726 bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR); |
2829 const intptr_t kNumInputs = 2; | 2727 const intptr_t kNumInputs = 2; |
2830 const intptr_t kNumTemps = is_shift ? 1 : 0; | 2728 const intptr_t kNumTemps = is_shift ? 1 : 0; |
2831 LocationSummary* summary = new (zone) LocationSummary( | 2729 LocationSummary* summary = new (zone) LocationSummary( |
2832 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2730 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2833 summary->set_in(0, Location::RequiresRegister()); | 2731 summary->set_in(0, Location::RequiresRegister()); |
2834 summary->set_in(1, Location::RequiresRegister()); | 2732 summary->set_in(1, Location::RequiresRegister()); |
2835 switch (op_kind()) { | 2733 switch (op_kind()) { |
(...skipping 11 matching lines...) Expand all Loading... |
2847 break; | 2745 break; |
2848 default: | 2746 default: |
2849 UNIMPLEMENTED(); | 2747 UNIMPLEMENTED(); |
2850 } | 2748 } |
2851 if (is_shift) { | 2749 if (is_shift) { |
2852 summary->set_temp(0, Location::RegisterLocation(RCX)); | 2750 summary->set_temp(0, Location::RegisterLocation(RCX)); |
2853 } | 2751 } |
2854 return summary; | 2752 return summary; |
2855 } | 2753 } |
2856 | 2754 |
2857 | |
2858 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2755 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2859 CheckedSmiSlowPath* slow_path = | 2756 CheckedSmiSlowPath* slow_path = |
2860 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); | 2757 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); |
2861 compiler->AddSlowPathCode(slow_path); | 2758 compiler->AddSlowPathCode(slow_path); |
2862 // Test operands if necessary. | 2759 // Test operands if necessary. |
2863 | 2760 |
2864 intptr_t left_cid = left()->Type()->ToCid(); | 2761 intptr_t left_cid = left()->Type()->ToCid(); |
2865 intptr_t right_cid = right()->Type()->ToCid(); | 2762 intptr_t right_cid = right()->Type()->ToCid(); |
2866 Register left = locs()->in(0).reg(); | 2763 Register left = locs()->in(0).reg(); |
2867 Register right = locs()->in(1).reg(); | 2764 Register right = locs()->in(1).reg(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2936 __ sarq(result, RCX); | 2833 __ sarq(result, RCX); |
2937 __ SmiTag(result); | 2834 __ SmiTag(result); |
2938 break; | 2835 break; |
2939 } | 2836 } |
2940 default: | 2837 default: |
2941 UNIMPLEMENTED(); | 2838 UNIMPLEMENTED(); |
2942 } | 2839 } |
2943 __ Bind(slow_path->exit_label()); | 2840 __ Bind(slow_path->exit_label()); |
2944 } | 2841 } |
2945 | 2842 |
2946 | |
2947 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2843 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
2948 public: | 2844 public: |
2949 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2845 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
2950 intptr_t try_index, | 2846 intptr_t try_index, |
2951 BranchLabels labels, | 2847 BranchLabels labels, |
2952 bool merged = false) | 2848 bool merged = false) |
2953 : instruction_(instruction), | 2849 : instruction_(instruction), |
2954 try_index_(try_index), | 2850 try_index_(try_index), |
2955 labels_(labels), | 2851 labels_(labels), |
2956 merged_(merged) {} | 2852 merged_(merged) {} |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2994 } | 2890 } |
2995 } | 2891 } |
2996 | 2892 |
2997 private: | 2893 private: |
2998 CheckedSmiComparisonInstr* instruction_; | 2894 CheckedSmiComparisonInstr* instruction_; |
2999 intptr_t try_index_; | 2895 intptr_t try_index_; |
3000 BranchLabels labels_; | 2896 BranchLabels labels_; |
3001 bool merged_; | 2897 bool merged_; |
3002 }; | 2898 }; |
3003 | 2899 |
3004 | |
3005 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2900 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
3006 Zone* zone, | 2901 Zone* zone, |
3007 bool opt) const { | 2902 bool opt) const { |
3008 const intptr_t kNumInputs = 2; | 2903 const intptr_t kNumInputs = 2; |
3009 const intptr_t kNumTemps = 1; | 2904 const intptr_t kNumTemps = 1; |
3010 LocationSummary* summary = new (zone) LocationSummary( | 2905 LocationSummary* summary = new (zone) LocationSummary( |
3011 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2906 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3012 summary->set_in(0, Location::RequiresRegister()); | 2907 summary->set_in(0, Location::RequiresRegister()); |
3013 summary->set_in(1, Location::RequiresRegister()); | 2908 summary->set_in(1, Location::RequiresRegister()); |
3014 summary->set_temp(0, Location::RequiresRegister()); | 2909 summary->set_temp(0, Location::RequiresRegister()); |
3015 summary->set_out(0, Location::RequiresRegister()); | 2910 summary->set_out(0, Location::RequiresRegister()); |
3016 return summary; | 2911 return summary; |
3017 } | 2912 } |
3018 | 2913 |
3019 | |
3020 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2914 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
3021 FlowGraphCompiler* compiler, | 2915 FlowGraphCompiler* compiler, |
3022 BranchLabels labels) { | 2916 BranchLabels labels) { |
3023 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 2917 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
3024 } | 2918 } |
3025 | 2919 |
3026 | |
3027 #define EMIT_SMI_CHECK \ | 2920 #define EMIT_SMI_CHECK \ |
3028 intptr_t left_cid = left()->Type()->ToCid(); \ | 2921 intptr_t left_cid = left()->Type()->ToCid(); \ |
3029 intptr_t right_cid = right()->Type()->ToCid(); \ | 2922 intptr_t right_cid = right()->Type()->ToCid(); \ |
3030 Register left = locs()->in(0).reg(); \ | 2923 Register left = locs()->in(0).reg(); \ |
3031 Register right = locs()->in(1).reg(); \ | 2924 Register right = locs()->in(1).reg(); \ |
3032 if (this->left()->definition() == this->right()->definition()) { \ | 2925 if (this->left()->definition() == this->right()->definition()) { \ |
3033 __ testq(left, Immediate(kSmiTagMask)); \ | 2926 __ testq(left, Immediate(kSmiTagMask)); \ |
3034 } else if (left_cid == kSmiCid) { \ | 2927 } else if (left_cid == kSmiCid) { \ |
3035 __ testq(right, Immediate(kSmiTagMask)); \ | 2928 __ testq(right, Immediate(kSmiTagMask)); \ |
3036 } else if (right_cid == kSmiCid) { \ | 2929 } else if (right_cid == kSmiCid) { \ |
3037 __ testq(left, Immediate(kSmiTagMask)); \ | 2930 __ testq(left, Immediate(kSmiTagMask)); \ |
3038 } else { \ | 2931 } else { \ |
3039 __ movq(TMP, left); \ | 2932 __ movq(TMP, left); \ |
3040 __ orq(TMP, right); \ | 2933 __ orq(TMP, right); \ |
3041 __ testq(TMP, Immediate(kSmiTagMask)); \ | 2934 __ testq(TMP, Immediate(kSmiTagMask)); \ |
3042 } \ | 2935 } \ |
3043 __ j(NOT_ZERO, slow_path->entry_label()) | 2936 __ j(NOT_ZERO, slow_path->entry_label()) |
3044 | 2937 |
3045 | |
3046 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2938 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3047 BranchInstr* branch) { | 2939 BranchInstr* branch) { |
3048 BranchLabels labels = compiler->CreateBranchLabels(branch); | 2940 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3049 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2941 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3050 this, compiler->CurrentTryIndex(), labels, | 2942 this, compiler->CurrentTryIndex(), labels, |
3051 /* merged = */ true); | 2943 /* merged = */ true); |
3052 compiler->AddSlowPathCode(slow_path); | 2944 compiler->AddSlowPathCode(slow_path); |
3053 EMIT_SMI_CHECK; | 2945 EMIT_SMI_CHECK; |
3054 Condition true_condition = EmitComparisonCode(compiler, labels); | 2946 Condition true_condition = EmitComparisonCode(compiler, labels); |
3055 ASSERT(true_condition != INVALID_CONDITION); | 2947 ASSERT(true_condition != INVALID_CONDITION); |
3056 EmitBranchOnCondition(compiler, true_condition, labels); | 2948 EmitBranchOnCondition(compiler, true_condition, labels); |
3057 __ Bind(slow_path->exit_label()); | 2949 __ Bind(slow_path->exit_label()); |
3058 } | 2950 } |
3059 | 2951 |
3060 | |
3061 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2952 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3062 Label true_label, false_label, done; | 2953 Label true_label, false_label, done; |
3063 BranchLabels labels = {&true_label, &false_label, &false_label}; | 2954 BranchLabels labels = {&true_label, &false_label, &false_label}; |
3064 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2955 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3065 this, compiler->CurrentTryIndex(), labels, | 2956 this, compiler->CurrentTryIndex(), labels, |
3066 /* merged = */ false); | 2957 /* merged = */ false); |
3067 compiler->AddSlowPathCode(slow_path); | 2958 compiler->AddSlowPathCode(slow_path); |
3068 EMIT_SMI_CHECK; | 2959 EMIT_SMI_CHECK; |
3069 Condition true_condition = EmitComparisonCode(compiler, labels); | 2960 Condition true_condition = EmitComparisonCode(compiler, labels); |
3070 ASSERT(true_condition != INVALID_CONDITION); | 2961 ASSERT(true_condition != INVALID_CONDITION); |
3071 EmitBranchOnCondition(compiler, true_condition, labels); | 2962 EmitBranchOnCondition(compiler, true_condition, labels); |
3072 Register result = locs()->out(0).reg(); | 2963 Register result = locs()->out(0).reg(); |
3073 __ Bind(&false_label); | 2964 __ Bind(&false_label); |
3074 __ LoadObject(result, Bool::False()); | 2965 __ LoadObject(result, Bool::False()); |
3075 __ jmp(&done); | 2966 __ jmp(&done); |
3076 __ Bind(&true_label); | 2967 __ Bind(&true_label); |
3077 __ LoadObject(result, Bool::True()); | 2968 __ LoadObject(result, Bool::True()); |
3078 __ Bind(&done); | 2969 __ Bind(&done); |
3079 __ Bind(slow_path->exit_label()); | 2970 __ Bind(slow_path->exit_label()); |
3080 } | 2971 } |
3081 | 2972 |
3082 | |
3083 static bool CanBeImmediate(const Object& constant) { | 2973 static bool CanBeImmediate(const Object& constant) { |
3084 return constant.IsSmi() && | 2974 return constant.IsSmi() && |
3085 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 2975 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
3086 } | 2976 } |
3087 | 2977 |
3088 static bool IsSmiValue(const Object& constant, intptr_t value) { | 2978 static bool IsSmiValue(const Object& constant, intptr_t value) { |
3089 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 2979 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
3090 } | 2980 } |
3091 | 2981 |
3092 | |
3093 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2982 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3094 bool opt) const { | 2983 bool opt) const { |
3095 const intptr_t kNumInputs = 2; | 2984 const intptr_t kNumInputs = 2; |
3096 | 2985 |
3097 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2986 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
3098 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && | 2987 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && |
3099 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && | 2988 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && |
3100 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { | 2989 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { |
3101 const intptr_t kNumTemps = 0; | 2990 const intptr_t kNumTemps = 0; |
3102 LocationSummary* summary = new (zone) | 2991 LocationSummary* summary = new (zone) |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3257 break; | 3146 break; |
3258 } | 3147 } |
3259 | 3148 |
3260 default: | 3149 default: |
3261 UNREACHABLE(); | 3150 UNREACHABLE(); |
3262 break; | 3151 break; |
3263 } | 3152 } |
3264 return; | 3153 return; |
3265 } // locs()->in(1).IsConstant(). | 3154 } // locs()->in(1).IsConstant(). |
3266 | 3155 |
3267 | |
3268 if (locs()->in(1).IsStackSlot()) { | 3156 if (locs()->in(1).IsStackSlot()) { |
3269 const Address& right = locs()->in(1).ToStackSlotAddress(); | 3157 const Address& right = locs()->in(1).ToStackSlotAddress(); |
3270 switch (op_kind()) { | 3158 switch (op_kind()) { |
3271 case Token::kADD: { | 3159 case Token::kADD: { |
3272 __ addq(left, right); | 3160 __ addq(left, right); |
3273 if (deopt != NULL) __ j(OVERFLOW, deopt); | 3161 if (deopt != NULL) __ j(OVERFLOW, deopt); |
3274 break; | 3162 break; |
3275 } | 3163 } |
3276 case Token::kSUB: { | 3164 case Token::kSUB: { |
3277 __ subq(left, right); | 3165 __ subq(left, right); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3492 // behavior (short-circuit evaluation). | 3380 // behavior (short-circuit evaluation). |
3493 UNREACHABLE(); | 3381 UNREACHABLE(); |
3494 break; | 3382 break; |
3495 } | 3383 } |
3496 default: | 3384 default: |
3497 UNREACHABLE(); | 3385 UNREACHABLE(); |
3498 break; | 3386 break; |
3499 } | 3387 } |
3500 } | 3388 } |
3501 | 3389 |
3502 | |
3503 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3390 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3504 bool opt) const { | 3391 bool opt) const { |
3505 intptr_t left_cid = left()->Type()->ToCid(); | 3392 intptr_t left_cid = left()->Type()->ToCid(); |
3506 intptr_t right_cid = right()->Type()->ToCid(); | 3393 intptr_t right_cid = right()->Type()->ToCid(); |
3507 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3394 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3508 const intptr_t kNumInputs = 2; | 3395 const intptr_t kNumInputs = 2; |
3509 const bool need_temp = (left()->definition() != right()->definition()) && | 3396 const bool need_temp = (left()->definition() != right()->definition()) && |
3510 (left_cid != kSmiCid) && (right_cid != kSmiCid); | 3397 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
3511 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3398 const intptr_t kNumTemps = need_temp ? 1 : 0; |
3512 LocationSummary* summary = new (zone) | 3399 LocationSummary* summary = new (zone) |
3513 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3400 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3514 summary->set_in(0, Location::RequiresRegister()); | 3401 summary->set_in(0, Location::RequiresRegister()); |
3515 summary->set_in(1, Location::RequiresRegister()); | 3402 summary->set_in(1, Location::RequiresRegister()); |
3516 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3403 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
3517 return summary; | 3404 return summary; |
3518 } | 3405 } |
3519 | 3406 |
3520 | |
3521 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3407 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3522 Label* deopt = | 3408 Label* deopt = |
3523 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 3409 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3524 licm_hoisted_ ? ICData::kHoisted : 0); | 3410 licm_hoisted_ ? ICData::kHoisted : 0); |
3525 intptr_t left_cid = left()->Type()->ToCid(); | 3411 intptr_t left_cid = left()->Type()->ToCid(); |
3526 intptr_t right_cid = right()->Type()->ToCid(); | 3412 intptr_t right_cid = right()->Type()->ToCid(); |
3527 Register left = locs()->in(0).reg(); | 3413 Register left = locs()->in(0).reg(); |
3528 Register right = locs()->in(1).reg(); | 3414 Register right = locs()->in(1).reg(); |
3529 if (this->left()->definition() == this->right()->definition()) { | 3415 if (this->left()->definition() == this->right()->definition()) { |
3530 __ testq(left, Immediate(kSmiTagMask)); | 3416 __ testq(left, Immediate(kSmiTagMask)); |
3531 } else if (left_cid == kSmiCid) { | 3417 } else if (left_cid == kSmiCid) { |
3532 __ testq(right, Immediate(kSmiTagMask)); | 3418 __ testq(right, Immediate(kSmiTagMask)); |
3533 } else if (right_cid == kSmiCid) { | 3419 } else if (right_cid == kSmiCid) { |
3534 __ testq(left, Immediate(kSmiTagMask)); | 3420 __ testq(left, Immediate(kSmiTagMask)); |
3535 } else { | 3421 } else { |
3536 Register temp = locs()->temp(0).reg(); | 3422 Register temp = locs()->temp(0).reg(); |
3537 __ movq(temp, left); | 3423 __ movq(temp, left); |
3538 __ orq(temp, right); | 3424 __ orq(temp, right); |
3539 __ testq(temp, Immediate(kSmiTagMask)); | 3425 __ testq(temp, Immediate(kSmiTagMask)); |
3540 } | 3426 } |
3541 __ j(ZERO, deopt); | 3427 __ j(ZERO, deopt); |
3542 } | 3428 } |
3543 | 3429 |
3544 | |
3545 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3430 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3546 const intptr_t kNumInputs = 1; | 3431 const intptr_t kNumInputs = 1; |
3547 const intptr_t kNumTemps = 1; | 3432 const intptr_t kNumTemps = 1; |
3548 LocationSummary* summary = new (zone) LocationSummary( | 3433 LocationSummary* summary = new (zone) LocationSummary( |
3549 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3434 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3550 summary->set_in(0, Location::RequiresFpuRegister()); | 3435 summary->set_in(0, Location::RequiresFpuRegister()); |
3551 summary->set_temp(0, Location::RequiresRegister()); | 3436 summary->set_temp(0, Location::RequiresRegister()); |
3552 summary->set_out(0, Location::RequiresRegister()); | 3437 summary->set_out(0, Location::RequiresRegister()); |
3553 return summary; | 3438 return summary; |
3554 } | 3439 } |
3555 | 3440 |
3556 | |
3557 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3441 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3558 Register out_reg = locs()->out(0).reg(); | 3442 Register out_reg = locs()->out(0).reg(); |
3559 Register temp = locs()->temp(0).reg(); | 3443 Register temp = locs()->temp(0).reg(); |
3560 XmmRegister value = locs()->in(0).fpu_reg(); | 3444 XmmRegister value = locs()->in(0).fpu_reg(); |
3561 | 3445 |
3562 BoxAllocationSlowPath::Allocate(compiler, this, | 3446 BoxAllocationSlowPath::Allocate(compiler, this, |
3563 compiler->BoxClassFor(from_representation()), | 3447 compiler->BoxClassFor(from_representation()), |
3564 out_reg, temp); | 3448 out_reg, temp); |
3565 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 3449 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
3566 switch (from_representation()) { | 3450 switch (from_representation()) { |
3567 case kUnboxedDouble: | 3451 case kUnboxedDouble: |
3568 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3452 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
3569 break; | 3453 break; |
3570 case kUnboxedFloat32x4: | 3454 case kUnboxedFloat32x4: |
3571 case kUnboxedFloat64x2: | 3455 case kUnboxedFloat64x2: |
3572 case kUnboxedInt32x4: | 3456 case kUnboxedInt32x4: |
3573 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3457 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
3574 break; | 3458 break; |
3575 default: | 3459 default: |
3576 UNREACHABLE(); | 3460 UNREACHABLE(); |
3577 break; | 3461 break; |
3578 } | 3462 } |
3579 } | 3463 } |
3580 | 3464 |
3581 | |
3582 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3465 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3583 const intptr_t kNumInputs = 1; | 3466 const intptr_t kNumInputs = 1; |
3584 const intptr_t kNumTemps = 0; | 3467 const intptr_t kNumTemps = 0; |
3585 const bool needs_writable_input = | 3468 const bool needs_writable_input = |
3586 (representation() != kUnboxedMint) && | 3469 (representation() != kUnboxedMint) && |
3587 (value()->Type()->ToNullableCid() != BoxCid()); | 3470 (value()->Type()->ToNullableCid() != BoxCid()); |
3588 LocationSummary* summary = new (zone) | 3471 LocationSummary* summary = new (zone) |
3589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3472 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3590 summary->set_in(0, needs_writable_input ? Location::WritableRegister() | 3473 summary->set_in(0, needs_writable_input ? Location::WritableRegister() |
3591 : Location::RequiresRegister()); | 3474 : Location::RequiresRegister()); |
3592 if (representation() == kUnboxedMint) { | 3475 if (representation() == kUnboxedMint) { |
3593 summary->set_out(0, Location::SameAsFirstInput()); | 3476 summary->set_out(0, Location::SameAsFirstInput()); |
3594 } else { | 3477 } else { |
3595 summary->set_out(0, Location::RequiresFpuRegister()); | 3478 summary->set_out(0, Location::RequiresFpuRegister()); |
3596 } | 3479 } |
3597 return summary; | 3480 return summary; |
3598 } | 3481 } |
3599 | 3482 |
3600 | |
3601 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3483 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
3602 const Register box = locs()->in(0).reg(); | 3484 const Register box = locs()->in(0).reg(); |
3603 | 3485 |
3604 switch (representation()) { | 3486 switch (representation()) { |
3605 case kUnboxedMint: { | 3487 case kUnboxedMint: { |
3606 const Register result = locs()->out(0).reg(); | 3488 const Register result = locs()->out(0).reg(); |
3607 __ movq(result, FieldAddress(box, ValueOffset())); | 3489 __ movq(result, FieldAddress(box, ValueOffset())); |
3608 break; | 3490 break; |
3609 } | 3491 } |
3610 | 3492 |
(...skipping 10 matching lines...) Expand all Loading... |
3621 __ movups(result, FieldAddress(box, ValueOffset())); | 3503 __ movups(result, FieldAddress(box, ValueOffset())); |
3622 break; | 3504 break; |
3623 } | 3505 } |
3624 | 3506 |
3625 default: | 3507 default: |
3626 UNREACHABLE(); | 3508 UNREACHABLE(); |
3627 break; | 3509 break; |
3628 } | 3510 } |
3629 } | 3511 } |
3630 | 3512 |
3631 | |
3632 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3513 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
3633 const Register box = locs()->in(0).reg(); | 3514 const Register box = locs()->in(0).reg(); |
3634 | 3515 |
3635 switch (representation()) { | 3516 switch (representation()) { |
3636 case kUnboxedMint: { | 3517 case kUnboxedMint: { |
3637 const Register result = locs()->out(0).reg(); | 3518 const Register result = locs()->out(0).reg(); |
3638 ASSERT(result == box); | 3519 ASSERT(result == box); |
3639 __ SmiUntag(box); | 3520 __ SmiUntag(box); |
3640 break; | 3521 break; |
3641 } | 3522 } |
3642 | 3523 |
3643 case kUnboxedDouble: { | 3524 case kUnboxedDouble: { |
3644 const FpuRegister result = locs()->out(0).fpu_reg(); | 3525 const FpuRegister result = locs()->out(0).fpu_reg(); |
3645 __ SmiUntag(box); | 3526 __ SmiUntag(box); |
3646 __ cvtsi2sdq(result, box); | 3527 __ cvtsi2sdq(result, box); |
3647 break; | 3528 break; |
3648 } | 3529 } |
3649 | 3530 |
3650 default: | 3531 default: |
3651 UNREACHABLE(); | 3532 UNREACHABLE(); |
3652 break; | 3533 break; |
3653 } | 3534 } |
3654 } | 3535 } |
3655 | 3536 |
3656 | |
3657 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3537 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3658 const intptr_t value_cid = value()->Type()->ToCid(); | 3538 const intptr_t value_cid = value()->Type()->ToCid(); |
3659 const intptr_t box_cid = BoxCid(); | 3539 const intptr_t box_cid = BoxCid(); |
3660 | 3540 |
3661 if (value_cid == box_cid) { | 3541 if (value_cid == box_cid) { |
3662 EmitLoadFromBox(compiler); | 3542 EmitLoadFromBox(compiler); |
3663 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3543 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
3664 EmitSmiConversion(compiler); | 3544 EmitSmiConversion(compiler); |
3665 } else { | 3545 } else { |
3666 const Register box = locs()->in(0).reg(); | 3546 const Register box = locs()->in(0).reg(); |
(...skipping 17 matching lines...) Expand all Loading... |
3684 if (is_smi.IsLinked()) { | 3564 if (is_smi.IsLinked()) { |
3685 Label done; | 3565 Label done; |
3686 __ jmp(&done); | 3566 __ jmp(&done); |
3687 __ Bind(&is_smi); | 3567 __ Bind(&is_smi); |
3688 EmitSmiConversion(compiler); | 3568 EmitSmiConversion(compiler); |
3689 __ Bind(&done); | 3569 __ Bind(&done); |
3690 } | 3570 } |
3691 } | 3571 } |
3692 } | 3572 } |
3693 | 3573 |
3694 | |
3695 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3574 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
3696 bool opt) const { | 3575 bool opt) const { |
3697 const intptr_t kNumInputs = 1; | 3576 const intptr_t kNumInputs = 1; |
3698 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 3577 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
3699 LocationSummary* summary = new (zone) | 3578 LocationSummary* summary = new (zone) |
3700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3579 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3701 summary->set_in(0, Location::RequiresRegister()); | 3580 summary->set_in(0, Location::RequiresRegister()); |
3702 summary->set_out(0, Location::SameAsFirstInput()); | 3581 summary->set_out(0, Location::SameAsFirstInput()); |
3703 if (kNumTemps > 0) { | 3582 if (kNumTemps > 0) { |
3704 summary->set_temp(0, Location::RequiresRegister()); | 3583 summary->set_temp(0, Location::RequiresRegister()); |
3705 } | 3584 } |
3706 return summary; | 3585 return summary; |
3707 } | 3586 } |
3708 | 3587 |
3709 | |
3710 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3588 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3711 const intptr_t value_cid = value()->Type()->ToCid(); | 3589 const intptr_t value_cid = value()->Type()->ToCid(); |
3712 const Register value = locs()->in(0).reg(); | 3590 const Register value = locs()->in(0).reg(); |
3713 Label* deopt = | 3591 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
3714 CanDeoptimize() | 3592 GetDeoptId(), ICData::kDeoptUnboxInteger) |
3715 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 3593 : NULL; |
3716 : NULL; | |
3717 ASSERT(value == locs()->out(0).reg()); | 3594 ASSERT(value == locs()->out(0).reg()); |
3718 | 3595 |
3719 if (value_cid == kSmiCid) { | 3596 if (value_cid == kSmiCid) { |
3720 __ SmiUntag(value); | 3597 __ SmiUntag(value); |
3721 } else if (value_cid == kMintCid) { | 3598 } else if (value_cid == kMintCid) { |
3722 __ movq(value, FieldAddress(value, Mint::value_offset())); | 3599 __ movq(value, FieldAddress(value, Mint::value_offset())); |
3723 } else if (!CanDeoptimize()) { | 3600 } else if (!CanDeoptimize()) { |
3724 // Type information is not conclusive, but range analysis found | 3601 // Type information is not conclusive, but range analysis found |
3725 // the value to be in int64 range. Therefore it must be a smi | 3602 // the value to be in int64 range. Therefore it must be a smi |
3726 // or mint value. | 3603 // or mint value. |
(...skipping 18 matching lines...) Expand all Loading... |
3745 // leave "garbage" in the higher word. | 3622 // leave "garbage" in the higher word. |
3746 if (!is_truncating() && (deopt != NULL)) { | 3623 if (!is_truncating() && (deopt != NULL)) { |
3747 ASSERT(representation() == kUnboxedInt32); | 3624 ASSERT(representation() == kUnboxedInt32); |
3748 Register temp = locs()->temp(0).reg(); | 3625 Register temp = locs()->temp(0).reg(); |
3749 __ movsxd(temp, value); | 3626 __ movsxd(temp, value); |
3750 __ cmpq(temp, value); | 3627 __ cmpq(temp, value); |
3751 __ j(NOT_EQUAL, deopt); | 3628 __ j(NOT_EQUAL, deopt); |
3752 } | 3629 } |
3753 } | 3630 } |
3754 | 3631 |
3755 | |
3756 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3632 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
3757 bool opt) const { | 3633 bool opt) const { |
3758 ASSERT((from_representation() == kUnboxedInt32) || | 3634 ASSERT((from_representation() == kUnboxedInt32) || |
3759 (from_representation() == kUnboxedUint32)); | 3635 (from_representation() == kUnboxedUint32)); |
3760 const intptr_t kNumInputs = 1; | 3636 const intptr_t kNumInputs = 1; |
3761 const intptr_t kNumTemps = 0; | 3637 const intptr_t kNumTemps = 0; |
3762 LocationSummary* summary = new (zone) | 3638 LocationSummary* summary = new (zone) |
3763 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3639 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3764 summary->set_in(0, Location::RequiresRegister()); | 3640 summary->set_in(0, Location::RequiresRegister()); |
3765 summary->set_out(0, Location::RequiresRegister()); | 3641 summary->set_out(0, Location::RequiresRegister()); |
3766 return summary; | 3642 return summary; |
3767 } | 3643 } |
3768 | 3644 |
3769 | |
3770 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3645 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3771 const Register value = locs()->in(0).reg(); | 3646 const Register value = locs()->in(0).reg(); |
3772 const Register out = locs()->out(0).reg(); | 3647 const Register out = locs()->out(0).reg(); |
3773 ASSERT(value != out); | 3648 ASSERT(value != out); |
3774 | 3649 |
3775 ASSERT(kSmiTagSize == 1); | 3650 ASSERT(kSmiTagSize == 1); |
3776 if (from_representation() == kUnboxedInt32) { | 3651 if (from_representation() == kUnboxedInt32) { |
3777 __ movsxd(out, value); | 3652 __ movsxd(out, value); |
3778 } else { | 3653 } else { |
3779 ASSERT(from_representation() == kUnboxedUint32); | 3654 ASSERT(from_representation() == kUnboxedUint32); |
3780 __ movl(out, value); | 3655 __ movl(out, value); |
3781 } | 3656 } |
3782 __ SmiTag(out); | 3657 __ SmiTag(out); |
3783 } | 3658 } |
3784 | 3659 |
3785 | |
3786 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3660 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
3787 bool opt) const { | 3661 bool opt) const { |
3788 const intptr_t kNumInputs = 1; | 3662 const intptr_t kNumInputs = 1; |
3789 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3663 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3790 LocationSummary* summary = new (zone) | 3664 LocationSummary* summary = new (zone) |
3791 LocationSummary(zone, kNumInputs, kNumTemps, | 3665 LocationSummary(zone, kNumInputs, kNumTemps, |
3792 ValueFitsSmi() ? LocationSummary::kNoCall | 3666 ValueFitsSmi() ? LocationSummary::kNoCall |
3793 : LocationSummary::kCallOnSlowPath); | 3667 : LocationSummary::kCallOnSlowPath); |
3794 summary->set_in(0, Location::RequiresRegister()); | 3668 summary->set_in(0, Location::RequiresRegister()); |
3795 if (!ValueFitsSmi()) { | 3669 if (!ValueFitsSmi()) { |
3796 summary->set_temp(0, Location::RequiresRegister()); | 3670 summary->set_temp(0, Location::RequiresRegister()); |
3797 } | 3671 } |
3798 summary->set_out(0, Location::RequiresRegister()); | 3672 summary->set_out(0, Location::RequiresRegister()); |
3799 return summary; | 3673 return summary; |
3800 } | 3674 } |
3801 | 3675 |
3802 | |
3803 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3676 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3804 const Register out = locs()->out(0).reg(); | 3677 const Register out = locs()->out(0).reg(); |
3805 const Register value = locs()->in(0).reg(); | 3678 const Register value = locs()->in(0).reg(); |
3806 __ MoveRegister(out, value); | 3679 __ MoveRegister(out, value); |
3807 __ SmiTag(out); | 3680 __ SmiTag(out); |
3808 if (!ValueFitsSmi()) { | 3681 if (!ValueFitsSmi()) { |
3809 const Register temp = locs()->temp(0).reg(); | 3682 const Register temp = locs()->temp(0).reg(); |
3810 Label done; | 3683 Label done; |
3811 __ j(NO_OVERFLOW, &done); | 3684 __ j(NO_OVERFLOW, &done); |
3812 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, | 3685 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
3813 temp); | 3686 temp); |
3814 __ movq(FieldAddress(out, Mint::value_offset()), value); | 3687 __ movq(FieldAddress(out, Mint::value_offset()), value); |
3815 __ Bind(&done); | 3688 __ Bind(&done); |
3816 } | 3689 } |
3817 } | 3690 } |
3818 | 3691 |
3819 | |
3820 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3692 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
3821 bool opt) const { | 3693 bool opt) const { |
3822 const intptr_t kNumInputs = 2; | 3694 const intptr_t kNumInputs = 2; |
3823 const intptr_t kNumTemps = 0; | 3695 const intptr_t kNumTemps = 0; |
3824 LocationSummary* summary = new (zone) | 3696 LocationSummary* summary = new (zone) |
3825 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3697 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3826 summary->set_in(0, Location::RequiresFpuRegister()); | 3698 summary->set_in(0, Location::RequiresFpuRegister()); |
3827 summary->set_in(1, Location::RequiresFpuRegister()); | 3699 summary->set_in(1, Location::RequiresFpuRegister()); |
3828 summary->set_out(0, Location::SameAsFirstInput()); | 3700 summary->set_out(0, Location::SameAsFirstInput()); |
3829 return summary; | 3701 return summary; |
3830 } | 3702 } |
3831 | 3703 |
3832 | |
3833 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3704 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3834 XmmRegister left = locs()->in(0).fpu_reg(); | 3705 XmmRegister left = locs()->in(0).fpu_reg(); |
3835 XmmRegister right = locs()->in(1).fpu_reg(); | 3706 XmmRegister right = locs()->in(1).fpu_reg(); |
3836 | 3707 |
3837 ASSERT(locs()->out(0).fpu_reg() == left); | 3708 ASSERT(locs()->out(0).fpu_reg() == left); |
3838 | 3709 |
3839 switch (op_kind()) { | 3710 switch (op_kind()) { |
3840 case Token::kADD: | 3711 case Token::kADD: |
3841 __ addsd(left, right); | 3712 __ addsd(left, right); |
3842 break; | 3713 break; |
3843 case Token::kSUB: | 3714 case Token::kSUB: |
3844 __ subsd(left, right); | 3715 __ subsd(left, right); |
3845 break; | 3716 break; |
3846 case Token::kMUL: | 3717 case Token::kMUL: |
3847 __ mulsd(left, right); | 3718 __ mulsd(left, right); |
3848 break; | 3719 break; |
3849 case Token::kDIV: | 3720 case Token::kDIV: |
3850 __ divsd(left, right); | 3721 __ divsd(left, right); |
3851 break; | 3722 break; |
3852 default: | 3723 default: |
3853 UNREACHABLE(); | 3724 UNREACHABLE(); |
3854 } | 3725 } |
3855 } | 3726 } |
3856 | 3727 |
3857 | |
3858 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3728 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
3859 bool opt) const { | 3729 bool opt) const { |
3860 const intptr_t kNumInputs = 1; | 3730 const intptr_t kNumInputs = 1; |
3861 const intptr_t kNumTemps = | 3731 const intptr_t kNumTemps = |
3862 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3732 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
3863 LocationSummary* summary = new (zone) | 3733 LocationSummary* summary = new (zone) |
3864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3734 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3865 summary->set_in(0, Location::RequiresFpuRegister()); | 3735 summary->set_in(0, Location::RequiresFpuRegister()); |
3866 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3736 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3867 summary->set_temp(0, Location::RequiresRegister()); | 3737 summary->set_temp(0, Location::RequiresRegister()); |
3868 } | 3738 } |
3869 summary->set_out(0, Location::RequiresRegister()); | 3739 summary->set_out(0, Location::RequiresRegister()); |
3870 return summary; | 3740 return summary; |
3871 } | 3741 } |
3872 | 3742 |
3873 | |
3874 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3743 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
3875 BranchLabels labels) { | 3744 BranchLabels labels) { |
3876 ASSERT(compiler->is_optimizing()); | 3745 ASSERT(compiler->is_optimizing()); |
3877 const XmmRegister value = locs()->in(0).fpu_reg(); | 3746 const XmmRegister value = locs()->in(0).fpu_reg(); |
3878 const bool is_negated = kind() != Token::kEQ; | 3747 const bool is_negated = kind() != Token::kEQ; |
3879 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3748 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
3880 Label is_nan; | 3749 Label is_nan; |
3881 __ comisd(value, value); | 3750 __ comisd(value, value); |
3882 return is_negated ? PARITY_ODD : PARITY_EVEN; | 3751 return is_negated ? PARITY_ODD : PARITY_EVEN; |
3883 } else { | 3752 } else { |
3884 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); | 3753 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
3885 const Register temp = locs()->temp(0).reg(); | 3754 const Register temp = locs()->temp(0).reg(); |
3886 __ AddImmediate(RSP, Immediate(-kDoubleSize)); | 3755 __ AddImmediate(RSP, Immediate(-kDoubleSize)); |
3887 __ movsd(Address(RSP, 0), value); | 3756 __ movsd(Address(RSP, 0), value); |
3888 __ movq(temp, Address(RSP, 0)); | 3757 __ movq(temp, Address(RSP, 0)); |
3889 __ AddImmediate(RSP, Immediate(kDoubleSize)); | 3758 __ AddImmediate(RSP, Immediate(kDoubleSize)); |
3890 // Mask off the sign. | 3759 // Mask off the sign. |
3891 __ AndImmediate(temp, Immediate(0x7FFFFFFFFFFFFFFFLL)); | 3760 __ AndImmediate(temp, Immediate(0x7FFFFFFFFFFFFFFFLL)); |
3892 // Compare with +infinity. | 3761 // Compare with +infinity. |
3893 __ CompareImmediate(temp, Immediate(0x7FF0000000000000LL)); | 3762 __ CompareImmediate(temp, Immediate(0x7FF0000000000000LL)); |
3894 return is_negated ? NOT_EQUAL : EQUAL; | 3763 return is_negated ? NOT_EQUAL : EQUAL; |
3895 } | 3764 } |
3896 } | 3765 } |
3897 | 3766 |
3898 | |
3899 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3767 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3900 bool opt) const { | 3768 bool opt) const { |
3901 const intptr_t kNumInputs = 2; | 3769 const intptr_t kNumInputs = 2; |
3902 const intptr_t kNumTemps = 0; | 3770 const intptr_t kNumTemps = 0; |
3903 LocationSummary* summary = new (zone) | 3771 LocationSummary* summary = new (zone) |
3904 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3772 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3905 summary->set_in(0, Location::RequiresFpuRegister()); | 3773 summary->set_in(0, Location::RequiresFpuRegister()); |
3906 summary->set_in(1, Location::RequiresFpuRegister()); | 3774 summary->set_in(1, Location::RequiresFpuRegister()); |
3907 summary->set_out(0, Location::SameAsFirstInput()); | 3775 summary->set_out(0, Location::SameAsFirstInput()); |
3908 return summary; | 3776 return summary; |
3909 } | 3777 } |
3910 | 3778 |
3911 | |
3912 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3779 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3913 XmmRegister left = locs()->in(0).fpu_reg(); | 3780 XmmRegister left = locs()->in(0).fpu_reg(); |
3914 XmmRegister right = locs()->in(1).fpu_reg(); | 3781 XmmRegister right = locs()->in(1).fpu_reg(); |
3915 | 3782 |
3916 ASSERT(locs()->out(0).fpu_reg() == left); | 3783 ASSERT(locs()->out(0).fpu_reg() == left); |
3917 | 3784 |
3918 switch (op_kind()) { | 3785 switch (op_kind()) { |
3919 case Token::kADD: | 3786 case Token::kADD: |
3920 __ addps(left, right); | 3787 __ addps(left, right); |
3921 break; | 3788 break; |
3922 case Token::kSUB: | 3789 case Token::kSUB: |
3923 __ subps(left, right); | 3790 __ subps(left, right); |
3924 break; | 3791 break; |
3925 case Token::kMUL: | 3792 case Token::kMUL: |
3926 __ mulps(left, right); | 3793 __ mulps(left, right); |
3927 break; | 3794 break; |
3928 case Token::kDIV: | 3795 case Token::kDIV: |
3929 __ divps(left, right); | 3796 __ divps(left, right); |
3930 break; | 3797 break; |
3931 default: | 3798 default: |
3932 UNREACHABLE(); | 3799 UNREACHABLE(); |
3933 } | 3800 } |
3934 } | 3801 } |
3935 | 3802 |
3936 | |
3937 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3803 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
3938 bool opt) const { | 3804 bool opt) const { |
3939 const intptr_t kNumInputs = 2; | 3805 const intptr_t kNumInputs = 2; |
3940 const intptr_t kNumTemps = 0; | 3806 const intptr_t kNumTemps = 0; |
3941 LocationSummary* summary = new (zone) | 3807 LocationSummary* summary = new (zone) |
3942 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3808 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3943 summary->set_in(0, Location::RequiresFpuRegister()); | 3809 summary->set_in(0, Location::RequiresFpuRegister()); |
3944 summary->set_in(1, Location::RequiresFpuRegister()); | 3810 summary->set_in(1, Location::RequiresFpuRegister()); |
3945 summary->set_out(0, Location::SameAsFirstInput()); | 3811 summary->set_out(0, Location::SameAsFirstInput()); |
3946 return summary; | 3812 return summary; |
3947 } | 3813 } |
3948 | 3814 |
3949 | |
3950 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3815 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3951 XmmRegister left = locs()->in(0).fpu_reg(); | 3816 XmmRegister left = locs()->in(0).fpu_reg(); |
3952 XmmRegister right = locs()->in(1).fpu_reg(); | 3817 XmmRegister right = locs()->in(1).fpu_reg(); |
3953 | 3818 |
3954 ASSERT(locs()->out(0).fpu_reg() == left); | 3819 ASSERT(locs()->out(0).fpu_reg() == left); |
3955 | 3820 |
3956 switch (op_kind()) { | 3821 switch (op_kind()) { |
3957 case Token::kADD: | 3822 case Token::kADD: |
3958 __ addpd(left, right); | 3823 __ addpd(left, right); |
3959 break; | 3824 break; |
3960 case Token::kSUB: | 3825 case Token::kSUB: |
3961 __ subpd(left, right); | 3826 __ subpd(left, right); |
3962 break; | 3827 break; |
3963 case Token::kMUL: | 3828 case Token::kMUL: |
3964 __ mulpd(left, right); | 3829 __ mulpd(left, right); |
3965 break; | 3830 break; |
3966 case Token::kDIV: | 3831 case Token::kDIV: |
3967 __ divpd(left, right); | 3832 __ divpd(left, right); |
3968 break; | 3833 break; |
3969 default: | 3834 default: |
3970 UNREACHABLE(); | 3835 UNREACHABLE(); |
3971 } | 3836 } |
3972 } | 3837 } |
3973 | 3838 |
3974 | |
3975 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3839 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
3976 bool opt) const { | 3840 bool opt) const { |
3977 const intptr_t kNumInputs = 1; | 3841 const intptr_t kNumInputs = 1; |
3978 const intptr_t kNumTemps = 0; | 3842 const intptr_t kNumTemps = 0; |
3979 LocationSummary* summary = new (zone) | 3843 LocationSummary* summary = new (zone) |
3980 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3844 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3981 summary->set_in(0, Location::RequiresFpuRegister()); | 3845 summary->set_in(0, Location::RequiresFpuRegister()); |
3982 summary->set_out(0, Location::SameAsFirstInput()); | 3846 summary->set_out(0, Location::SameAsFirstInput()); |
3983 return summary; | 3847 return summary; |
3984 } | 3848 } |
3985 | 3849 |
3986 | |
3987 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3850 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3988 XmmRegister value = locs()->in(0).fpu_reg(); | 3851 XmmRegister value = locs()->in(0).fpu_reg(); |
3989 | 3852 |
3990 ASSERT(locs()->out(0).fpu_reg() == value); | 3853 ASSERT(locs()->out(0).fpu_reg() == value); |
3991 | 3854 |
3992 switch (op_kind()) { | 3855 switch (op_kind()) { |
3993 case MethodRecognizer::kFloat32x4ShuffleX: | 3856 case MethodRecognizer::kFloat32x4ShuffleX: |
3994 // Shuffle not necessary. | 3857 // Shuffle not necessary. |
3995 __ cvtss2sd(value, value); | 3858 __ cvtss2sd(value, value); |
3996 break; | 3859 break; |
(...skipping 11 matching lines...) Expand all Loading... |
4008 break; | 3871 break; |
4009 case MethodRecognizer::kFloat32x4Shuffle: | 3872 case MethodRecognizer::kFloat32x4Shuffle: |
4010 case MethodRecognizer::kInt32x4Shuffle: | 3873 case MethodRecognizer::kInt32x4Shuffle: |
4011 __ shufps(value, value, Immediate(mask_)); | 3874 __ shufps(value, value, Immediate(mask_)); |
4012 break; | 3875 break; |
4013 default: | 3876 default: |
4014 UNREACHABLE(); | 3877 UNREACHABLE(); |
4015 } | 3878 } |
4016 } | 3879 } |
4017 | 3880 |
4018 | |
4019 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3881 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
4020 bool opt) const { | 3882 bool opt) const { |
4021 const intptr_t kNumInputs = 2; | 3883 const intptr_t kNumInputs = 2; |
4022 const intptr_t kNumTemps = 0; | 3884 const intptr_t kNumTemps = 0; |
4023 LocationSummary* summary = new (zone) | 3885 LocationSummary* summary = new (zone) |
4024 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3886 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4025 summary->set_in(0, Location::RequiresFpuRegister()); | 3887 summary->set_in(0, Location::RequiresFpuRegister()); |
4026 summary->set_in(1, Location::RequiresFpuRegister()); | 3888 summary->set_in(1, Location::RequiresFpuRegister()); |
4027 summary->set_out(0, Location::SameAsFirstInput()); | 3889 summary->set_out(0, Location::SameAsFirstInput()); |
4028 return summary; | 3890 return summary; |
4029 } | 3891 } |
4030 | 3892 |
4031 | |
4032 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3893 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4033 XmmRegister left = locs()->in(0).fpu_reg(); | 3894 XmmRegister left = locs()->in(0).fpu_reg(); |
4034 XmmRegister right = locs()->in(1).fpu_reg(); | 3895 XmmRegister right = locs()->in(1).fpu_reg(); |
4035 | 3896 |
4036 ASSERT(locs()->out(0).fpu_reg() == left); | 3897 ASSERT(locs()->out(0).fpu_reg() == left); |
4037 switch (op_kind()) { | 3898 switch (op_kind()) { |
4038 case MethodRecognizer::kFloat32x4ShuffleMix: | 3899 case MethodRecognizer::kFloat32x4ShuffleMix: |
4039 case MethodRecognizer::kInt32x4ShuffleMix: | 3900 case MethodRecognizer::kInt32x4ShuffleMix: |
4040 __ shufps(left, right, Immediate(mask_)); | 3901 __ shufps(left, right, Immediate(mask_)); |
4041 break; | 3902 break; |
4042 default: | 3903 default: |
4043 UNREACHABLE(); | 3904 UNREACHABLE(); |
4044 } | 3905 } |
4045 } | 3906 } |
4046 | 3907 |
4047 | |
4048 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3908 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
4049 bool opt) const { | 3909 bool opt) const { |
4050 const intptr_t kNumInputs = 1; | 3910 const intptr_t kNumInputs = 1; |
4051 const intptr_t kNumTemps = 0; | 3911 const intptr_t kNumTemps = 0; |
4052 LocationSummary* summary = new (zone) | 3912 LocationSummary* summary = new (zone) |
4053 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3913 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4054 summary->set_in(0, Location::RequiresFpuRegister()); | 3914 summary->set_in(0, Location::RequiresFpuRegister()); |
4055 summary->set_out(0, Location::RequiresRegister()); | 3915 summary->set_out(0, Location::RequiresRegister()); |
4056 return summary; | 3916 return summary; |
4057 } | 3917 } |
4058 | 3918 |
4059 | |
4060 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3919 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4061 XmmRegister value = locs()->in(0).fpu_reg(); | 3920 XmmRegister value = locs()->in(0).fpu_reg(); |
4062 Register out = locs()->out(0).reg(); | 3921 Register out = locs()->out(0).reg(); |
4063 | 3922 |
4064 __ movmskps(out, value); | 3923 __ movmskps(out, value); |
4065 __ SmiTag(out); | 3924 __ SmiTag(out); |
4066 } | 3925 } |
4067 | 3926 |
4068 | |
4069 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3927 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
4070 Zone* zone, | 3928 Zone* zone, |
4071 bool opt) const { | 3929 bool opt) const { |
4072 const intptr_t kNumInputs = 4; | 3930 const intptr_t kNumInputs = 4; |
4073 const intptr_t kNumTemps = 0; | 3931 const intptr_t kNumTemps = 0; |
4074 LocationSummary* summary = new (zone) | 3932 LocationSummary* summary = new (zone) |
4075 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3933 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4076 summary->set_in(0, Location::RequiresFpuRegister()); | 3934 summary->set_in(0, Location::RequiresFpuRegister()); |
4077 summary->set_in(1, Location::RequiresFpuRegister()); | 3935 summary->set_in(1, Location::RequiresFpuRegister()); |
4078 summary->set_in(2, Location::RequiresFpuRegister()); | 3936 summary->set_in(2, Location::RequiresFpuRegister()); |
4079 summary->set_in(3, Location::RequiresFpuRegister()); | 3937 summary->set_in(3, Location::RequiresFpuRegister()); |
4080 summary->set_out(0, Location::SameAsFirstInput()); | 3938 summary->set_out(0, Location::SameAsFirstInput()); |
4081 return summary; | 3939 return summary; |
4082 } | 3940 } |
4083 | 3941 |
4084 | |
4085 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3942 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4086 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3943 XmmRegister v0 = locs()->in(0).fpu_reg(); |
4087 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3944 XmmRegister v1 = locs()->in(1).fpu_reg(); |
4088 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3945 XmmRegister v2 = locs()->in(2).fpu_reg(); |
4089 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3946 XmmRegister v3 = locs()->in(3).fpu_reg(); |
4090 ASSERT(v0 == locs()->out(0).fpu_reg()); | 3947 ASSERT(v0 == locs()->out(0).fpu_reg()); |
4091 __ AddImmediate(RSP, Immediate(-16)); | 3948 __ AddImmediate(RSP, Immediate(-16)); |
4092 __ cvtsd2ss(v0, v0); | 3949 __ cvtsd2ss(v0, v0); |
4093 __ movss(Address(RSP, 0), v0); | 3950 __ movss(Address(RSP, 0), v0); |
4094 __ movsd(v0, v1); | 3951 __ movsd(v0, v1); |
4095 __ cvtsd2ss(v0, v0); | 3952 __ cvtsd2ss(v0, v0); |
4096 __ movss(Address(RSP, 4), v0); | 3953 __ movss(Address(RSP, 4), v0); |
4097 __ movsd(v0, v2); | 3954 __ movsd(v0, v2); |
4098 __ cvtsd2ss(v0, v0); | 3955 __ cvtsd2ss(v0, v0); |
4099 __ movss(Address(RSP, 8), v0); | 3956 __ movss(Address(RSP, 8), v0); |
4100 __ movsd(v0, v3); | 3957 __ movsd(v0, v3); |
4101 __ cvtsd2ss(v0, v0); | 3958 __ cvtsd2ss(v0, v0); |
4102 __ movss(Address(RSP, 12), v0); | 3959 __ movss(Address(RSP, 12), v0); |
4103 __ movups(v0, Address(RSP, 0)); | 3960 __ movups(v0, Address(RSP, 0)); |
4104 __ AddImmediate(RSP, Immediate(16)); | 3961 __ AddImmediate(RSP, Immediate(16)); |
4105 } | 3962 } |
4106 | 3963 |
4107 | |
4108 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3964 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
4109 bool opt) const { | 3965 bool opt) const { |
4110 const intptr_t kNumInputs = 0; | 3966 const intptr_t kNumInputs = 0; |
4111 const intptr_t kNumTemps = 0; | 3967 const intptr_t kNumTemps = 0; |
4112 LocationSummary* summary = new (zone) | 3968 LocationSummary* summary = new (zone) |
4113 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4114 summary->set_out(0, Location::RequiresFpuRegister()); | 3970 summary->set_out(0, Location::RequiresFpuRegister()); |
4115 return summary; | 3971 return summary; |
4116 } | 3972 } |
4117 | 3973 |
4118 | |
4119 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3974 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4120 XmmRegister value = locs()->out(0).fpu_reg(); | 3975 XmmRegister value = locs()->out(0).fpu_reg(); |
4121 __ xorps(value, value); | 3976 __ xorps(value, value); |
4122 } | 3977 } |
4123 | 3978 |
4124 | |
4125 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 3979 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
4126 bool opt) const { | 3980 bool opt) const { |
4127 const intptr_t kNumInputs = 1; | 3981 const intptr_t kNumInputs = 1; |
4128 const intptr_t kNumTemps = 0; | 3982 const intptr_t kNumTemps = 0; |
4129 LocationSummary* summary = new (zone) | 3983 LocationSummary* summary = new (zone) |
4130 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3984 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4131 summary->set_in(0, Location::RequiresFpuRegister()); | 3985 summary->set_in(0, Location::RequiresFpuRegister()); |
4132 summary->set_out(0, Location::SameAsFirstInput()); | 3986 summary->set_out(0, Location::SameAsFirstInput()); |
4133 return summary; | 3987 return summary; |
4134 } | 3988 } |
4135 | 3989 |
4136 | |
4137 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3990 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4138 XmmRegister value = locs()->out(0).fpu_reg(); | 3991 XmmRegister value = locs()->out(0).fpu_reg(); |
4139 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 3992 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
4140 // Convert to Float32. | 3993 // Convert to Float32. |
4141 __ cvtsd2ss(value, value); | 3994 __ cvtsd2ss(value, value); |
4142 // Splat across all lanes. | 3995 // Splat across all lanes. |
4143 __ shufps(value, value, Immediate(0x00)); | 3996 __ shufps(value, value, Immediate(0x00)); |
4144 } | 3997 } |
4145 | 3998 |
4146 | |
4147 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 3999 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
4148 bool opt) const { | 4000 bool opt) const { |
4149 const intptr_t kNumInputs = 2; | 4001 const intptr_t kNumInputs = 2; |
4150 const intptr_t kNumTemps = 0; | 4002 const intptr_t kNumTemps = 0; |
4151 LocationSummary* summary = new (zone) | 4003 LocationSummary* summary = new (zone) |
4152 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4004 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4153 summary->set_in(0, Location::RequiresFpuRegister()); | 4005 summary->set_in(0, Location::RequiresFpuRegister()); |
4154 summary->set_in(1, Location::RequiresFpuRegister()); | 4006 summary->set_in(1, Location::RequiresFpuRegister()); |
4155 summary->set_out(0, Location::SameAsFirstInput()); | 4007 summary->set_out(0, Location::SameAsFirstInput()); |
4156 return summary; | 4008 return summary; |
4157 } | 4009 } |
4158 | 4010 |
4159 | |
4160 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4011 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4161 XmmRegister left = locs()->in(0).fpu_reg(); | 4012 XmmRegister left = locs()->in(0).fpu_reg(); |
4162 XmmRegister right = locs()->in(1).fpu_reg(); | 4013 XmmRegister right = locs()->in(1).fpu_reg(); |
4163 | 4014 |
4164 ASSERT(locs()->out(0).fpu_reg() == left); | 4015 ASSERT(locs()->out(0).fpu_reg() == left); |
4165 | 4016 |
4166 switch (op_kind()) { | 4017 switch (op_kind()) { |
4167 case MethodRecognizer::kFloat32x4Equal: | 4018 case MethodRecognizer::kFloat32x4Equal: |
4168 __ cmppseq(left, right); | 4019 __ cmppseq(left, right); |
4169 break; | 4020 break; |
(...skipping 11 matching lines...) Expand all Loading... |
4181 break; | 4032 break; |
4182 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4033 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
4183 __ cmppsle(left, right); | 4034 __ cmppsle(left, right); |
4184 break; | 4035 break; |
4185 | 4036 |
4186 default: | 4037 default: |
4187 UNREACHABLE(); | 4038 UNREACHABLE(); |
4188 } | 4039 } |
4189 } | 4040 } |
4190 | 4041 |
4191 | |
4192 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4042 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
4193 bool opt) const { | 4043 bool opt) const { |
4194 const intptr_t kNumInputs = 2; | 4044 const intptr_t kNumInputs = 2; |
4195 const intptr_t kNumTemps = 0; | 4045 const intptr_t kNumTemps = 0; |
4196 LocationSummary* summary = new (zone) | 4046 LocationSummary* summary = new (zone) |
4197 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4047 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4198 summary->set_in(0, Location::RequiresFpuRegister()); | 4048 summary->set_in(0, Location::RequiresFpuRegister()); |
4199 summary->set_in(1, Location::RequiresFpuRegister()); | 4049 summary->set_in(1, Location::RequiresFpuRegister()); |
4200 summary->set_out(0, Location::SameAsFirstInput()); | 4050 summary->set_out(0, Location::SameAsFirstInput()); |
4201 return summary; | 4051 return summary; |
4202 } | 4052 } |
4203 | 4053 |
4204 | |
4205 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4054 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4206 XmmRegister left = locs()->in(0).fpu_reg(); | 4055 XmmRegister left = locs()->in(0).fpu_reg(); |
4207 XmmRegister right = locs()->in(1).fpu_reg(); | 4056 XmmRegister right = locs()->in(1).fpu_reg(); |
4208 | 4057 |
4209 ASSERT(locs()->out(0).fpu_reg() == left); | 4058 ASSERT(locs()->out(0).fpu_reg() == left); |
4210 | 4059 |
4211 switch (op_kind()) { | 4060 switch (op_kind()) { |
4212 case MethodRecognizer::kFloat32x4Min: | 4061 case MethodRecognizer::kFloat32x4Min: |
4213 __ minps(left, right); | 4062 __ minps(left, right); |
4214 break; | 4063 break; |
4215 case MethodRecognizer::kFloat32x4Max: | 4064 case MethodRecognizer::kFloat32x4Max: |
4216 __ maxps(left, right); | 4065 __ maxps(left, right); |
4217 break; | 4066 break; |
4218 default: | 4067 default: |
4219 UNREACHABLE(); | 4068 UNREACHABLE(); |
4220 } | 4069 } |
4221 } | 4070 } |
4222 | 4071 |
4223 | |
4224 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4072 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
4225 bool opt) const { | 4073 bool opt) const { |
4226 const intptr_t kNumInputs = 2; | 4074 const intptr_t kNumInputs = 2; |
4227 const intptr_t kNumTemps = 0; | 4075 const intptr_t kNumTemps = 0; |
4228 LocationSummary* summary = new (zone) | 4076 LocationSummary* summary = new (zone) |
4229 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4077 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4230 summary->set_in(0, Location::RequiresFpuRegister()); | 4078 summary->set_in(0, Location::RequiresFpuRegister()); |
4231 summary->set_in(1, Location::RequiresFpuRegister()); | 4079 summary->set_in(1, Location::RequiresFpuRegister()); |
4232 summary->set_out(0, Location::SameAsFirstInput()); | 4080 summary->set_out(0, Location::SameAsFirstInput()); |
4233 return summary; | 4081 return summary; |
4234 } | 4082 } |
4235 | 4083 |
4236 | |
4237 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4084 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4238 XmmRegister left = locs()->in(0).fpu_reg(); | 4085 XmmRegister left = locs()->in(0).fpu_reg(); |
4239 XmmRegister right = locs()->in(1).fpu_reg(); | 4086 XmmRegister right = locs()->in(1).fpu_reg(); |
4240 | 4087 |
4241 ASSERT(locs()->out(0).fpu_reg() == left); | 4088 ASSERT(locs()->out(0).fpu_reg() == left); |
4242 | 4089 |
4243 switch (op_kind()) { | 4090 switch (op_kind()) { |
4244 case MethodRecognizer::kFloat32x4Scale: | 4091 case MethodRecognizer::kFloat32x4Scale: |
4245 __ cvtsd2ss(left, left); | 4092 __ cvtsd2ss(left, left); |
4246 __ shufps(left, left, Immediate(0x00)); | 4093 __ shufps(left, left, Immediate(0x00)); |
4247 __ mulps(left, right); | 4094 __ mulps(left, right); |
4248 break; | 4095 break; |
4249 default: | 4096 default: |
4250 UNREACHABLE(); | 4097 UNREACHABLE(); |
4251 } | 4098 } |
4252 } | 4099 } |
4253 | 4100 |
4254 | |
4255 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4101 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
4256 bool opt) const { | 4102 bool opt) const { |
4257 const intptr_t kNumInputs = 1; | 4103 const intptr_t kNumInputs = 1; |
4258 const intptr_t kNumTemps = 0; | 4104 const intptr_t kNumTemps = 0; |
4259 LocationSummary* summary = new (zone) | 4105 LocationSummary* summary = new (zone) |
4260 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4106 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4261 summary->set_in(0, Location::RequiresFpuRegister()); | 4107 summary->set_in(0, Location::RequiresFpuRegister()); |
4262 summary->set_out(0, Location::SameAsFirstInput()); | 4108 summary->set_out(0, Location::SameAsFirstInput()); |
4263 return summary; | 4109 return summary; |
4264 } | 4110 } |
4265 | 4111 |
4266 | |
4267 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4112 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4268 XmmRegister left = locs()->in(0).fpu_reg(); | 4113 XmmRegister left = locs()->in(0).fpu_reg(); |
4269 | 4114 |
4270 ASSERT(locs()->out(0).fpu_reg() == left); | 4115 ASSERT(locs()->out(0).fpu_reg() == left); |
4271 | 4116 |
4272 switch (op_kind()) { | 4117 switch (op_kind()) { |
4273 case MethodRecognizer::kFloat32x4Sqrt: | 4118 case MethodRecognizer::kFloat32x4Sqrt: |
4274 __ sqrtps(left); | 4119 __ sqrtps(left); |
4275 break; | 4120 break; |
4276 case MethodRecognizer::kFloat32x4Reciprocal: | 4121 case MethodRecognizer::kFloat32x4Reciprocal: |
4277 __ reciprocalps(left); | 4122 __ reciprocalps(left); |
4278 break; | 4123 break; |
4279 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4124 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4280 __ rsqrtps(left); | 4125 __ rsqrtps(left); |
4281 break; | 4126 break; |
4282 default: | 4127 default: |
4283 UNREACHABLE(); | 4128 UNREACHABLE(); |
4284 } | 4129 } |
4285 } | 4130 } |
4286 | 4131 |
4287 | |
4288 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4132 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4289 bool opt) const { | 4133 bool opt) const { |
4290 const intptr_t kNumInputs = 1; | 4134 const intptr_t kNumInputs = 1; |
4291 const intptr_t kNumTemps = 0; | 4135 const intptr_t kNumTemps = 0; |
4292 LocationSummary* summary = new (zone) | 4136 LocationSummary* summary = new (zone) |
4293 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4137 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4294 summary->set_in(0, Location::RequiresFpuRegister()); | 4138 summary->set_in(0, Location::RequiresFpuRegister()); |
4295 summary->set_out(0, Location::SameAsFirstInput()); | 4139 summary->set_out(0, Location::SameAsFirstInput()); |
4296 return summary; | 4140 return summary; |
4297 } | 4141 } |
4298 | 4142 |
4299 | |
4300 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4143 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4301 XmmRegister left = locs()->in(0).fpu_reg(); | 4144 XmmRegister left = locs()->in(0).fpu_reg(); |
4302 | 4145 |
4303 ASSERT(locs()->out(0).fpu_reg() == left); | 4146 ASSERT(locs()->out(0).fpu_reg() == left); |
4304 switch (op_kind()) { | 4147 switch (op_kind()) { |
4305 case MethodRecognizer::kFloat32x4Negate: | 4148 case MethodRecognizer::kFloat32x4Negate: |
4306 __ negateps(left); | 4149 __ negateps(left); |
4307 break; | 4150 break; |
4308 case MethodRecognizer::kFloat32x4Absolute: | 4151 case MethodRecognizer::kFloat32x4Absolute: |
4309 __ absps(left); | 4152 __ absps(left); |
4310 break; | 4153 break; |
4311 default: | 4154 default: |
4312 UNREACHABLE(); | 4155 UNREACHABLE(); |
4313 } | 4156 } |
4314 } | 4157 } |
4315 | 4158 |
4316 | |
4317 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4159 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
4318 bool opt) const { | 4160 bool opt) const { |
4319 const intptr_t kNumInputs = 3; | 4161 const intptr_t kNumInputs = 3; |
4320 const intptr_t kNumTemps = 0; | 4162 const intptr_t kNumTemps = 0; |
4321 LocationSummary* summary = new (zone) | 4163 LocationSummary* summary = new (zone) |
4322 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4164 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4323 summary->set_in(0, Location::RequiresFpuRegister()); | 4165 summary->set_in(0, Location::RequiresFpuRegister()); |
4324 summary->set_in(1, Location::RequiresFpuRegister()); | 4166 summary->set_in(1, Location::RequiresFpuRegister()); |
4325 summary->set_in(2, Location::RequiresFpuRegister()); | 4167 summary->set_in(2, Location::RequiresFpuRegister()); |
4326 summary->set_out(0, Location::SameAsFirstInput()); | 4168 summary->set_out(0, Location::SameAsFirstInput()); |
4327 return summary; | 4169 return summary; |
4328 } | 4170 } |
4329 | 4171 |
4330 | |
4331 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4172 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4332 XmmRegister left = locs()->in(0).fpu_reg(); | 4173 XmmRegister left = locs()->in(0).fpu_reg(); |
4333 XmmRegister lower = locs()->in(1).fpu_reg(); | 4174 XmmRegister lower = locs()->in(1).fpu_reg(); |
4334 XmmRegister upper = locs()->in(2).fpu_reg(); | 4175 XmmRegister upper = locs()->in(2).fpu_reg(); |
4335 ASSERT(locs()->out(0).fpu_reg() == left); | 4176 ASSERT(locs()->out(0).fpu_reg() == left); |
4336 __ minps(left, upper); | 4177 __ minps(left, upper); |
4337 __ maxps(left, lower); | 4178 __ maxps(left, lower); |
4338 } | 4179 } |
4339 | 4180 |
4340 | |
4341 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4181 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
4342 bool opt) const { | 4182 bool opt) const { |
4343 const intptr_t kNumInputs = 2; | 4183 const intptr_t kNumInputs = 2; |
4344 const intptr_t kNumTemps = 0; | 4184 const intptr_t kNumTemps = 0; |
4345 LocationSummary* summary = new (zone) | 4185 LocationSummary* summary = new (zone) |
4346 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4186 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4347 summary->set_in(0, Location::RequiresFpuRegister()); | 4187 summary->set_in(0, Location::RequiresFpuRegister()); |
4348 summary->set_in(1, Location::RequiresFpuRegister()); | 4188 summary->set_in(1, Location::RequiresFpuRegister()); |
4349 summary->set_out(0, Location::SameAsFirstInput()); | 4189 summary->set_out(0, Location::SameAsFirstInput()); |
4350 return summary; | 4190 return summary; |
4351 } | 4191 } |
4352 | 4192 |
4353 | |
4354 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4193 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4355 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4194 XmmRegister replacement = locs()->in(0).fpu_reg(); |
4356 XmmRegister value = locs()->in(1).fpu_reg(); | 4195 XmmRegister value = locs()->in(1).fpu_reg(); |
4357 | 4196 |
4358 ASSERT(locs()->out(0).fpu_reg() == replacement); | 4197 ASSERT(locs()->out(0).fpu_reg() == replacement); |
4359 | 4198 |
4360 switch (op_kind()) { | 4199 switch (op_kind()) { |
4361 case MethodRecognizer::kFloat32x4WithX: | 4200 case MethodRecognizer::kFloat32x4WithX: |
4362 __ cvtsd2ss(replacement, replacement); | 4201 __ cvtsd2ss(replacement, replacement); |
4363 __ AddImmediate(RSP, Immediate(-16)); | 4202 __ AddImmediate(RSP, Immediate(-16)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4400 __ movss(Address(RSP, 12), replacement); | 4239 __ movss(Address(RSP, 12), replacement); |
4401 // Move updated value into output register. | 4240 // Move updated value into output register. |
4402 __ movups(replacement, Address(RSP, 0)); | 4241 __ movups(replacement, Address(RSP, 0)); |
4403 __ AddImmediate(RSP, Immediate(16)); | 4242 __ AddImmediate(RSP, Immediate(16)); |
4404 break; | 4243 break; |
4405 default: | 4244 default: |
4406 UNREACHABLE(); | 4245 UNREACHABLE(); |
4407 } | 4246 } |
4408 } | 4247 } |
4409 | 4248 |
4410 | |
4411 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4249 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
4412 bool opt) const { | 4250 bool opt) const { |
4413 const intptr_t kNumInputs = 1; | 4251 const intptr_t kNumInputs = 1; |
4414 const intptr_t kNumTemps = 0; | 4252 const intptr_t kNumTemps = 0; |
4415 LocationSummary* summary = new (zone) | 4253 LocationSummary* summary = new (zone) |
4416 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4417 summary->set_in(0, Location::RequiresFpuRegister()); | 4255 summary->set_in(0, Location::RequiresFpuRegister()); |
4418 summary->set_out(0, Location::SameAsFirstInput()); | 4256 summary->set_out(0, Location::SameAsFirstInput()); |
4419 return summary; | 4257 return summary; |
4420 } | 4258 } |
4421 | 4259 |
4422 | |
4423 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4260 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4424 // NOP. | 4261 // NOP. |
4425 } | 4262 } |
4426 | 4263 |
4427 | |
4428 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4264 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
4429 bool opt) const { | 4265 bool opt) const { |
4430 const intptr_t kNumInputs = 1; | 4266 const intptr_t kNumInputs = 1; |
4431 const intptr_t kNumTemps = 0; | 4267 const intptr_t kNumTemps = 0; |
4432 LocationSummary* summary = new (zone) | 4268 LocationSummary* summary = new (zone) |
4433 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4269 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4434 summary->set_in(0, Location::RequiresFpuRegister()); | 4270 summary->set_in(0, Location::RequiresFpuRegister()); |
4435 summary->set_out(0, Location::SameAsFirstInput()); | 4271 summary->set_out(0, Location::SameAsFirstInput()); |
4436 return summary; | 4272 return summary; |
4437 } | 4273 } |
4438 | 4274 |
4439 | |
4440 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4275 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4441 XmmRegister value = locs()->in(0).fpu_reg(); | 4276 XmmRegister value = locs()->in(0).fpu_reg(); |
4442 | 4277 |
4443 ASSERT(locs()->out(0).fpu_reg() == value); | 4278 ASSERT(locs()->out(0).fpu_reg() == value); |
4444 switch (op_kind()) { | 4279 switch (op_kind()) { |
4445 case MethodRecognizer::kFloat64x2GetX: | 4280 case MethodRecognizer::kFloat64x2GetX: |
4446 // nop. | 4281 // nop. |
4447 break; | 4282 break; |
4448 case MethodRecognizer::kFloat64x2GetY: | 4283 case MethodRecognizer::kFloat64x2GetY: |
4449 __ shufpd(value, value, Immediate(0x33)); | 4284 __ shufpd(value, value, Immediate(0x33)); |
4450 break; | 4285 break; |
4451 default: | 4286 default: |
4452 UNREACHABLE(); | 4287 UNREACHABLE(); |
4453 } | 4288 } |
4454 } | 4289 } |
4455 | 4290 |
4456 | |
4457 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4291 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
4458 bool opt) const { | 4292 bool opt) const { |
4459 const intptr_t kNumInputs = 0; | 4293 const intptr_t kNumInputs = 0; |
4460 const intptr_t kNumTemps = 0; | 4294 const intptr_t kNumTemps = 0; |
4461 LocationSummary* summary = new (zone) | 4295 LocationSummary* summary = new (zone) |
4462 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4296 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4463 summary->set_out(0, Location::RequiresFpuRegister()); | 4297 summary->set_out(0, Location::RequiresFpuRegister()); |
4464 return summary; | 4298 return summary; |
4465 } | 4299 } |
4466 | 4300 |
4467 | |
4468 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4301 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4469 XmmRegister value = locs()->out(0).fpu_reg(); | 4302 XmmRegister value = locs()->out(0).fpu_reg(); |
4470 __ xorpd(value, value); | 4303 __ xorpd(value, value); |
4471 } | 4304 } |
4472 | 4305 |
4473 | |
4474 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4306 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
4475 bool opt) const { | 4307 bool opt) const { |
4476 const intptr_t kNumInputs = 1; | 4308 const intptr_t kNumInputs = 1; |
4477 const intptr_t kNumTemps = 0; | 4309 const intptr_t kNumTemps = 0; |
4478 LocationSummary* summary = new (zone) | 4310 LocationSummary* summary = new (zone) |
4479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4311 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4480 summary->set_in(0, Location::RequiresFpuRegister()); | 4312 summary->set_in(0, Location::RequiresFpuRegister()); |
4481 summary->set_out(0, Location::SameAsFirstInput()); | 4313 summary->set_out(0, Location::SameAsFirstInput()); |
4482 return summary; | 4314 return summary; |
4483 } | 4315 } |
4484 | 4316 |
4485 | |
4486 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4317 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4487 XmmRegister value = locs()->out(0).fpu_reg(); | 4318 XmmRegister value = locs()->out(0).fpu_reg(); |
4488 __ shufpd(value, value, Immediate(0x0)); | 4319 __ shufpd(value, value, Immediate(0x0)); |
4489 } | 4320 } |
4490 | 4321 |
4491 | |
4492 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4322 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4493 Zone* zone, | 4323 Zone* zone, |
4494 bool opt) const { | 4324 bool opt) const { |
4495 const intptr_t kNumInputs = 2; | 4325 const intptr_t kNumInputs = 2; |
4496 const intptr_t kNumTemps = 0; | 4326 const intptr_t kNumTemps = 0; |
4497 LocationSummary* summary = new (zone) | 4327 LocationSummary* summary = new (zone) |
4498 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4328 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4499 summary->set_in(0, Location::RequiresFpuRegister()); | 4329 summary->set_in(0, Location::RequiresFpuRegister()); |
4500 summary->set_in(1, Location::RequiresFpuRegister()); | 4330 summary->set_in(1, Location::RequiresFpuRegister()); |
4501 summary->set_out(0, Location::SameAsFirstInput()); | 4331 summary->set_out(0, Location::SameAsFirstInput()); |
4502 return summary; | 4332 return summary; |
4503 } | 4333 } |
4504 | 4334 |
4505 | |
4506 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4507 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4336 XmmRegister v0 = locs()->in(0).fpu_reg(); |
4508 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4337 XmmRegister v1 = locs()->in(1).fpu_reg(); |
4509 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4338 ASSERT(v0 == locs()->out(0).fpu_reg()); |
4510 // shufpd mask 0x0 results in: | 4339 // shufpd mask 0x0 results in: |
4511 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4340 // Lower 64-bits of v0 = Lower 64-bits of v0. |
4512 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4341 // Upper 64-bits of v0 = Lower 64-bits of v1. |
4513 __ shufpd(v0, v1, Immediate(0x0)); | 4342 __ shufpd(v0, v1, Immediate(0x0)); |
4514 } | 4343 } |
4515 | 4344 |
4516 | |
4517 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4345 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4518 Zone* zone, | 4346 Zone* zone, |
4519 bool opt) const { | 4347 bool opt) const { |
4520 const intptr_t kNumInputs = 1; | 4348 const intptr_t kNumInputs = 1; |
4521 const intptr_t kNumTemps = 0; | 4349 const intptr_t kNumTemps = 0; |
4522 LocationSummary* summary = new (zone) | 4350 LocationSummary* summary = new (zone) |
4523 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4351 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4524 summary->set_in(0, Location::RequiresFpuRegister()); | 4352 summary->set_in(0, Location::RequiresFpuRegister()); |
4525 summary->set_out(0, Location::SameAsFirstInput()); | 4353 summary->set_out(0, Location::SameAsFirstInput()); |
4526 return summary; | 4354 return summary; |
4527 } | 4355 } |
4528 | 4356 |
4529 | |
4530 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4357 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4531 XmmRegister value = locs()->out(0).fpu_reg(); | 4358 XmmRegister value = locs()->out(0).fpu_reg(); |
4532 __ cvtpd2ps(value, value); | 4359 __ cvtpd2ps(value, value); |
4533 } | 4360 } |
4534 | 4361 |
4535 | |
4536 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4362 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4537 Zone* zone, | 4363 Zone* zone, |
4538 bool opt) const { | 4364 bool opt) const { |
4539 const intptr_t kNumInputs = 1; | 4365 const intptr_t kNumInputs = 1; |
4540 const intptr_t kNumTemps = 0; | 4366 const intptr_t kNumTemps = 0; |
4541 LocationSummary* summary = new (zone) | 4367 LocationSummary* summary = new (zone) |
4542 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4368 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4543 summary->set_in(0, Location::RequiresFpuRegister()); | 4369 summary->set_in(0, Location::RequiresFpuRegister()); |
4544 summary->set_out(0, Location::SameAsFirstInput()); | 4370 summary->set_out(0, Location::SameAsFirstInput()); |
4545 return summary; | 4371 return summary; |
4546 } | 4372 } |
4547 | 4373 |
4548 | |
4549 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4374 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4550 XmmRegister value = locs()->out(0).fpu_reg(); | 4375 XmmRegister value = locs()->out(0).fpu_reg(); |
4551 __ cvtps2pd(value, value); | 4376 __ cvtps2pd(value, value); |
4552 } | 4377 } |
4553 | 4378 |
4554 | |
4555 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4379 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4556 bool opt) const { | 4380 bool opt) const { |
4557 const intptr_t kNumInputs = 1; | 4381 const intptr_t kNumInputs = 1; |
4558 const intptr_t kNumTemps = 0; | 4382 const intptr_t kNumTemps = 0; |
4559 LocationSummary* summary = new (zone) | 4383 LocationSummary* summary = new (zone) |
4560 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4384 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4561 summary->set_in(0, Location::RequiresFpuRegister()); | 4385 summary->set_in(0, Location::RequiresFpuRegister()); |
4562 if (representation() == kTagged) { | 4386 if (representation() == kTagged) { |
4563 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4387 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
4564 summary->set_out(0, Location::RequiresRegister()); | 4388 summary->set_out(0, Location::RequiresRegister()); |
4565 } else { | 4389 } else { |
4566 ASSERT(representation() == kUnboxedFloat64x2); | 4390 ASSERT(representation() == kUnboxedFloat64x2); |
4567 summary->set_out(0, Location::SameAsFirstInput()); | 4391 summary->set_out(0, Location::SameAsFirstInput()); |
4568 } | 4392 } |
4569 return summary; | 4393 return summary; |
4570 } | 4394 } |
4571 | 4395 |
4572 | |
4573 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4396 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4574 XmmRegister left = locs()->in(0).fpu_reg(); | 4397 XmmRegister left = locs()->in(0).fpu_reg(); |
4575 | 4398 |
4576 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || | 4399 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || |
4577 (locs()->out(0).fpu_reg() == left)); | 4400 (locs()->out(0).fpu_reg() == left)); |
4578 | 4401 |
4579 switch (op_kind()) { | 4402 switch (op_kind()) { |
4580 case MethodRecognizer::kFloat64x2Negate: | 4403 case MethodRecognizer::kFloat64x2Negate: |
4581 __ negatepd(left); | 4404 __ negatepd(left); |
4582 break; | 4405 break; |
4583 case MethodRecognizer::kFloat64x2Abs: | 4406 case MethodRecognizer::kFloat64x2Abs: |
4584 __ abspd(left); | 4407 __ abspd(left); |
4585 break; | 4408 break; |
4586 case MethodRecognizer::kFloat64x2Sqrt: | 4409 case MethodRecognizer::kFloat64x2Sqrt: |
4587 __ sqrtpd(left); | 4410 __ sqrtpd(left); |
4588 break; | 4411 break; |
4589 case MethodRecognizer::kFloat64x2GetSignMask: | 4412 case MethodRecognizer::kFloat64x2GetSignMask: |
4590 __ movmskpd(locs()->out(0).reg(), left); | 4413 __ movmskpd(locs()->out(0).reg(), left); |
4591 __ SmiTag(locs()->out(0).reg()); | 4414 __ SmiTag(locs()->out(0).reg()); |
4592 break; | 4415 break; |
4593 default: | 4416 default: |
4594 UNREACHABLE(); | 4417 UNREACHABLE(); |
4595 } | 4418 } |
4596 } | 4419 } |
4597 | 4420 |
4598 | |
4599 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4421 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
4600 bool opt) const { | 4422 bool opt) const { |
4601 const intptr_t kNumInputs = 2; | 4423 const intptr_t kNumInputs = 2; |
4602 const intptr_t kNumTemps = 0; | 4424 const intptr_t kNumTemps = 0; |
4603 LocationSummary* summary = new (zone) | 4425 LocationSummary* summary = new (zone) |
4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4426 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4605 summary->set_in(0, Location::RequiresFpuRegister()); | 4427 summary->set_in(0, Location::RequiresFpuRegister()); |
4606 summary->set_in(1, Location::RequiresFpuRegister()); | 4428 summary->set_in(1, Location::RequiresFpuRegister()); |
4607 summary->set_out(0, Location::SameAsFirstInput()); | 4429 summary->set_out(0, Location::SameAsFirstInput()); |
4608 return summary; | 4430 return summary; |
4609 } | 4431 } |
4610 | 4432 |
4611 | |
4612 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4433 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4613 XmmRegister left = locs()->in(0).fpu_reg(); | 4434 XmmRegister left = locs()->in(0).fpu_reg(); |
4614 XmmRegister right = locs()->in(1).fpu_reg(); | 4435 XmmRegister right = locs()->in(1).fpu_reg(); |
4615 ASSERT((locs()->out(0).fpu_reg() == left)); | 4436 ASSERT((locs()->out(0).fpu_reg() == left)); |
4616 | 4437 |
4617 switch (op_kind()) { | 4438 switch (op_kind()) { |
4618 case MethodRecognizer::kFloat64x2Scale: | 4439 case MethodRecognizer::kFloat64x2Scale: |
4619 __ shufpd(right, right, Immediate(0x00)); | 4440 __ shufpd(right, right, Immediate(0x00)); |
4620 __ mulpd(left, right); | 4441 __ mulpd(left, right); |
4621 break; | 4442 break; |
(...skipping 21 matching lines...) Expand all Loading... |
4643 __ minpd(left, right); | 4464 __ minpd(left, right); |
4644 break; | 4465 break; |
4645 case MethodRecognizer::kFloat64x2Max: | 4466 case MethodRecognizer::kFloat64x2Max: |
4646 __ maxpd(left, right); | 4467 __ maxpd(left, right); |
4647 break; | 4468 break; |
4648 default: | 4469 default: |
4649 UNREACHABLE(); | 4470 UNREACHABLE(); |
4650 } | 4471 } |
4651 } | 4472 } |
4652 | 4473 |
4653 | |
4654 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 4474 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
4655 bool opt) const { | 4475 bool opt) const { |
4656 const intptr_t kNumInputs = 4; | 4476 const intptr_t kNumInputs = 4; |
4657 const intptr_t kNumTemps = 0; | 4477 const intptr_t kNumTemps = 0; |
4658 LocationSummary* summary = new (zone) | 4478 LocationSummary* summary = new (zone) |
4659 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4660 summary->set_in(0, Location::RequiresRegister()); | 4480 summary->set_in(0, Location::RequiresRegister()); |
4661 summary->set_in(1, Location::RequiresRegister()); | 4481 summary->set_in(1, Location::RequiresRegister()); |
4662 summary->set_in(2, Location::RequiresRegister()); | 4482 summary->set_in(2, Location::RequiresRegister()); |
4663 summary->set_in(3, Location::RequiresRegister()); | 4483 summary->set_in(3, Location::RequiresRegister()); |
4664 summary->set_out(0, Location::RequiresFpuRegister()); | 4484 summary->set_out(0, Location::RequiresFpuRegister()); |
4665 return summary; | 4485 return summary; |
4666 } | 4486 } |
4667 | 4487 |
4668 | |
4669 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4488 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4670 Register v0 = locs()->in(0).reg(); | 4489 Register v0 = locs()->in(0).reg(); |
4671 Register v1 = locs()->in(1).reg(); | 4490 Register v1 = locs()->in(1).reg(); |
4672 Register v2 = locs()->in(2).reg(); | 4491 Register v2 = locs()->in(2).reg(); |
4673 Register v3 = locs()->in(3).reg(); | 4492 Register v3 = locs()->in(3).reg(); |
4674 XmmRegister result = locs()->out(0).fpu_reg(); | 4493 XmmRegister result = locs()->out(0).fpu_reg(); |
4675 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); | 4494 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); |
4676 __ movl(Address(RSP, 0 * kInt32Size), v0); | 4495 __ movl(Address(RSP, 0 * kInt32Size), v0); |
4677 __ movl(Address(RSP, 1 * kInt32Size), v1); | 4496 __ movl(Address(RSP, 1 * kInt32Size), v1); |
4678 __ movl(Address(RSP, 2 * kInt32Size), v2); | 4497 __ movl(Address(RSP, 2 * kInt32Size), v2); |
4679 __ movl(Address(RSP, 3 * kInt32Size), v3); | 4498 __ movl(Address(RSP, 3 * kInt32Size), v3); |
4680 __ movups(result, Address(RSP, 0)); | 4499 __ movups(result, Address(RSP, 0)); |
4681 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); | 4500 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); |
4682 } | 4501 } |
4683 | 4502 |
4684 | |
4685 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4503 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
4686 Zone* zone, | 4504 Zone* zone, |
4687 bool opt) const { | 4505 bool opt) const { |
4688 const intptr_t kNumInputs = 4; | 4506 const intptr_t kNumInputs = 4; |
4689 const intptr_t kNumTemps = 1; | 4507 const intptr_t kNumTemps = 1; |
4690 LocationSummary* summary = new (zone) | 4508 LocationSummary* summary = new (zone) |
4691 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4509 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4692 summary->set_in(0, Location::RequiresRegister()); | 4510 summary->set_in(0, Location::RequiresRegister()); |
4693 summary->set_in(1, Location::RequiresRegister()); | 4511 summary->set_in(1, Location::RequiresRegister()); |
4694 summary->set_in(2, Location::RequiresRegister()); | 4512 summary->set_in(2, Location::RequiresRegister()); |
4695 summary->set_in(3, Location::RequiresRegister()); | 4513 summary->set_in(3, Location::RequiresRegister()); |
4696 summary->set_temp(0, Location::RequiresRegister()); | 4514 summary->set_temp(0, Location::RequiresRegister()); |
4697 summary->set_out(0, Location::RequiresFpuRegister()); | 4515 summary->set_out(0, Location::RequiresFpuRegister()); |
4698 return summary; | 4516 return summary; |
4699 } | 4517 } |
4700 | 4518 |
4701 | |
4702 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4519 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4703 Register v0 = locs()->in(0).reg(); | 4520 Register v0 = locs()->in(0).reg(); |
4704 Register v1 = locs()->in(1).reg(); | 4521 Register v1 = locs()->in(1).reg(); |
4705 Register v2 = locs()->in(2).reg(); | 4522 Register v2 = locs()->in(2).reg(); |
4706 Register v3 = locs()->in(3).reg(); | 4523 Register v3 = locs()->in(3).reg(); |
4707 Register temp = locs()->temp(0).reg(); | 4524 Register temp = locs()->temp(0).reg(); |
4708 XmmRegister result = locs()->out(0).fpu_reg(); | 4525 XmmRegister result = locs()->out(0).fpu_reg(); |
4709 Label x_false, x_done; | 4526 Label x_false, x_done; |
4710 Label y_false, y_done; | 4527 Label y_false, y_done; |
4711 Label z_false, z_done; | 4528 Label z_false, z_done; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4745 __ jmp(&w_done); | 4562 __ jmp(&w_done); |
4746 __ Bind(&w_false); | 4563 __ Bind(&w_false); |
4747 __ LoadImmediate(temp, Immediate(0x0)); | 4564 __ LoadImmediate(temp, Immediate(0x0)); |
4748 __ Bind(&w_done); | 4565 __ Bind(&w_done); |
4749 __ movl(Address(RSP, 12), temp); | 4566 __ movl(Address(RSP, 12), temp); |
4750 | 4567 |
4751 __ movups(result, Address(RSP, 0)); | 4568 __ movups(result, Address(RSP, 0)); |
4752 __ AddImmediate(RSP, Immediate(16)); | 4569 __ AddImmediate(RSP, Immediate(16)); |
4753 } | 4570 } |
4754 | 4571 |
4755 | |
4756 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4572 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
4757 bool opt) const { | 4573 bool opt) const { |
4758 const intptr_t kNumInputs = 1; | 4574 const intptr_t kNumInputs = 1; |
4759 const intptr_t kNumTemps = 0; | 4575 const intptr_t kNumTemps = 0; |
4760 LocationSummary* summary = new (zone) | 4576 LocationSummary* summary = new (zone) |
4761 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4577 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4762 summary->set_in(0, Location::RequiresFpuRegister()); | 4578 summary->set_in(0, Location::RequiresFpuRegister()); |
4763 summary->set_out(0, Location::RequiresRegister()); | 4579 summary->set_out(0, Location::RequiresRegister()); |
4764 return summary; | 4580 return summary; |
4765 } | 4581 } |
4766 | 4582 |
4767 | |
4768 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4583 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4769 XmmRegister value = locs()->in(0).fpu_reg(); | 4584 XmmRegister value = locs()->in(0).fpu_reg(); |
4770 Register result = locs()->out(0).reg(); | 4585 Register result = locs()->out(0).reg(); |
4771 Label done; | 4586 Label done; |
4772 Label non_zero; | 4587 Label non_zero; |
4773 __ AddImmediate(RSP, Immediate(-16)); | 4588 __ AddImmediate(RSP, Immediate(-16)); |
4774 // Move value to stack. | 4589 // Move value to stack. |
4775 __ movups(Address(RSP, 0), value); | 4590 __ movups(Address(RSP, 0), value); |
4776 switch (op_kind()) { | 4591 switch (op_kind()) { |
4777 case MethodRecognizer::kInt32x4GetFlagX: | 4592 case MethodRecognizer::kInt32x4GetFlagX: |
(...skipping 14 matching lines...) Expand all Loading... |
4792 __ AddImmediate(RSP, Immediate(16)); | 4607 __ AddImmediate(RSP, Immediate(16)); |
4793 __ testl(result, result); | 4608 __ testl(result, result); |
4794 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4609 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
4795 __ LoadObject(result, Bool::False()); | 4610 __ LoadObject(result, Bool::False()); |
4796 __ jmp(&done); | 4611 __ jmp(&done); |
4797 __ Bind(&non_zero); | 4612 __ Bind(&non_zero); |
4798 __ LoadObject(result, Bool::True()); | 4613 __ LoadObject(result, Bool::True()); |
4799 __ Bind(&done); | 4614 __ Bind(&done); |
4800 } | 4615 } |
4801 | 4616 |
4802 | |
4803 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4617 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
4804 bool opt) const { | 4618 bool opt) const { |
4805 const intptr_t kNumInputs = 3; | 4619 const intptr_t kNumInputs = 3; |
4806 const intptr_t kNumTemps = 1; | 4620 const intptr_t kNumTemps = 1; |
4807 LocationSummary* summary = new (zone) | 4621 LocationSummary* summary = new (zone) |
4808 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4622 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4809 summary->set_in(0, Location::RequiresFpuRegister()); | 4623 summary->set_in(0, Location::RequiresFpuRegister()); |
4810 summary->set_in(1, Location::RequiresFpuRegister()); | 4624 summary->set_in(1, Location::RequiresFpuRegister()); |
4811 summary->set_in(2, Location::RequiresFpuRegister()); | 4625 summary->set_in(2, Location::RequiresFpuRegister()); |
4812 summary->set_temp(0, Location::RequiresFpuRegister()); | 4626 summary->set_temp(0, Location::RequiresFpuRegister()); |
4813 summary->set_out(0, Location::SameAsFirstInput()); | 4627 summary->set_out(0, Location::SameAsFirstInput()); |
4814 return summary; | 4628 return summary; |
4815 } | 4629 } |
4816 | 4630 |
4817 | |
4818 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4631 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4819 XmmRegister mask = locs()->in(0).fpu_reg(); | 4632 XmmRegister mask = locs()->in(0).fpu_reg(); |
4820 XmmRegister trueValue = locs()->in(1).fpu_reg(); | 4633 XmmRegister trueValue = locs()->in(1).fpu_reg(); |
4821 XmmRegister falseValue = locs()->in(2).fpu_reg(); | 4634 XmmRegister falseValue = locs()->in(2).fpu_reg(); |
4822 XmmRegister out = locs()->out(0).fpu_reg(); | 4635 XmmRegister out = locs()->out(0).fpu_reg(); |
4823 XmmRegister temp = locs()->temp(0).fpu_reg(); | 4636 XmmRegister temp = locs()->temp(0).fpu_reg(); |
4824 ASSERT(out == mask); | 4637 ASSERT(out == mask); |
4825 // Copy mask. | 4638 // Copy mask. |
4826 __ movaps(temp, mask); | 4639 __ movaps(temp, mask); |
4827 // Invert it. | 4640 // Invert it. |
4828 __ notps(temp); | 4641 __ notps(temp); |
4829 // mask = mask & trueValue. | 4642 // mask = mask & trueValue. |
4830 __ andps(mask, trueValue); | 4643 __ andps(mask, trueValue); |
4831 // temp = temp & falseValue. | 4644 // temp = temp & falseValue. |
4832 __ andps(temp, falseValue); | 4645 __ andps(temp, falseValue); |
4833 // out = mask | temp. | 4646 // out = mask | temp. |
4834 __ orps(mask, temp); | 4647 __ orps(mask, temp); |
4835 } | 4648 } |
4836 | 4649 |
4837 | |
4838 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4650 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
4839 bool opt) const { | 4651 bool opt) const { |
4840 const intptr_t kNumInputs = 2; | 4652 const intptr_t kNumInputs = 2; |
4841 const intptr_t kNumTemps = 1; | 4653 const intptr_t kNumTemps = 1; |
4842 LocationSummary* summary = new (zone) | 4654 LocationSummary* summary = new (zone) |
4843 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4655 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4844 summary->set_in(0, Location::RequiresFpuRegister()); | 4656 summary->set_in(0, Location::RequiresFpuRegister()); |
4845 summary->set_in(1, Location::RequiresRegister()); | 4657 summary->set_in(1, Location::RequiresRegister()); |
4846 summary->set_temp(0, Location::RequiresRegister()); | 4658 summary->set_temp(0, Location::RequiresRegister()); |
4847 summary->set_out(0, Location::SameAsFirstInput()); | 4659 summary->set_out(0, Location::SameAsFirstInput()); |
4848 return summary; | 4660 return summary; |
4849 } | 4661 } |
4850 | 4662 |
4851 | |
4852 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4663 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4853 XmmRegister mask = locs()->in(0).fpu_reg(); | 4664 XmmRegister mask = locs()->in(0).fpu_reg(); |
4854 Register flag = locs()->in(1).reg(); | 4665 Register flag = locs()->in(1).reg(); |
4855 Register temp = locs()->temp(0).reg(); | 4666 Register temp = locs()->temp(0).reg(); |
4856 ASSERT(mask == locs()->out(0).fpu_reg()); | 4667 ASSERT(mask == locs()->out(0).fpu_reg()); |
4857 __ AddImmediate(RSP, Immediate(-16)); | 4668 __ AddImmediate(RSP, Immediate(-16)); |
4858 // Copy mask to stack. | 4669 // Copy mask to stack. |
4859 __ movups(Address(RSP, 0), mask); | 4670 __ movups(Address(RSP, 0), mask); |
4860 Label falsePath, exitPath; | 4671 Label falsePath, exitPath; |
4861 __ CompareObject(flag, Bool::True()); | 4672 __ CompareObject(flag, Bool::True()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4895 break; | 4706 break; |
4896 default: | 4707 default: |
4897 UNREACHABLE(); | 4708 UNREACHABLE(); |
4898 } | 4709 } |
4899 __ Bind(&exitPath); | 4710 __ Bind(&exitPath); |
4900 // Copy mask back to register. | 4711 // Copy mask back to register. |
4901 __ movups(mask, Address(RSP, 0)); | 4712 __ movups(mask, Address(RSP, 0)); |
4902 __ AddImmediate(RSP, Immediate(16)); | 4713 __ AddImmediate(RSP, Immediate(16)); |
4903 } | 4714 } |
4904 | 4715 |
4905 | |
4906 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4716 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
4907 bool opt) const { | 4717 bool opt) const { |
4908 const intptr_t kNumInputs = 1; | 4718 const intptr_t kNumInputs = 1; |
4909 const intptr_t kNumTemps = 0; | 4719 const intptr_t kNumTemps = 0; |
4910 LocationSummary* summary = new (zone) | 4720 LocationSummary* summary = new (zone) |
4911 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4912 summary->set_in(0, Location::RequiresFpuRegister()); | 4722 summary->set_in(0, Location::RequiresFpuRegister()); |
4913 summary->set_out(0, Location::SameAsFirstInput()); | 4723 summary->set_out(0, Location::SameAsFirstInput()); |
4914 return summary; | 4724 return summary; |
4915 } | 4725 } |
4916 | 4726 |
4917 | |
4918 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4727 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4919 // NOP. | 4728 // NOP. |
4920 } | 4729 } |
4921 | 4730 |
4922 | |
4923 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4731 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
4924 bool opt) const { | 4732 bool opt) const { |
4925 const intptr_t kNumInputs = 2; | 4733 const intptr_t kNumInputs = 2; |
4926 const intptr_t kNumTemps = 0; | 4734 const intptr_t kNumTemps = 0; |
4927 LocationSummary* summary = new (zone) | 4735 LocationSummary* summary = new (zone) |
4928 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4736 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4929 summary->set_in(0, Location::RequiresFpuRegister()); | 4737 summary->set_in(0, Location::RequiresFpuRegister()); |
4930 summary->set_in(1, Location::RequiresFpuRegister()); | 4738 summary->set_in(1, Location::RequiresFpuRegister()); |
4931 summary->set_out(0, Location::SameAsFirstInput()); | 4739 summary->set_out(0, Location::SameAsFirstInput()); |
4932 return summary; | 4740 return summary; |
4933 } | 4741 } |
4934 | 4742 |
4935 | |
4936 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4743 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4937 XmmRegister left = locs()->in(0).fpu_reg(); | 4744 XmmRegister left = locs()->in(0).fpu_reg(); |
4938 XmmRegister right = locs()->in(1).fpu_reg(); | 4745 XmmRegister right = locs()->in(1).fpu_reg(); |
4939 ASSERT(left == locs()->out(0).fpu_reg()); | 4746 ASSERT(left == locs()->out(0).fpu_reg()); |
4940 switch (op_kind()) { | 4747 switch (op_kind()) { |
4941 case Token::kBIT_AND: { | 4748 case Token::kBIT_AND: { |
4942 __ andps(left, right); | 4749 __ andps(left, right); |
4943 break; | 4750 break; |
4944 } | 4751 } |
4945 case Token::kBIT_OR: { | 4752 case Token::kBIT_OR: { |
4946 __ orps(left, right); | 4753 __ orps(left, right); |
4947 break; | 4754 break; |
4948 } | 4755 } |
4949 case Token::kBIT_XOR: { | 4756 case Token::kBIT_XOR: { |
4950 __ xorps(left, right); | 4757 __ xorps(left, right); |
4951 break; | 4758 break; |
4952 } | 4759 } |
4953 case Token::kADD: | 4760 case Token::kADD: |
4954 __ addpl(left, right); | 4761 __ addpl(left, right); |
4955 break; | 4762 break; |
4956 case Token::kSUB: | 4763 case Token::kSUB: |
4957 __ subpl(left, right); | 4764 __ subpl(left, right); |
4958 break; | 4765 break; |
4959 default: | 4766 default: |
4960 UNREACHABLE(); | 4767 UNREACHABLE(); |
4961 } | 4768 } |
4962 } | 4769 } |
4963 | 4770 |
4964 | |
4965 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4771 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
4966 bool opt) const { | 4772 bool opt) const { |
4967 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4773 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
4968 (kind() == MathUnaryInstr::kDoubleSquare)); | 4774 (kind() == MathUnaryInstr::kDoubleSquare)); |
4969 const intptr_t kNumInputs = 1; | 4775 const intptr_t kNumInputs = 1; |
4970 const intptr_t kNumTemps = 0; | 4776 const intptr_t kNumTemps = 0; |
4971 LocationSummary* summary = new (zone) | 4777 LocationSummary* summary = new (zone) |
4972 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4778 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4973 summary->set_in(0, Location::RequiresFpuRegister()); | 4779 summary->set_in(0, Location::RequiresFpuRegister()); |
4974 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4780 if (kind() == MathUnaryInstr::kDoubleSquare) { |
4975 summary->set_out(0, Location::SameAsFirstInput()); | 4781 summary->set_out(0, Location::SameAsFirstInput()); |
4976 } else { | 4782 } else { |
4977 summary->set_out(0, Location::RequiresFpuRegister()); | 4783 summary->set_out(0, Location::RequiresFpuRegister()); |
4978 } | 4784 } |
4979 return summary; | 4785 return summary; |
4980 } | 4786 } |
4981 | 4787 |
4982 | |
4983 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4788 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4984 if (kind() == MathUnaryInstr::kSqrt) { | 4789 if (kind() == MathUnaryInstr::kSqrt) { |
4985 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4790 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
4986 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4791 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
4987 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4792 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
4988 __ mulsd(value_reg, value_reg); | 4793 __ mulsd(value_reg, value_reg); |
4989 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4794 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
4990 } else { | 4795 } else { |
4991 UNREACHABLE(); | 4796 UNREACHABLE(); |
4992 } | 4797 } |
4993 } | 4798 } |
4994 | 4799 |
4995 | |
4996 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4800 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
4997 Zone* zone, | 4801 Zone* zone, |
4998 bool opt) const { | 4802 bool opt) const { |
4999 const intptr_t kNumTemps = 0; | 4803 const intptr_t kNumTemps = 0; |
5000 LocationSummary* summary = new (zone) | 4804 LocationSummary* summary = new (zone) |
5001 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4805 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5002 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); | 4806 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); |
5003 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); | 4807 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); |
5004 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); | 4808 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); |
5005 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); | 4809 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); |
5006 summary->set_out(0, Location::RegisterLocation(RAX)); | 4810 summary->set_out(0, Location::RegisterLocation(RAX)); |
5007 return summary; | 4811 return summary; |
5008 } | 4812 } |
5009 | 4813 |
5010 | |
5011 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4814 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
5012 FlowGraphCompiler* compiler) { | 4815 FlowGraphCompiler* compiler) { |
5013 // Save RSP. R13 is chosen because it is callee saved so we do not need to | 4816 // Save RSP. R13 is chosen because it is callee saved so we do not need to |
5014 // back it up before calling into the runtime. | 4817 // back it up before calling into the runtime. |
5015 static const Register kSavedSPReg = R13; | 4818 static const Register kSavedSPReg = R13; |
5016 __ movq(kSavedSPReg, RSP); | 4819 __ movq(kSavedSPReg, RSP); |
5017 __ ReserveAlignedFrameSpace(0); | 4820 __ ReserveAlignedFrameSpace(0); |
5018 | 4821 |
5019 // Call the function. Parameters are already in their correct spots. | 4822 // Call the function. Parameters are already in their correct spots. |
5020 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4823 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
5021 | 4824 |
5022 // Restore RSP. | 4825 // Restore RSP. |
5023 __ movq(RSP, kSavedSPReg); | 4826 __ movq(RSP, kSavedSPReg); |
5024 } | 4827 } |
5025 | 4828 |
5026 | |
5027 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4829 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
5028 bool opt) const { | 4830 bool opt) const { |
5029 const intptr_t kNumInputs = 1; | 4831 const intptr_t kNumInputs = 1; |
5030 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 4832 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
5031 LocationSummary::kNoCall); | 4833 LocationSummary::kNoCall); |
5032 } | 4834 } |
5033 | 4835 |
5034 | |
5035 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4836 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5036 Register value = locs()->in(0).reg(); | 4837 Register value = locs()->in(0).reg(); |
5037 ASSERT(value == locs()->out(0).reg()); | 4838 ASSERT(value == locs()->out(0).reg()); |
5038 switch (op_kind()) { | 4839 switch (op_kind()) { |
5039 case Token::kNEGATE: { | 4840 case Token::kNEGATE: { |
5040 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4841 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
5041 __ negq(value); | 4842 __ negq(value); |
5042 __ j(OVERFLOW, deopt); | 4843 __ j(OVERFLOW, deopt); |
5043 break; | 4844 break; |
5044 } | 4845 } |
5045 case Token::kBIT_NOT: | 4846 case Token::kBIT_NOT: |
5046 __ notq(value); | 4847 __ notq(value); |
5047 // Remove inverted smi-tag. | 4848 // Remove inverted smi-tag. |
5048 __ AndImmediate(value, Immediate(~kSmiTagMask)); | 4849 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
5049 break; | 4850 break; |
5050 default: | 4851 default: |
5051 UNREACHABLE(); | 4852 UNREACHABLE(); |
5052 } | 4853 } |
5053 } | 4854 } |
5054 | 4855 |
5055 | |
5056 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4856 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
5057 bool opt) const { | 4857 bool opt) const { |
5058 const intptr_t kNumInputs = 1; | 4858 const intptr_t kNumInputs = 1; |
5059 const intptr_t kNumTemps = 0; | 4859 const intptr_t kNumTemps = 0; |
5060 LocationSummary* summary = new (zone) | 4860 LocationSummary* summary = new (zone) |
5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5062 summary->set_in(0, Location::RequiresFpuRegister()); | 4862 summary->set_in(0, Location::RequiresFpuRegister()); |
5063 summary->set_out(0, Location::SameAsFirstInput()); | 4863 summary->set_out(0, Location::SameAsFirstInput()); |
5064 return summary; | 4864 return summary; |
5065 } | 4865 } |
5066 | 4866 |
5067 | |
5068 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4867 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5069 XmmRegister value = locs()->in(0).fpu_reg(); | 4868 XmmRegister value = locs()->in(0).fpu_reg(); |
5070 ASSERT(locs()->out(0).fpu_reg() == value); | 4869 ASSERT(locs()->out(0).fpu_reg() == value); |
5071 __ DoubleNegate(value); | 4870 __ DoubleNegate(value); |
5072 } | 4871 } |
5073 | 4872 |
5074 | |
5075 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4873 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
5076 bool opt) const { | 4874 bool opt) const { |
5077 if (result_cid() == kDoubleCid) { | 4875 if (result_cid() == kDoubleCid) { |
5078 const intptr_t kNumInputs = 2; | 4876 const intptr_t kNumInputs = 2; |
5079 const intptr_t kNumTemps = 1; | 4877 const intptr_t kNumTemps = 1; |
5080 LocationSummary* summary = new (zone) | 4878 LocationSummary* summary = new (zone) |
5081 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5082 summary->set_in(0, Location::RequiresFpuRegister()); | 4880 summary->set_in(0, Location::RequiresFpuRegister()); |
5083 summary->set_in(1, Location::RequiresFpuRegister()); | 4881 summary->set_in(1, Location::RequiresFpuRegister()); |
5084 // Reuse the left register so that code can be made shorter. | 4882 // Reuse the left register so that code can be made shorter. |
5085 summary->set_out(0, Location::SameAsFirstInput()); | 4883 summary->set_out(0, Location::SameAsFirstInput()); |
5086 summary->set_temp(0, Location::RequiresRegister()); | 4884 summary->set_temp(0, Location::RequiresRegister()); |
5087 return summary; | 4885 return summary; |
5088 } | 4886 } |
5089 ASSERT(result_cid() == kSmiCid); | 4887 ASSERT(result_cid() == kSmiCid); |
5090 const intptr_t kNumInputs = 2; | 4888 const intptr_t kNumInputs = 2; |
5091 const intptr_t kNumTemps = 0; | 4889 const intptr_t kNumTemps = 0; |
5092 LocationSummary* summary = new (zone) | 4890 LocationSummary* summary = new (zone) |
5093 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5094 summary->set_in(0, Location::RequiresRegister()); | 4892 summary->set_in(0, Location::RequiresRegister()); |
5095 summary->set_in(1, Location::RequiresRegister()); | 4893 summary->set_in(1, Location::RequiresRegister()); |
5096 // Reuse the left register so that code can be made shorter. | 4894 // Reuse the left register so that code can be made shorter. |
5097 summary->set_out(0, Location::SameAsFirstInput()); | 4895 summary->set_out(0, Location::SameAsFirstInput()); |
5098 return summary; | 4896 return summary; |
5099 } | 4897 } |
5100 | 4898 |
5101 | |
5102 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4899 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5103 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4900 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
5104 (op_kind() == MethodRecognizer::kMathMax)); | 4901 (op_kind() == MethodRecognizer::kMathMax)); |
5105 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4902 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
5106 if (result_cid() == kDoubleCid) { | 4903 if (result_cid() == kDoubleCid) { |
5107 Label done, returns_nan, are_equal; | 4904 Label done, returns_nan, are_equal; |
5108 XmmRegister left = locs()->in(0).fpu_reg(); | 4905 XmmRegister left = locs()->in(0).fpu_reg(); |
5109 XmmRegister right = locs()->in(1).fpu_reg(); | 4906 XmmRegister right = locs()->in(1).fpu_reg(); |
5110 XmmRegister result = locs()->out(0).fpu_reg(); | 4907 XmmRegister result = locs()->out(0).fpu_reg(); |
5111 Register temp = locs()->temp(0).reg(); | 4908 Register temp = locs()->temp(0).reg(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5154 Register result = locs()->out(0).reg(); | 4951 Register result = locs()->out(0).reg(); |
5155 __ cmpq(left, right); | 4952 __ cmpq(left, right); |
5156 ASSERT(result == left); | 4953 ASSERT(result == left); |
5157 if (is_min) { | 4954 if (is_min) { |
5158 __ cmovgeq(result, right); | 4955 __ cmovgeq(result, right); |
5159 } else { | 4956 } else { |
5160 __ cmovlessq(result, right); | 4957 __ cmovlessq(result, right); |
5161 } | 4958 } |
5162 } | 4959 } |
5163 | 4960 |
5164 | |
5165 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4961 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
5166 bool opt) const { | 4962 bool opt) const { |
5167 const intptr_t kNumInputs = 1; | 4963 const intptr_t kNumInputs = 1; |
5168 const intptr_t kNumTemps = 0; | 4964 const intptr_t kNumTemps = 0; |
5169 LocationSummary* result = new (zone) | 4965 LocationSummary* result = new (zone) |
5170 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5171 result->set_in(0, Location::RequiresRegister()); | 4967 result->set_in(0, Location::RequiresRegister()); |
5172 result->set_out(0, Location::RequiresFpuRegister()); | 4968 result->set_out(0, Location::RequiresFpuRegister()); |
5173 return result; | 4969 return result; |
5174 } | 4970 } |
5175 | 4971 |
5176 | |
5177 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4972 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5178 Register value = locs()->in(0).reg(); | 4973 Register value = locs()->in(0).reg(); |
5179 FpuRegister result = locs()->out(0).fpu_reg(); | 4974 FpuRegister result = locs()->out(0).fpu_reg(); |
5180 __ cvtsi2sdl(result, value); | 4975 __ cvtsi2sdl(result, value); |
5181 } | 4976 } |
5182 | 4977 |
5183 | |
5184 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4978 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
5185 bool opt) const { | 4979 bool opt) const { |
5186 const intptr_t kNumInputs = 1; | 4980 const intptr_t kNumInputs = 1; |
5187 const intptr_t kNumTemps = 0; | 4981 const intptr_t kNumTemps = 0; |
5188 LocationSummary* result = new (zone) | 4982 LocationSummary* result = new (zone) |
5189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4983 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5190 result->set_in(0, Location::WritableRegister()); | 4984 result->set_in(0, Location::WritableRegister()); |
5191 result->set_out(0, Location::RequiresFpuRegister()); | 4985 result->set_out(0, Location::RequiresFpuRegister()); |
5192 return result; | 4986 return result; |
5193 } | 4987 } |
5194 | 4988 |
5195 | |
5196 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4989 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5197 Register value = locs()->in(0).reg(); | 4990 Register value = locs()->in(0).reg(); |
5198 FpuRegister result = locs()->out(0).fpu_reg(); | 4991 FpuRegister result = locs()->out(0).fpu_reg(); |
5199 __ SmiUntag(value); | 4992 __ SmiUntag(value); |
5200 __ cvtsi2sdq(result, value); | 4993 __ cvtsi2sdq(result, value); |
5201 } | 4994 } |
5202 | 4995 |
5203 | |
5204 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 4996 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
5205 bool opt) const { | 4997 bool opt) const { |
5206 UNIMPLEMENTED(); | 4998 UNIMPLEMENTED(); |
5207 return NULL; | 4999 return NULL; |
5208 } | 5000 } |
5209 | 5001 |
5210 | |
5211 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5002 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5212 UNIMPLEMENTED(); | 5003 UNIMPLEMENTED(); |
5213 } | 5004 } |
5214 | 5005 |
5215 | |
5216 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5006 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
5217 bool opt) const { | 5007 bool opt) const { |
5218 const intptr_t kNumInputs = 1; | 5008 const intptr_t kNumInputs = 1; |
5219 const intptr_t kNumTemps = 1; | 5009 const intptr_t kNumTemps = 1; |
5220 LocationSummary* result = new (zone) | 5010 LocationSummary* result = new (zone) |
5221 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5011 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5222 result->set_in(0, Location::RegisterLocation(RCX)); | 5012 result->set_in(0, Location::RegisterLocation(RCX)); |
5223 result->set_out(0, Location::RegisterLocation(RAX)); | 5013 result->set_out(0, Location::RegisterLocation(RAX)); |
5224 result->set_temp(0, Location::RegisterLocation(RBX)); | 5014 result->set_temp(0, Location::RegisterLocation(RBX)); |
5225 return result; | 5015 return result; |
5226 } | 5016 } |
5227 | 5017 |
5228 | |
5229 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5018 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5230 Register result = locs()->out(0).reg(); | 5019 Register result = locs()->out(0).reg(); |
5231 Register value_obj = locs()->in(0).reg(); | 5020 Register value_obj = locs()->in(0).reg(); |
5232 Register temp = locs()->temp(0).reg(); | 5021 Register temp = locs()->temp(0).reg(); |
5233 XmmRegister value_double = XMM0; | 5022 XmmRegister value_double = XMM0; |
5234 ASSERT(result == RAX); | 5023 ASSERT(result == RAX); |
5235 ASSERT(result != value_obj); | 5024 ASSERT(result != value_obj); |
5236 ASSERT(result != temp); | 5025 ASSERT(result != temp); |
5237 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 5026 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
5238 __ cvttsd2siq(result, value_double); | 5027 __ cvttsd2siq(result, value_double); |
(...skipping 13 matching lines...) Expand all Loading... |
5252 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5041 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
5253 const int kTypeArgsLen = 0; | 5042 const int kTypeArgsLen = 0; |
5254 const int kNumberOfArguments = 1; | 5043 const int kNumberOfArguments = 1; |
5255 const Array& kNoArgumentNames = Object::null_array(); | 5044 const Array& kNoArgumentNames = Object::null_array(); |
5256 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 5045 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
5257 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 5046 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
5258 args_info, locs(), ICData::Handle()); | 5047 args_info, locs(), ICData::Handle()); |
5259 __ Bind(&done); | 5048 __ Bind(&done); |
5260 } | 5049 } |
5261 | 5050 |
5262 | |
5263 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5051 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
5264 bool opt) const { | 5052 bool opt) const { |
5265 const intptr_t kNumInputs = 1; | 5053 const intptr_t kNumInputs = 1; |
5266 const intptr_t kNumTemps = 1; | 5054 const intptr_t kNumTemps = 1; |
5267 LocationSummary* result = new (zone) | 5055 LocationSummary* result = new (zone) |
5268 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5056 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5269 result->set_in(0, Location::RequiresFpuRegister()); | 5057 result->set_in(0, Location::RequiresFpuRegister()); |
5270 result->set_out(0, Location::RequiresRegister()); | 5058 result->set_out(0, Location::RequiresRegister()); |
5271 result->set_temp(0, Location::RequiresRegister()); | 5059 result->set_temp(0, Location::RequiresRegister()); |
5272 return result; | 5060 return result; |
5273 } | 5061 } |
5274 | 5062 |
5275 | |
5276 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5063 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5277 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5064 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
5278 Register result = locs()->out(0).reg(); | 5065 Register result = locs()->out(0).reg(); |
5279 XmmRegister value = locs()->in(0).fpu_reg(); | 5066 XmmRegister value = locs()->in(0).fpu_reg(); |
5280 Register temp = locs()->temp(0).reg(); | 5067 Register temp = locs()->temp(0).reg(); |
5281 | 5068 |
5282 __ cvttsd2siq(result, value); | 5069 __ cvttsd2siq(result, value); |
5283 // Overflow is signalled with minint. | 5070 // Overflow is signalled with minint. |
5284 Label do_call, done; | 5071 Label do_call, done; |
5285 // Check for overflow and that it fits into Smi. | 5072 // Check for overflow and that it fits into Smi. |
5286 __ movq(temp, result); | 5073 __ movq(temp, result); |
5287 __ shlq(temp, Immediate(1)); | 5074 __ shlq(temp, Immediate(1)); |
5288 __ j(OVERFLOW, deopt); | 5075 __ j(OVERFLOW, deopt); |
5289 __ SmiTag(result); | 5076 __ SmiTag(result); |
5290 } | 5077 } |
5291 | 5078 |
5292 | |
5293 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5079 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
5294 bool opt) const { | 5080 bool opt) const { |
5295 const intptr_t kNumInputs = 1; | 5081 const intptr_t kNumInputs = 1; |
5296 const intptr_t kNumTemps = 0; | 5082 const intptr_t kNumTemps = 0; |
5297 LocationSummary* result = new (zone) | 5083 LocationSummary* result = new (zone) |
5298 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5084 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5299 result->set_in(0, Location::RequiresFpuRegister()); | 5085 result->set_in(0, Location::RequiresFpuRegister()); |
5300 result->set_out(0, Location::RequiresFpuRegister()); | 5086 result->set_out(0, Location::RequiresFpuRegister()); |
5301 return result; | 5087 return result; |
5302 } | 5088 } |
5303 | 5089 |
5304 | |
5305 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5090 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5306 XmmRegister value = locs()->in(0).fpu_reg(); | 5091 XmmRegister value = locs()->in(0).fpu_reg(); |
5307 XmmRegister result = locs()->out(0).fpu_reg(); | 5092 XmmRegister result = locs()->out(0).fpu_reg(); |
5308 switch (recognized_kind()) { | 5093 switch (recognized_kind()) { |
5309 case MethodRecognizer::kDoubleTruncate: | 5094 case MethodRecognizer::kDoubleTruncate: |
5310 __ roundsd(result, value, Assembler::kRoundToZero); | 5095 __ roundsd(result, value, Assembler::kRoundToZero); |
5311 break; | 5096 break; |
5312 case MethodRecognizer::kDoubleFloor: | 5097 case MethodRecognizer::kDoubleFloor: |
5313 __ roundsd(result, value, Assembler::kRoundDown); | 5098 __ roundsd(result, value, Assembler::kRoundDown); |
5314 break; | 5099 break; |
5315 case MethodRecognizer::kDoubleCeil: | 5100 case MethodRecognizer::kDoubleCeil: |
5316 __ roundsd(result, value, Assembler::kRoundUp); | 5101 __ roundsd(result, value, Assembler::kRoundUp); |
5317 break; | 5102 break; |
5318 default: | 5103 default: |
5319 UNREACHABLE(); | 5104 UNREACHABLE(); |
5320 } | 5105 } |
5321 } | 5106 } |
5322 | 5107 |
5323 | |
5324 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5108 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
5325 bool opt) const { | 5109 bool opt) const { |
5326 const intptr_t kNumInputs = 1; | 5110 const intptr_t kNumInputs = 1; |
5327 const intptr_t kNumTemps = 0; | 5111 const intptr_t kNumTemps = 0; |
5328 LocationSummary* result = new (zone) | 5112 LocationSummary* result = new (zone) |
5329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5113 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5330 result->set_in(0, Location::RequiresFpuRegister()); | 5114 result->set_in(0, Location::RequiresFpuRegister()); |
5331 result->set_out(0, Location::SameAsFirstInput()); | 5115 result->set_out(0, Location::SameAsFirstInput()); |
5332 return result; | 5116 return result; |
5333 } | 5117 } |
5334 | 5118 |
5335 | |
5336 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5119 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5337 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5120 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5338 } | 5121 } |
5339 | 5122 |
5340 | |
5341 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5123 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
5342 bool opt) const { | 5124 bool opt) const { |
5343 const intptr_t kNumInputs = 1; | 5125 const intptr_t kNumInputs = 1; |
5344 const intptr_t kNumTemps = 0; | 5126 const intptr_t kNumTemps = 0; |
5345 LocationSummary* result = new (zone) | 5127 LocationSummary* result = new (zone) |
5346 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5128 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5347 result->set_in(0, Location::RequiresFpuRegister()); | 5129 result->set_in(0, Location::RequiresFpuRegister()); |
5348 result->set_out(0, Location::SameAsFirstInput()); | 5130 result->set_out(0, Location::SameAsFirstInput()); |
5349 return result; | 5131 return result; |
5350 } | 5132 } |
5351 | 5133 |
5352 | |
5353 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5134 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5354 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5135 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5355 } | 5136 } |
5356 | 5137 |
5357 | |
5358 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5138 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
5359 bool opt) const { | 5139 bool opt) const { |
5360 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 5140 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
5361 // double arguments and XMM0 to return the result. Unfortunately | 5141 // double arguments and XMM0 to return the result. Unfortunately |
5362 // currently we can't specify these registers because ParallelMoveResolver | 5142 // currently we can't specify these registers because ParallelMoveResolver |
5363 // assumes that XMM0 is free at all times. | 5143 // assumes that XMM0 is free at all times. |
5364 // TODO(vegorov): allow XMM0 to be used. | 5144 // TODO(vegorov): allow XMM0 to be used. |
5365 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5145 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5366 const intptr_t kNumTemps = | 5146 const intptr_t kNumTemps = |
5367 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5147 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
5368 LocationSummary* result = new (zone) | 5148 LocationSummary* result = new (zone) |
5369 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5149 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5370 ASSERT(R13 != CALLEE_SAVED_TEMP); | 5150 ASSERT(R13 != CALLEE_SAVED_TEMP); |
5371 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); | 5151 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); |
5372 result->set_temp(0, Location::RegisterLocation(R13)); | 5152 result->set_temp(0, Location::RegisterLocation(R13)); |
5373 result->set_in(0, Location::FpuRegisterLocation(XMM2)); | 5153 result->set_in(0, Location::FpuRegisterLocation(XMM2)); |
5374 if (InputCount() == 2) { | 5154 if (InputCount() == 2) { |
5375 result->set_in(1, Location::FpuRegisterLocation(XMM1)); | 5155 result->set_in(1, Location::FpuRegisterLocation(XMM1)); |
5376 } | 5156 } |
5377 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5157 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5378 // Temp index 1. | 5158 // Temp index 1. |
5379 result->set_temp(1, Location::RegisterLocation(RAX)); | 5159 result->set_temp(1, Location::RegisterLocation(RAX)); |
5380 // Temp index 2. | 5160 // Temp index 2. |
5381 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); | 5161 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); |
5382 } | 5162 } |
5383 result->set_out(0, Location::FpuRegisterLocation(XMM3)); | 5163 result->set_out(0, Location::FpuRegisterLocation(XMM3)); |
5384 return result; | 5164 return result; |
5385 } | 5165 } |
5386 | 5166 |
5387 | |
5388 // Pseudo code: | 5167 // Pseudo code: |
5389 // if (exponent == 0.0) return 1.0; | 5168 // if (exponent == 0.0) return 1.0; |
5390 // // Speed up simple cases. | 5169 // // Speed up simple cases. |
5391 // if (exponent == 1.0) return base; | 5170 // if (exponent == 1.0) return base; |
5392 // if (exponent == 2.0) return base * base; | 5171 // if (exponent == 2.0) return base * base; |
5393 // if (exponent == 3.0) return base * base * base; | 5172 // if (exponent == 3.0) return base * base * base; |
5394 // if (base == 1.0) return 1.0; | 5173 // if (base == 1.0) return 1.0; |
5395 // if (base.isNaN || exponent.isNaN) { | 5174 // if (base.isNaN || exponent.isNaN) { |
5396 // return double.NAN; | 5175 // return double.NAN; |
5397 // } | 5176 // } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5510 __ movaps(XMM0, locs->in(0).fpu_reg()); | 5289 __ movaps(XMM0, locs->in(0).fpu_reg()); |
5511 ASSERT(locs->in(1).fpu_reg() == XMM1); | 5290 ASSERT(locs->in(1).fpu_reg() == XMM1); |
5512 | 5291 |
5513 __ CallRuntime(instr->TargetFunction(), kInputCount); | 5292 __ CallRuntime(instr->TargetFunction(), kInputCount); |
5514 __ movaps(locs->out(0).fpu_reg(), XMM0); | 5293 __ movaps(locs->out(0).fpu_reg(), XMM0); |
5515 // Restore RSP. | 5294 // Restore RSP. |
5516 __ movq(RSP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); | 5295 __ movq(RSP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); |
5517 __ Bind(&skip_call); | 5296 __ Bind(&skip_call); |
5518 } | 5297 } |
5519 | 5298 |
5520 | |
5521 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5299 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5522 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5300 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5523 InvokeDoublePow(compiler, this); | 5301 InvokeDoublePow(compiler, this); |
5524 return; | 5302 return; |
5525 } | 5303 } |
5526 // Save RSP. | 5304 // Save RSP. |
5527 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); | 5305 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); |
5528 __ ReserveAlignedFrameSpace(0); | 5306 __ ReserveAlignedFrameSpace(0); |
5529 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 5307 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
5530 if (InputCount() == 2) { | 5308 if (InputCount() == 2) { |
5531 ASSERT(locs()->in(1).fpu_reg() == XMM1); | 5309 ASSERT(locs()->in(1).fpu_reg() == XMM1); |
5532 } | 5310 } |
5533 | 5311 |
5534 __ CallRuntime(TargetFunction(), InputCount()); | 5312 __ CallRuntime(TargetFunction(), InputCount()); |
5535 __ movaps(locs()->out(0).fpu_reg(), XMM0); | 5313 __ movaps(locs()->out(0).fpu_reg(), XMM0); |
5536 // Restore RSP. | 5314 // Restore RSP. |
5537 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 5315 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
5538 } | 5316 } |
5539 | 5317 |
5540 | |
5541 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5318 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
5542 bool opt) const { | 5319 bool opt) const { |
5543 // Only use this instruction in optimized code. | 5320 // Only use this instruction in optimized code. |
5544 ASSERT(opt); | 5321 ASSERT(opt); |
5545 const intptr_t kNumInputs = 1; | 5322 const intptr_t kNumInputs = 1; |
5546 LocationSummary* summary = | 5323 LocationSummary* summary = |
5547 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 5324 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
5548 if (representation() == kUnboxedDouble) { | 5325 if (representation() == kUnboxedDouble) { |
5549 if (index() == 0) { | 5326 if (index() == 0) { |
5550 summary->set_in( | 5327 summary->set_in( |
(...skipping 12 matching lines...) Expand all Loading... |
5563 } else { | 5340 } else { |
5564 ASSERT(index() == 1); | 5341 ASSERT(index() == 1); |
5565 summary->set_in( | 5342 summary->set_in( |
5566 0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 5343 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
5567 } | 5344 } |
5568 summary->set_out(0, Location::RequiresRegister()); | 5345 summary->set_out(0, Location::RequiresRegister()); |
5569 } | 5346 } |
5570 return summary; | 5347 return summary; |
5571 } | 5348 } |
5572 | 5349 |
5573 | |
5574 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5350 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5575 ASSERT(locs()->in(0).IsPairLocation()); | 5351 ASSERT(locs()->in(0).IsPairLocation()); |
5576 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5352 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5577 Location in_loc = pair->At(index()); | 5353 Location in_loc = pair->At(index()); |
5578 if (representation() == kUnboxedDouble) { | 5354 if (representation() == kUnboxedDouble) { |
5579 XmmRegister out = locs()->out(0).fpu_reg(); | 5355 XmmRegister out = locs()->out(0).fpu_reg(); |
5580 XmmRegister in = in_loc.fpu_reg(); | 5356 XmmRegister in = in_loc.fpu_reg(); |
5581 __ movaps(out, in); | 5357 __ movaps(out, in); |
5582 } else { | 5358 } else { |
5583 ASSERT(representation() == kTagged); | 5359 ASSERT(representation() == kTagged); |
5584 Register out = locs()->out(0).reg(); | 5360 Register out = locs()->out(0).reg(); |
5585 Register in = in_loc.reg(); | 5361 Register in = in_loc.reg(); |
5586 __ movq(out, in); | 5362 __ movq(out, in); |
5587 } | 5363 } |
5588 } | 5364 } |
5589 | 5365 |
5590 | |
5591 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, | 5366 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
5592 bool opt) const { | 5367 bool opt) const { |
5593 const intptr_t kNumInputs = 2; | 5368 const intptr_t kNumInputs = 2; |
5594 const intptr_t kNumTemps = 0; | 5369 const intptr_t kNumTemps = 0; |
5595 LocationSummary* summary = new (zone) | 5370 LocationSummary* summary = new (zone) |
5596 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5371 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5597 // Both inputs must be writable because they will be untagged. | 5372 // Both inputs must be writable because they will be untagged. |
5598 summary->set_in(0, Location::RegisterLocation(RAX)); | 5373 summary->set_in(0, Location::RegisterLocation(RAX)); |
5599 summary->set_in(1, Location::WritableRegister()); | 5374 summary->set_in(1, Location::WritableRegister()); |
5600 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), | 5375 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
5601 Location::RegisterLocation(RDX))); | 5376 Location::RegisterLocation(RDX))); |
5602 return summary; | 5377 return summary; |
5603 } | 5378 } |
5604 | 5379 |
5605 | |
5606 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5380 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5607 ASSERT(CanDeoptimize()); | 5381 ASSERT(CanDeoptimize()); |
5608 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5382 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5609 Register left = locs()->in(0).reg(); | 5383 Register left = locs()->in(0).reg(); |
5610 Register right = locs()->in(1).reg(); | 5384 Register right = locs()->in(1).reg(); |
5611 ASSERT(locs()->out(0).IsPairLocation()); | 5385 ASSERT(locs()->out(0).IsPairLocation()); |
5612 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5386 PairLocation* pair = locs()->out(0).AsPairLocation(); |
5613 Register result1 = pair->At(0).reg(); | 5387 Register result1 = pair->At(0).reg(); |
5614 Register result2 = pair->At(1).reg(); | 5388 Register result2 = pair->At(1).reg(); |
5615 Label not_32bit, done; | 5389 Label not_32bit, done; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5685 __ subq(RDX, right); | 5459 __ subq(RDX, right); |
5686 } | 5460 } |
5687 __ Bind(&all_done); | 5461 __ Bind(&all_done); |
5688 | 5462 |
5689 __ SmiTag(RAX); | 5463 __ SmiTag(RAX); |
5690 __ SmiTag(RDX); | 5464 __ SmiTag(RDX); |
5691 // Note that the result of an integer division/modulo of two | 5465 // Note that the result of an integer division/modulo of two |
5692 // in-range arguments, cannot create out-of-range result. | 5466 // in-range arguments, cannot create out-of-range result. |
5693 } | 5467 } |
5694 | 5468 |
5695 | |
5696 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5469 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5697 Zone* zone, | 5470 Zone* zone, |
5698 bool opt) const { | 5471 bool opt) const { |
5699 return MakeCallSummary(zone); | 5472 return MakeCallSummary(zone); |
5700 } | 5473 } |
5701 | 5474 |
5702 | |
5703 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5475 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5704 comparison()->InitializeLocationSummary(zone, opt); | 5476 comparison()->InitializeLocationSummary(zone, opt); |
5705 // Branches don't produce a result. | 5477 // Branches don't produce a result. |
5706 comparison()->locs()->set_out(0, Location::NoLocation()); | 5478 comparison()->locs()->set_out(0, Location::NoLocation()); |
5707 return comparison()->locs(); | 5479 return comparison()->locs(); |
5708 } | 5480 } |
5709 | 5481 |
5710 | |
5711 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5482 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5712 comparison()->EmitBranchCode(compiler, this); | 5483 comparison()->EmitBranchCode(compiler, this); |
5713 } | 5484 } |
5714 | 5485 |
5715 | |
5716 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5486 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5717 bool opt) const { | 5487 bool opt) const { |
5718 const intptr_t kNumInputs = 1; | 5488 const intptr_t kNumInputs = 1; |
5719 const bool need_mask_temp = IsBitTest(); | 5489 const bool need_mask_temp = IsBitTest(); |
5720 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5490 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5721 LocationSummary* summary = new (zone) | 5491 LocationSummary* summary = new (zone) |
5722 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5492 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5723 summary->set_in(0, Location::RequiresRegister()); | 5493 summary->set_in(0, Location::RequiresRegister()); |
5724 if (!IsNullCheck()) { | 5494 if (!IsNullCheck()) { |
5725 summary->set_temp(0, Location::RequiresRegister()); | 5495 summary->set_temp(0, Location::RequiresRegister()); |
5726 if (need_mask_temp) { | 5496 if (need_mask_temp) { |
5727 summary->set_temp(1, Location::RequiresRegister()); | 5497 summary->set_temp(1, Location::RequiresRegister()); |
5728 } | 5498 } |
5729 } | 5499 } |
5730 return summary; | 5500 return summary; |
5731 } | 5501 } |
5732 | 5502 |
5733 | |
5734 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { | 5503 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
5735 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5504 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
5736 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; | 5505 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; |
5737 __ j(cond, deopt); | 5506 __ j(cond, deopt); |
5738 } | 5507 } |
5739 | 5508 |
5740 | |
5741 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | 5509 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, |
5742 intptr_t min, | 5510 intptr_t min, |
5743 intptr_t max, | 5511 intptr_t max, |
5744 intptr_t mask, | 5512 intptr_t mask, |
5745 Label* deopt) { | 5513 Label* deopt) { |
5746 Register biased_cid = locs()->temp(0).reg(); | 5514 Register biased_cid = locs()->temp(0).reg(); |
5747 __ subq(biased_cid, Immediate(min)); | 5515 __ subq(biased_cid, Immediate(min)); |
5748 __ cmpq(biased_cid, Immediate(max - min)); | 5516 __ cmpq(biased_cid, Immediate(max - min)); |
5749 __ j(ABOVE, deopt); | 5517 __ j(ABOVE, deopt); |
5750 | 5518 |
5751 Register mask_reg = locs()->temp(1).reg(); | 5519 Register mask_reg = locs()->temp(1).reg(); |
5752 __ movq(mask_reg, Immediate(mask)); | 5520 __ movq(mask_reg, Immediate(mask)); |
5753 __ btq(mask_reg, biased_cid); | 5521 __ btq(mask_reg, biased_cid); |
5754 __ j(NOT_CARRY, deopt); | 5522 __ j(NOT_CARRY, deopt); |
5755 } | 5523 } |
5756 | 5524 |
5757 | |
5758 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | 5525 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, |
5759 int bias, | 5526 int bias, |
5760 intptr_t cid_start, | 5527 intptr_t cid_start, |
5761 intptr_t cid_end, | 5528 intptr_t cid_end, |
5762 bool is_last, | 5529 bool is_last, |
5763 Label* is_ok, | 5530 Label* is_ok, |
5764 Label* deopt, | 5531 Label* deopt, |
5765 bool use_near_jump) { | 5532 bool use_near_jump) { |
5766 Register biased_cid = locs()->temp(0).reg(); | 5533 Register biased_cid = locs()->temp(0).reg(); |
5767 Condition no_match, match; | 5534 Condition no_match, match; |
(...skipping 16 matching lines...) Expand all Loading... |
5784 } else { | 5551 } else { |
5785 if (use_near_jump) { | 5552 if (use_near_jump) { |
5786 __ j(match, is_ok, Assembler::kNearJump); | 5553 __ j(match, is_ok, Assembler::kNearJump); |
5787 } else { | 5554 } else { |
5788 __ j(match, is_ok); | 5555 __ j(match, is_ok); |
5789 } | 5556 } |
5790 } | 5557 } |
5791 return bias; | 5558 return bias; |
5792 } | 5559 } |
5793 | 5560 |
5794 | |
5795 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5561 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5796 bool opt) const { | 5562 bool opt) const { |
5797 const intptr_t kNumInputs = 1; | 5563 const intptr_t kNumInputs = 1; |
5798 const intptr_t kNumTemps = 0; | 5564 const intptr_t kNumTemps = 0; |
5799 LocationSummary* summary = new (zone) | 5565 LocationSummary* summary = new (zone) |
5800 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5566 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5801 summary->set_in(0, Location::RequiresRegister()); | 5567 summary->set_in(0, Location::RequiresRegister()); |
5802 return summary; | 5568 return summary; |
5803 } | 5569 } |
5804 | 5570 |
5805 | |
5806 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5571 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5807 Register value = locs()->in(0).reg(); | 5572 Register value = locs()->in(0).reg(); |
5808 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 5573 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
5809 licm_hoisted_ ? ICData::kHoisted : 0); | 5574 licm_hoisted_ ? ICData::kHoisted : 0); |
5810 __ BranchIfNotSmi(value, deopt); | 5575 __ BranchIfNotSmi(value, deopt); |
5811 } | 5576 } |
5812 | 5577 |
5813 | |
5814 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5578 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5815 bool opt) const { | 5579 bool opt) const { |
5816 const intptr_t kNumInputs = 1; | 5580 const intptr_t kNumInputs = 1; |
5817 const intptr_t kNumTemps = 0; | 5581 const intptr_t kNumTemps = 0; |
5818 LocationSummary* summary = new (zone) | 5582 LocationSummary* summary = new (zone) |
5819 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5583 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5820 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() | 5584 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() |
5821 : Location::WritableRegister()); | 5585 : Location::WritableRegister()); |
5822 return summary; | 5586 return summary; |
5823 } | 5587 } |
5824 | 5588 |
5825 | |
5826 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5589 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5827 Register value = locs()->in(0).reg(); | 5590 Register value = locs()->in(0).reg(); |
5828 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5591 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
5829 if (cids_.IsSingleCid()) { | 5592 if (cids_.IsSingleCid()) { |
5830 __ CompareImmediate(value, Immediate(Smi::RawValue(cids_.cid_start))); | 5593 __ CompareImmediate(value, Immediate(Smi::RawValue(cids_.cid_start))); |
5831 __ j(NOT_ZERO, deopt); | 5594 __ j(NOT_ZERO, deopt); |
5832 } else { | 5595 } else { |
5833 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); | 5596 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); |
5834 __ cmpq(value, Immediate(Smi::RawValue(cids_.Extent()))); | 5597 __ cmpq(value, Immediate(Smi::RawValue(cids_.Extent()))); |
5835 __ j(ABOVE, deopt); | 5598 __ j(ABOVE, deopt); |
5836 } | 5599 } |
5837 } | 5600 } |
5838 | 5601 |
5839 | |
5840 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5602 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
5841 bool opt) const { | 5603 bool opt) const { |
5842 const intptr_t kNumInputs = 2; | 5604 const intptr_t kNumInputs = 2; |
5843 const intptr_t kNumTemps = 0; | 5605 const intptr_t kNumTemps = 0; |
5844 LocationSummary* locs = new (zone) LocationSummary( | 5606 LocationSummary* locs = new (zone) LocationSummary( |
5845 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5607 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
5846 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5608 locs->set_in(kLengthPos, Location::RequiresRegister()); |
5847 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5609 locs->set_in(kIndexPos, Location::RequiresRegister()); |
5848 return locs; | 5610 return locs; |
5849 } | 5611 } |
5850 | 5612 |
5851 | |
5852 class RangeErrorSlowPath : public SlowPathCode { | 5613 class RangeErrorSlowPath : public SlowPathCode { |
5853 public: | 5614 public: |
5854 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5615 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
5855 : instruction_(instruction), try_index_(try_index) {} | 5616 : instruction_(instruction), try_index_(try_index) {} |
5856 | 5617 |
5857 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5618 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5858 if (Assembler::EmittingComments()) { | 5619 if (Assembler::EmittingComments()) { |
5859 __ Comment("slow path check bound operation"); | 5620 __ Comment("slow path check bound operation"); |
5860 } | 5621 } |
5861 __ Bind(entry_label()); | 5622 __ Bind(entry_label()); |
5862 LocationSummary* locs = instruction_->locs(); | 5623 LocationSummary* locs = instruction_->locs(); |
5863 compiler->SaveLiveRegisters(locs); | 5624 compiler->SaveLiveRegisters(locs); |
5864 __ pushq(locs->in(0).reg()); | 5625 __ pushq(locs->in(0).reg()); |
5865 __ pushq(locs->in(1).reg()); | 5626 __ pushq(locs->in(1).reg()); |
5866 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5627 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
5867 compiler->AddDescriptor( | 5628 compiler->AddDescriptor( |
5868 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), | 5629 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
5869 instruction_->deopt_id(), instruction_->token_pos(), try_index_); | 5630 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
5870 compiler->RecordSafepoint(locs, 2); | 5631 compiler->RecordSafepoint(locs, 2); |
5871 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 5632 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
5872 compiler->EmitCatchEntryState(env, try_index_); | 5633 compiler->EmitCatchEntryState(env, try_index_); |
5873 __ int3(); | 5634 __ int3(); |
5874 } | 5635 } |
5875 | 5636 |
5876 private: | 5637 private: |
5877 GenericCheckBoundInstr* instruction_; | 5638 GenericCheckBoundInstr* instruction_; |
5878 intptr_t try_index_; | 5639 intptr_t try_index_; |
5879 }; | 5640 }; |
5880 | 5641 |
5881 | |
5882 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5642 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5883 RangeErrorSlowPath* slow_path = | 5643 RangeErrorSlowPath* slow_path = |
5884 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); | 5644 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); |
5885 compiler->AddSlowPathCode(slow_path); | 5645 compiler->AddSlowPathCode(slow_path); |
5886 Location length_loc = locs()->in(kLengthPos); | 5646 Location length_loc = locs()->in(kLengthPos); |
5887 Location index_loc = locs()->in(kIndexPos); | 5647 Location index_loc = locs()->in(kIndexPos); |
5888 Register length = length_loc.reg(); | 5648 Register length = length_loc.reg(); |
5889 Register index = index_loc.reg(); | 5649 Register index = index_loc.reg(); |
5890 const intptr_t index_cid = this->index()->Type()->ToCid(); | 5650 const intptr_t index_cid = this->index()->Type()->ToCid(); |
5891 if (index_cid != kSmiCid) { | 5651 if (index_cid != kSmiCid) { |
5892 __ BranchIfNotSmi(index, slow_path->entry_label()); | 5652 __ BranchIfNotSmi(index, slow_path->entry_label()); |
5893 } | 5653 } |
5894 __ cmpq(index, length); | 5654 __ cmpq(index, length); |
5895 __ j(ABOVE_EQUAL, slow_path->entry_label()); | 5655 __ j(ABOVE_EQUAL, slow_path->entry_label()); |
5896 } | 5656 } |
5897 | 5657 |
5898 | |
5899 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5658 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
5900 bool opt) const { | 5659 bool opt) const { |
5901 const intptr_t kNumInputs = 2; | 5660 const intptr_t kNumInputs = 2; |
5902 const intptr_t kNumTemps = 0; | 5661 const intptr_t kNumTemps = 0; |
5903 LocationSummary* locs = new (zone) | 5662 LocationSummary* locs = new (zone) |
5904 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5663 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5905 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5664 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
5906 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5665 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
5907 return locs; | 5666 return locs; |
5908 } | 5667 } |
5909 | 5668 |
5910 | |
5911 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5669 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5912 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5670 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
5913 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5671 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
5914 Label* deopt = | 5672 Label* deopt = |
5915 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 5673 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
5916 | 5674 |
5917 Location length_loc = locs()->in(kLengthPos); | 5675 Location length_loc = locs()->in(kLengthPos); |
5918 Location index_loc = locs()->in(kIndexPos); | 5676 Location index_loc = locs()->in(kIndexPos); |
5919 | 5677 |
5920 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5678 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5952 Register length = length_loc.reg(); | 5710 Register length = length_loc.reg(); |
5953 Register index = index_loc.reg(); | 5711 Register index = index_loc.reg(); |
5954 if (index_cid != kSmiCid) { | 5712 if (index_cid != kSmiCid) { |
5955 __ BranchIfNotSmi(index, deopt); | 5713 __ BranchIfNotSmi(index, deopt); |
5956 } | 5714 } |
5957 __ cmpq(index, length); | 5715 __ cmpq(index, length); |
5958 __ j(ABOVE_EQUAL, deopt); | 5716 __ j(ABOVE_EQUAL, deopt); |
5959 } | 5717 } |
5960 } | 5718 } |
5961 | 5719 |
5962 | |
5963 template <typename OperandType> | 5720 template <typename OperandType> |
5964 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, | 5721 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, |
5965 Token::Kind op_kind, | 5722 Token::Kind op_kind, |
5966 Register left, | 5723 Register left, |
5967 const OperandType& right, | 5724 const OperandType& right, |
5968 Label* deopt) { | 5725 Label* deopt) { |
5969 switch (op_kind) { | 5726 switch (op_kind) { |
5970 case Token::kADD: | 5727 case Token::kADD: |
5971 __ addq(left, right); | 5728 __ addq(left, right); |
5972 break; | 5729 break; |
(...skipping 11 matching lines...) Expand all Loading... |
5984 break; | 5741 break; |
5985 case Token::kMUL: | 5742 case Token::kMUL: |
5986 __ imulq(left, right); | 5743 __ imulq(left, right); |
5987 break; | 5744 break; |
5988 default: | 5745 default: |
5989 UNREACHABLE(); | 5746 UNREACHABLE(); |
5990 } | 5747 } |
5991 if (deopt != NULL) __ j(OVERFLOW, deopt); | 5748 if (deopt != NULL) __ j(OVERFLOW, deopt); |
5992 } | 5749 } |
5993 | 5750 |
5994 | |
5995 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5751 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
5996 bool opt) const { | 5752 bool opt) const { |
5997 const intptr_t kNumInputs = 2; | 5753 const intptr_t kNumInputs = 2; |
5998 const intptr_t kNumTemps = 0; | 5754 const intptr_t kNumTemps = 0; |
5999 LocationSummary* summary = new (zone) | 5755 LocationSummary* summary = new (zone) |
6000 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6001 summary->set_in(0, Location::RequiresRegister()); | 5757 summary->set_in(0, Location::RequiresRegister()); |
6002 summary->set_in(1, Location::RequiresRegister()); | 5758 summary->set_in(1, Location::RequiresRegister()); |
6003 summary->set_out(0, Location::SameAsFirstInput()); | 5759 summary->set_out(0, Location::SameAsFirstInput()); |
6004 return summary; | 5760 return summary; |
6005 } | 5761 } |
6006 | 5762 |
6007 | |
6008 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5763 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6009 const Register left = locs()->in(0).reg(); | 5764 const Register left = locs()->in(0).reg(); |
6010 const Register right = locs()->in(1).reg(); | 5765 const Register right = locs()->in(1).reg(); |
6011 const Register out = locs()->out(0).reg(); | 5766 const Register out = locs()->out(0).reg(); |
6012 | 5767 |
6013 ASSERT(out == left); | 5768 ASSERT(out == left); |
6014 | 5769 |
6015 Label* deopt = NULL; | 5770 Label* deopt = NULL; |
6016 if (CanDeoptimize()) { | 5771 if (CanDeoptimize()) { |
6017 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5772 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6018 } | 5773 } |
6019 | 5774 |
6020 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | 5775 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
6021 } | 5776 } |
6022 | 5777 |
6023 | |
6024 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5778 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6025 bool opt) const { | 5779 bool opt) const { |
6026 const intptr_t kNumInputs = 1; | 5780 const intptr_t kNumInputs = 1; |
6027 const intptr_t kNumTemps = 0; | 5781 const intptr_t kNumTemps = 0; |
6028 LocationSummary* summary = new (zone) | 5782 LocationSummary* summary = new (zone) |
6029 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6030 summary->set_in(0, Location::RequiresRegister()); | 5784 summary->set_in(0, Location::RequiresRegister()); |
6031 summary->set_out(0, Location::SameAsFirstInput()); | 5785 summary->set_out(0, Location::SameAsFirstInput()); |
6032 return summary; | 5786 return summary; |
6033 } | 5787 } |
6034 | 5788 |
6035 | |
6036 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5789 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6037 ASSERT(op_kind() == Token::kBIT_NOT); | 5790 ASSERT(op_kind() == Token::kBIT_NOT); |
6038 const Register left = locs()->in(0).reg(); | 5791 const Register left = locs()->in(0).reg(); |
6039 const Register out = locs()->out(0).reg(); | 5792 const Register out = locs()->out(0).reg(); |
6040 ASSERT(out == left); | 5793 ASSERT(out == left); |
6041 __ notq(left); | 5794 __ notq(left); |
6042 } | 5795 } |
6043 | 5796 |
6044 | |
6045 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5797 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
6046 bool opt) const { | 5798 bool opt) const { |
6047 const intptr_t kNumInputs = 2; | 5799 const intptr_t kNumInputs = 2; |
6048 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 5800 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
6049 LocationSummary* summary = new (zone) | 5801 LocationSummary* summary = new (zone) |
6050 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5802 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6051 summary->set_in(0, Location::RequiresRegister()); | 5803 summary->set_in(0, Location::RequiresRegister()); |
6052 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 5804 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
6053 if (kNumTemps > 0) { | 5805 if (kNumTemps > 0) { |
6054 summary->set_temp(0, Location::RequiresRegister()); | 5806 summary->set_temp(0, Location::RequiresRegister()); |
6055 } | 5807 } |
6056 summary->set_out(0, Location::SameAsFirstInput()); | 5808 summary->set_out(0, Location::SameAsFirstInput()); |
6057 return summary; | 5809 return summary; |
6058 } | 5810 } |
6059 | 5811 |
6060 | |
6061 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5812 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6062 const Register left = locs()->in(0).reg(); | 5813 const Register left = locs()->in(0).reg(); |
6063 const Register out = locs()->out(0).reg(); | 5814 const Register out = locs()->out(0).reg(); |
6064 ASSERT(left == out); | 5815 ASSERT(left == out); |
6065 | 5816 |
6066 Label* deopt = NULL; | 5817 Label* deopt = NULL; |
6067 if (CanDeoptimize()) { | 5818 if (CanDeoptimize()) { |
6068 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5819 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6069 } | 5820 } |
6070 if (locs()->in(1).IsConstant()) { | 5821 if (locs()->in(1).IsConstant()) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6124 // Shift for result now we know there is no overflow. | 5875 // Shift for result now we know there is no overflow. |
6125 __ shlq(left, RCX); | 5876 __ shlq(left, RCX); |
6126 break; | 5877 break; |
6127 } | 5878 } |
6128 default: | 5879 default: |
6129 UNREACHABLE(); | 5880 UNREACHABLE(); |
6130 } | 5881 } |
6131 } | 5882 } |
6132 } | 5883 } |
6133 | 5884 |
6134 | |
6135 CompileType BinaryUint32OpInstr::ComputeType() const { | 5885 CompileType BinaryUint32OpInstr::ComputeType() const { |
6136 return CompileType::FromCid(kSmiCid); | 5886 return CompileType::FromCid(kSmiCid); |
6137 } | 5887 } |
6138 | 5888 |
6139 | |
6140 CompileType ShiftUint32OpInstr::ComputeType() const { | 5889 CompileType ShiftUint32OpInstr::ComputeType() const { |
6141 return CompileType::FromCid(kSmiCid); | 5890 return CompileType::FromCid(kSmiCid); |
6142 } | 5891 } |
6143 | 5892 |
6144 | |
6145 CompileType UnaryUint32OpInstr::ComputeType() const { | 5893 CompileType UnaryUint32OpInstr::ComputeType() const { |
6146 return CompileType::FromCid(kSmiCid); | 5894 return CompileType::FromCid(kSmiCid); |
6147 } | 5895 } |
6148 | 5896 |
6149 | |
6150 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5897 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6151 bool opt) const { | 5898 bool opt) const { |
6152 const intptr_t kNumInputs = 2; | 5899 const intptr_t kNumInputs = 2; |
6153 const intptr_t kNumTemps = 0; | 5900 const intptr_t kNumTemps = 0; |
6154 LocationSummary* summary = new (zone) | 5901 LocationSummary* summary = new (zone) |
6155 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5902 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6156 summary->set_in(0, Location::RequiresRegister()); | 5903 summary->set_in(0, Location::RequiresRegister()); |
6157 summary->set_in(1, Location::RequiresRegister()); | 5904 summary->set_in(1, Location::RequiresRegister()); |
6158 summary->set_out(0, Location::SameAsFirstInput()); | 5905 summary->set_out(0, Location::SameAsFirstInput()); |
6159 return summary; | 5906 return summary; |
6160 } | 5907 } |
6161 | 5908 |
6162 | |
6163 template <typename OperandType> | 5909 template <typename OperandType> |
6164 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 5910 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
6165 Token::Kind op_kind, | 5911 Token::Kind op_kind, |
6166 Register left, | 5912 Register left, |
6167 const OperandType& right, | 5913 const OperandType& right, |
6168 Label* deopt) { | 5914 Label* deopt) { |
6169 switch (op_kind) { | 5915 switch (op_kind) { |
6170 case Token::kADD: | 5916 case Token::kADD: |
6171 __ addl(left, right); | 5917 __ addl(left, right); |
6172 break; | 5918 break; |
(...skipping 11 matching lines...) Expand all Loading... |
6184 break; | 5930 break; |
6185 case Token::kMUL: | 5931 case Token::kMUL: |
6186 __ imull(left, right); | 5932 __ imull(left, right); |
6187 break; | 5933 break; |
6188 default: | 5934 default: |
6189 UNREACHABLE(); | 5935 UNREACHABLE(); |
6190 } | 5936 } |
6191 if (deopt != NULL) __ j(OVERFLOW, deopt); | 5937 if (deopt != NULL) __ j(OVERFLOW, deopt); |
6192 } | 5938 } |
6193 | 5939 |
6194 | |
6195 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5940 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6196 Register left = locs()->in(0).reg(); | 5941 Register left = locs()->in(0).reg(); |
6197 Register right = locs()->in(1).reg(); | 5942 Register right = locs()->in(1).reg(); |
6198 Register out = locs()->out(0).reg(); | 5943 Register out = locs()->out(0).reg(); |
6199 ASSERT(out == left); | 5944 ASSERT(out == left); |
6200 switch (op_kind()) { | 5945 switch (op_kind()) { |
6201 case Token::kBIT_AND: | 5946 case Token::kBIT_AND: |
6202 case Token::kBIT_OR: | 5947 case Token::kBIT_OR: |
6203 case Token::kBIT_XOR: | 5948 case Token::kBIT_XOR: |
6204 case Token::kADD: | 5949 case Token::kADD: |
6205 case Token::kSUB: | 5950 case Token::kSUB: |
6206 case Token::kMUL: | 5951 case Token::kMUL: |
6207 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | 5952 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); |
6208 return; | 5953 return; |
6209 default: | 5954 default: |
6210 UNREACHABLE(); | 5955 UNREACHABLE(); |
6211 } | 5956 } |
6212 } | 5957 } |
6213 | 5958 |
6214 | |
6215 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 5959 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
6216 bool opt) const { | 5960 bool opt) const { |
6217 const intptr_t kNumInputs = 2; | 5961 const intptr_t kNumInputs = 2; |
6218 const intptr_t kNumTemps = 0; | 5962 const intptr_t kNumTemps = 0; |
6219 LocationSummary* summary = new (zone) | 5963 LocationSummary* summary = new (zone) |
6220 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5964 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6221 summary->set_in(0, Location::RequiresRegister()); | 5965 summary->set_in(0, Location::RequiresRegister()); |
6222 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 5966 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
6223 summary->set_out(0, Location::SameAsFirstInput()); | 5967 summary->set_out(0, Location::SameAsFirstInput()); |
6224 return summary; | 5968 return summary; |
6225 } | 5969 } |
6226 | 5970 |
6227 | |
6228 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5971 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6229 const intptr_t kShifterLimit = 31; | 5972 const intptr_t kShifterLimit = 31; |
6230 | 5973 |
6231 Register left = locs()->in(0).reg(); | 5974 Register left = locs()->in(0).reg(); |
6232 Register out = locs()->out(0).reg(); | 5975 Register out = locs()->out(0).reg(); |
6233 ASSERT(left == out); | 5976 ASSERT(left == out); |
6234 | 5977 |
6235 | |
6236 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5978 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6237 | 5979 |
6238 if (locs()->in(1).IsConstant()) { | 5980 if (locs()->in(1).IsConstant()) { |
6239 // Shifter is constant. | 5981 // Shifter is constant. |
6240 | 5982 |
6241 const Object& constant = locs()->in(1).constant(); | 5983 const Object& constant = locs()->in(1).constant(); |
6242 ASSERT(constant.IsSmi()); | 5984 ASSERT(constant.IsSmi()); |
6243 const intptr_t shift_value = Smi::Cast(constant).Value(); | 5985 const intptr_t shift_value = Smi::Cast(constant).Value(); |
6244 | 5986 |
6245 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 5987 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6288 } | 6030 } |
6289 | 6031 |
6290 __ Bind(&zero); | 6032 __ Bind(&zero); |
6291 // Shift was greater than 31 bits, just return zero. | 6033 // Shift was greater than 31 bits, just return zero. |
6292 __ xorq(left, left); | 6034 __ xorq(left, left); |
6293 | 6035 |
6294 // Exit path. | 6036 // Exit path. |
6295 __ Bind(&done); | 6037 __ Bind(&done); |
6296 } | 6038 } |
6297 | 6039 |
6298 | |
6299 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6040 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6300 bool opt) const { | 6041 bool opt) const { |
6301 const intptr_t kNumInputs = 1; | 6042 const intptr_t kNumInputs = 1; |
6302 const intptr_t kNumTemps = 0; | 6043 const intptr_t kNumTemps = 0; |
6303 LocationSummary* summary = new (zone) | 6044 LocationSummary* summary = new (zone) |
6304 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6045 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6305 summary->set_in(0, Location::RequiresRegister()); | 6046 summary->set_in(0, Location::RequiresRegister()); |
6306 summary->set_out(0, Location::SameAsFirstInput()); | 6047 summary->set_out(0, Location::SameAsFirstInput()); |
6307 return summary; | 6048 return summary; |
6308 } | 6049 } |
6309 | 6050 |
6310 | |
6311 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6051 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6312 Register out = locs()->out(0).reg(); | 6052 Register out = locs()->out(0).reg(); |
6313 ASSERT(locs()->in(0).reg() == out); | 6053 ASSERT(locs()->in(0).reg() == out); |
6314 | 6054 |
6315 ASSERT(op_kind() == Token::kBIT_NOT); | 6055 ASSERT(op_kind() == Token::kBIT_NOT); |
6316 | 6056 |
6317 __ notl(out); | 6057 __ notl(out); |
6318 } | 6058 } |
6319 | 6059 |
6320 | |
6321 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 6060 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
6322 | 6061 |
6323 | |
6324 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6062 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
6325 bool opt) const { | 6063 bool opt) const { |
6326 const intptr_t kNumInputs = 1; | 6064 const intptr_t kNumInputs = 1; |
6327 const intptr_t kNumTemps = 0; | 6065 const intptr_t kNumTemps = 0; |
6328 LocationSummary* summary = new (zone) | 6066 LocationSummary* summary = new (zone) |
6329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6067 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6330 if (from() == kUnboxedMint) { | 6068 if (from() == kUnboxedMint) { |
6331 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6069 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
6332 summary->set_in(0, Location::RequiresRegister()); | 6070 summary->set_in(0, Location::RequiresRegister()); |
6333 summary->set_out(0, Location::SameAsFirstInput()); | 6071 summary->set_out(0, Location::SameAsFirstInput()); |
6334 } else if (to() == kUnboxedMint) { | 6072 } else if (to() == kUnboxedMint) { |
6335 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); | 6073 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
6336 summary->set_in(0, Location::RequiresRegister()); | 6074 summary->set_in(0, Location::RequiresRegister()); |
6337 summary->set_out(0, Location::SameAsFirstInput()); | 6075 summary->set_out(0, Location::SameAsFirstInput()); |
6338 } else { | 6076 } else { |
6339 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6077 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
6340 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6078 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
6341 summary->set_in(0, Location::RequiresRegister()); | 6079 summary->set_in(0, Location::RequiresRegister()); |
6342 summary->set_out(0, Location::SameAsFirstInput()); | 6080 summary->set_out(0, Location::SameAsFirstInput()); |
6343 } | 6081 } |
6344 return summary; | 6082 return summary; |
6345 } | 6083 } |
6346 | 6084 |
6347 | |
6348 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6085 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6349 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 6086 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
6350 const Register value = locs()->in(0).reg(); | 6087 const Register value = locs()->in(0).reg(); |
6351 const Register out = locs()->out(0).reg(); | 6088 const Register out = locs()->out(0).reg(); |
6352 // Representations are bitwise equivalent but we want to normalize | 6089 // Representations are bitwise equivalent but we want to normalize |
6353 // upperbits for safety reasons. | 6090 // upperbits for safety reasons. |
6354 // TODO(vegorov) if we ensure that we never use upperbits we could | 6091 // TODO(vegorov) if we ensure that we never use upperbits we could |
6355 // avoid this. | 6092 // avoid this. |
6356 __ movl(out, value); | 6093 __ movl(out, value); |
6357 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 6094 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6392 } else { | 6129 } else { |
6393 // Sign extend. | 6130 // Sign extend. |
6394 ASSERT(from() == kUnboxedInt32); | 6131 ASSERT(from() == kUnboxedInt32); |
6395 __ movsxd(out, value); | 6132 __ movsxd(out, value); |
6396 } | 6133 } |
6397 } else { | 6134 } else { |
6398 UNREACHABLE(); | 6135 UNREACHABLE(); |
6399 } | 6136 } |
6400 } | 6137 } |
6401 | 6138 |
6402 | |
6403 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6139 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6404 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6140 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6405 } | 6141 } |
6406 | 6142 |
6407 | |
6408 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6143 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6409 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 6144 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
6410 locs()); | 6145 locs()); |
6411 __ int3(); | 6146 __ int3(); |
6412 } | 6147 } |
6413 | 6148 |
6414 | |
6415 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6149 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6416 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6150 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6417 } | 6151 } |
6418 | 6152 |
6419 | |
6420 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6153 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6421 compiler->SetNeedsStackTrace(catch_try_index()); | 6154 compiler->SetNeedsStackTrace(catch_try_index()); |
6422 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 6155 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
6423 2, locs()); | 6156 2, locs()); |
6424 __ int3(); | 6157 __ int3(); |
6425 } | 6158 } |
6426 | 6159 |
6427 | |
6428 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6160 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6429 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6161 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6430 } | 6162 } |
6431 | 6163 |
6432 | |
6433 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6164 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6434 __ Stop(message()); | 6165 __ Stop(message()); |
6435 } | 6166 } |
6436 | 6167 |
6437 | |
6438 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6168 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6439 if (!compiler->CanFallThroughTo(normal_entry())) { | 6169 if (!compiler->CanFallThroughTo(normal_entry())) { |
6440 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6170 __ jmp(compiler->GetJumpLabel(normal_entry())); |
6441 } | 6171 } |
6442 } | 6172 } |
6443 | 6173 |
6444 | |
6445 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6174 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6446 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6175 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6447 } | 6176 } |
6448 | 6177 |
6449 | |
6450 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6178 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6451 if (!compiler->is_optimizing()) { | 6179 if (!compiler->is_optimizing()) { |
6452 if (FLAG_reorder_basic_blocks) { | 6180 if (FLAG_reorder_basic_blocks) { |
6453 compiler->EmitEdgeCounter(block()->preorder_number()); | 6181 compiler->EmitEdgeCounter(block()->preorder_number()); |
6454 } | 6182 } |
6455 // Add a deoptimization descriptor for deoptimizing instructions that | 6183 // Add a deoptimization descriptor for deoptimizing instructions that |
6456 // may be inserted before this instruction. | 6184 // may be inserted before this instruction. |
6457 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 6185 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
6458 TokenPosition::kNoSource); | 6186 TokenPosition::kNoSource); |
6459 } | 6187 } |
6460 if (HasParallelMove()) { | 6188 if (HasParallelMove()) { |
6461 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6189 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
6462 } | 6190 } |
6463 | 6191 |
6464 // We can fall through if the successor is the next block in the list. | 6192 // We can fall through if the successor is the next block in the list. |
6465 // Otherwise, we need a jump. | 6193 // Otherwise, we need a jump. |
6466 if (!compiler->CanFallThroughTo(successor())) { | 6194 if (!compiler->CanFallThroughTo(successor())) { |
6467 __ jmp(compiler->GetJumpLabel(successor())); | 6195 __ jmp(compiler->GetJumpLabel(successor())); |
6468 } | 6196 } |
6469 } | 6197 } |
6470 | 6198 |
6471 | |
6472 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6199 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
6473 bool opt) const { | 6200 bool opt) const { |
6474 const intptr_t kNumInputs = 1; | 6201 const intptr_t kNumInputs = 1; |
6475 const intptr_t kNumTemps = 1; | 6202 const intptr_t kNumTemps = 1; |
6476 | 6203 |
6477 LocationSummary* summary = new (zone) | 6204 LocationSummary* summary = new (zone) |
6478 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6205 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6479 | 6206 |
6480 summary->set_in(0, Location::RequiresRegister()); | 6207 summary->set_in(0, Location::RequiresRegister()); |
6481 summary->set_temp(0, Location::RequiresRegister()); | 6208 summary->set_temp(0, Location::RequiresRegister()); |
6482 | 6209 |
6483 return summary; | 6210 return summary; |
6484 } | 6211 } |
6485 | 6212 |
6486 | |
6487 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6213 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6488 Register offset_reg = locs()->in(0).reg(); | 6214 Register offset_reg = locs()->in(0).reg(); |
6489 Register target_address_reg = locs()->temp(0).reg(); | 6215 Register target_address_reg = locs()->temp(0).reg(); |
6490 | 6216 |
6491 { | 6217 { |
6492 const intptr_t kRIPRelativeLeaqSize = 7; | 6218 const intptr_t kRIPRelativeLeaqSize = 7; |
6493 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; | 6219 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; |
6494 __ leaq(target_address_reg, | 6220 __ leaq(target_address_reg, |
6495 Address::AddressRIPRelative(-entry_to_rip_offset)); | 6221 Address::AddressRIPRelative(-entry_to_rip_offset)); |
6496 ASSERT(__ CodeSize() == entry_to_rip_offset); | 6222 ASSERT(__ CodeSize() == entry_to_rip_offset); |
(...skipping 28 matching lines...) Expand all Loading... |
6525 locs->set_in(0, Location::RegisterOrConstant(left())); | 6251 locs->set_in(0, Location::RegisterOrConstant(left())); |
6526 // Only one of the inputs can be a constant. Choose register if the first one | 6252 // Only one of the inputs can be a constant. Choose register if the first one |
6527 // is a constant. | 6253 // is a constant. |
6528 locs->set_in(1, locs->in(0).IsConstant() | 6254 locs->set_in(1, locs->in(0).IsConstant() |
6529 ? Location::RequiresRegister() | 6255 ? Location::RequiresRegister() |
6530 : Location::RegisterOrConstant(right())); | 6256 : Location::RegisterOrConstant(right())); |
6531 locs->set_out(0, Location::RequiresRegister()); | 6257 locs->set_out(0, Location::RequiresRegister()); |
6532 return locs; | 6258 return locs; |
6533 } | 6259 } |
6534 | 6260 |
6535 | |
6536 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6261 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
6537 BranchLabels labels) { | 6262 BranchLabels labels) { |
6538 Location left = locs()->in(0); | 6263 Location left = locs()->in(0); |
6539 Location right = locs()->in(1); | 6264 Location right = locs()->in(1); |
6540 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6265 ASSERT(!left.IsConstant() || !right.IsConstant()); |
6541 Condition true_condition; | 6266 Condition true_condition; |
6542 if (left.IsConstant()) { | 6267 if (left.IsConstant()) { |
6543 true_condition = compiler->EmitEqualityRegConstCompare( | 6268 true_condition = compiler->EmitEqualityRegConstCompare( |
6544 right.reg(), left.constant(), needs_number_check(), token_pos(), | 6269 right.reg(), left.constant(), needs_number_check(), token_pos(), |
6545 deopt_id_); | 6270 deopt_id_); |
6546 } else if (right.IsConstant()) { | 6271 } else if (right.IsConstant()) { |
6547 true_condition = compiler->EmitEqualityRegConstCompare( | 6272 true_condition = compiler->EmitEqualityRegConstCompare( |
6548 left.reg(), right.constant(), needs_number_check(), token_pos(), | 6273 left.reg(), right.constant(), needs_number_check(), token_pos(), |
6549 deopt_id_); | 6274 deopt_id_); |
6550 } else { | 6275 } else { |
6551 true_condition = compiler->EmitEqualityRegRegCompare( | 6276 true_condition = compiler->EmitEqualityRegRegCompare( |
6552 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6277 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
6553 } | 6278 } |
6554 if (kind() != Token::kEQ_STRICT) { | 6279 if (kind() != Token::kEQ_STRICT) { |
6555 ASSERT(kind() == Token::kNE_STRICT); | 6280 ASSERT(kind() == Token::kNE_STRICT); |
6556 true_condition = NegateCondition(true_condition); | 6281 true_condition = NegateCondition(true_condition); |
6557 } | 6282 } |
6558 return true_condition; | 6283 return true_condition; |
6559 } | 6284 } |
6560 | 6285 |
6561 | |
6562 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6286 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
6563 bool opt) const { | 6287 bool opt) const { |
6564 const intptr_t kNumInputs = 1; | 6288 const intptr_t kNumInputs = 1; |
6565 const intptr_t kNumTemps = 0; | 6289 const intptr_t kNumTemps = 0; |
6566 LocationSummary* summary = new (zone) | 6290 LocationSummary* summary = new (zone) |
6567 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6291 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6568 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. | 6292 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. |
6569 summary->set_out(0, Location::RegisterLocation(RAX)); | 6293 summary->set_out(0, Location::RegisterLocation(RAX)); |
6570 return summary; | 6294 return summary; |
6571 } | 6295 } |
6572 | 6296 |
6573 | |
6574 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6297 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6575 // Arguments descriptor is expected in R10. | 6298 // Arguments descriptor is expected in R10. |
6576 const intptr_t argument_count = ArgumentCount(); // Includes type args. | 6299 const intptr_t argument_count = ArgumentCount(); // Includes type args. |
6577 const Array& arguments_descriptor = | 6300 const Array& arguments_descriptor = |
6578 Array::ZoneHandle(Z, GetArgumentsDescriptor()); | 6301 Array::ZoneHandle(Z, GetArgumentsDescriptor()); |
6579 __ LoadObject(R10, arguments_descriptor); | 6302 __ LoadObject(R10, arguments_descriptor); |
6580 | 6303 |
6581 // Function in RAX. | 6304 // Function in RAX. |
6582 ASSERT(locs()->in(0).reg() == RAX); | 6305 ASSERT(locs()->in(0).reg() == RAX); |
6583 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 6306 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
(...skipping 13 matching lines...) Expand all Loading... |
6597 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6320 compiler->AddDeoptIndexAtCall(deopt_id_after); |
6598 } | 6321 } |
6599 // Add deoptimization continuation point after the call and before the | 6322 // Add deoptimization continuation point after the call and before the |
6600 // arguments are removed. | 6323 // arguments are removed. |
6601 // In optimized code this descriptor is needed for exception handling. | 6324 // In optimized code this descriptor is needed for exception handling. |
6602 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 6325 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
6603 token_pos()); | 6326 token_pos()); |
6604 __ Drop(argument_count); | 6327 __ Drop(argument_count); |
6605 } | 6328 } |
6606 | 6329 |
6607 | |
6608 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6330 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
6609 bool opt) const { | 6331 bool opt) const { |
6610 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 6332 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
6611 LocationSummary::kNoCall); | 6333 LocationSummary::kNoCall); |
6612 } | 6334 } |
6613 | 6335 |
6614 | |
6615 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6336 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6616 Register value = locs()->in(0).reg(); | 6337 Register value = locs()->in(0).reg(); |
6617 Register result = locs()->out(0).reg(); | 6338 Register result = locs()->out(0).reg(); |
6618 | 6339 |
6619 Label done; | 6340 Label done; |
6620 __ LoadObject(result, Bool::True()); | 6341 __ LoadObject(result, Bool::True()); |
6621 __ CompareRegisters(result, value); | 6342 __ CompareRegisters(result, value); |
6622 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6343 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
6623 __ LoadObject(result, Bool::False()); | 6344 __ LoadObject(result, Bool::False()); |
6624 __ Bind(&done); | 6345 __ Bind(&done); |
6625 } | 6346 } |
6626 | 6347 |
6627 | |
6628 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6348 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
6629 bool opt) const { | 6349 bool opt) const { |
6630 return MakeCallSummary(zone); | 6350 return MakeCallSummary(zone); |
6631 } | 6351 } |
6632 | 6352 |
6633 | |
6634 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6353 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6635 const Code& stub = Code::ZoneHandle( | 6354 const Code& stub = Code::ZoneHandle( |
6636 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6355 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
6637 const StubEntry stub_entry(stub); | 6356 const StubEntry stub_entry(stub); |
6638 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 6357 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
6639 locs()); | 6358 locs()); |
6640 compiler->AddStubCallTarget(stub); | 6359 compiler->AddStubCallTarget(stub); |
6641 __ Drop(ArgumentCount()); // Discard arguments. | 6360 __ Drop(ArgumentCount()); // Discard arguments. |
6642 } | 6361 } |
6643 | 6362 |
6644 | |
6645 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6363 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6646 ASSERT(!compiler->is_optimizing()); | 6364 ASSERT(!compiler->is_optimizing()); |
6647 __ CallPatchable(*StubCode::DebugStepCheck_entry()); | 6365 __ CallPatchable(*StubCode::DebugStepCheck_entry()); |
6648 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); | 6366 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); |
6649 compiler->RecordSafepoint(locs()); | 6367 compiler->RecordSafepoint(locs()); |
6650 } | 6368 } |
6651 | 6369 |
6652 | |
6653 } // namespace dart | 6370 } // namespace dart |
6654 | 6371 |
6655 #undef __ | 6372 #undef __ |
6656 | 6373 |
6657 #endif // defined TARGET_ARCH_X64 | 6374 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |