Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/intermediate_language_test.cc ('k') | runtime/vm/intrinsifier.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_test.cc ('k') | runtime/vm/intrinsifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698